mirror of
https://github.com/tendermint/tendermint.git
synced 2026-09-10 01:56:08 +00:00
bring back EventSubscriber
This commit is contained in:
@@ -59,14 +59,12 @@ func WaitForOneEvent(c EventsClient, evtTyp string, timeout time.Duration) (type
|
||||
const subscriber = "helpers"
|
||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
||||
defer cancel()
|
||||
evts := make(chan interface{}, 1)
|
||||
|
||||
// register for the next event of this type
|
||||
sub, err := c.Subscribe(ctx, subscriber, types.QueryForEvent(evtTyp))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to subscribe")
|
||||
}
|
||||
|
||||
// make sure to unregister after the test is over
|
||||
defer c.UnsubscribeAll(ctx, subscriber)
|
||||
|
||||
|
||||
+51
-14
@@ -249,6 +249,28 @@ func (c *HTTP) Validators(height *int64) (*ctypes.ResultValidators, error) {
|
||||
|
||||
/** websocket event stuff here... **/
|
||||
|
||||
type subscription struct {
|
||||
out chan tmpubsub.Message
|
||||
cancelled chan struct{}
|
||||
|
||||
mtx sync.RWMutex
|
||||
err error
|
||||
}
|
||||
|
||||
func (s *subscription) Out() <-chan tmpubsub.Message {
|
||||
return s.out
|
||||
}
|
||||
|
||||
func (s *subscription) Cancelled() <-chan struct{} {
|
||||
return s.cancelled
|
||||
}
|
||||
|
||||
func (s *subscription) Err() error {
|
||||
s.mtx.RLock()
|
||||
defer s.mtx.RUnlock()
|
||||
return s.err
|
||||
}
|
||||
|
||||
type WSEvents struct {
|
||||
cmn.BaseService
|
||||
cdc *amino.Codec
|
||||
@@ -256,8 +278,9 @@ type WSEvents struct {
|
||||
endpoint string
|
||||
ws *rpcclient.WSClient
|
||||
|
||||
mtx sync.RWMutex
|
||||
subscriptions map[string]chan<- EventMessage
|
||||
mtx sync.RWMutex
|
||||
// query -> subscription
|
||||
subscriptions map[string]*subscription
|
||||
}
|
||||
|
||||
func newWSEvents(cdc *amino.Codec, remote, endpoint string) *WSEvents {
|
||||
@@ -265,7 +288,7 @@ func newWSEvents(cdc *amino.Codec, remote, endpoint string) *WSEvents {
|
||||
cdc: cdc,
|
||||
endpoint: endpoint,
|
||||
remote: remote,
|
||||
subscriptions: make(map[string]chan<- EventMessage),
|
||||
subscriptions: make(map[string]*subscription),
|
||||
}
|
||||
|
||||
wsEvents.BaseService = *cmn.NewBaseService(nil, "WSEvents", wsEvents)
|
||||
@@ -295,21 +318,29 @@ func (w *WSEvents) OnStop() {
|
||||
}
|
||||
}
|
||||
|
||||
func (w *WSEvents) Subscribe(ctx context.Context, subscriber string, query tmpubsub.Query, out chan<- interface{}) error {
|
||||
func (w *WSEvents) Subscribe(ctx context.Context, subscriber string, query tmpubsub.Query, outCapacity ...int) (types.Subscription, error) {
|
||||
q := query.String()
|
||||
|
||||
err := w.ws.Subscribe(ctx, q)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
outCap := 1
|
||||
if len(outCapacity) > 0 && outCapacity[0] >= 0 {
|
||||
outCap = outCapacity[0]
|
||||
}
|
||||
|
||||
w.mtx.Lock()
|
||||
// subscriber param is ignored because Tendermint will override it with
|
||||
// remote IP anyway.
|
||||
w.subscriptions[q] = out
|
||||
w.subscriptions[q] = &subscription{
|
||||
out: make(chan tmpubsub.Message, outCap),
|
||||
cancelled: make(chan struct{}),
|
||||
}
|
||||
w.mtx.Unlock()
|
||||
|
||||
return nil
|
||||
return w.subscriptions[q], nil
|
||||
}
|
||||
|
||||
func (w *WSEvents) Unsubscribe(ctx context.Context, subscriber string, query tmpubsub.Query) error {
|
||||
@@ -321,9 +352,12 @@ func (w *WSEvents) Unsubscribe(ctx context.Context, subscriber string, query tmp
|
||||
}
|
||||
|
||||
w.mtx.Lock()
|
||||
ch, ok := w.subscriptions[q]
|
||||
sub, ok := w.subscriptions[q]
|
||||
if ok {
|
||||
close(ch)
|
||||
close(sub.cancelled)
|
||||
sub.mtx.Lock()
|
||||
sub.err = errors.New("unsubscribed")
|
||||
sub.mtx.Unlock()
|
||||
delete(w.subscriptions, q)
|
||||
}
|
||||
w.mtx.Unlock()
|
||||
@@ -338,10 +372,13 @@ func (w *WSEvents) UnsubscribeAll(ctx context.Context, subscriber string) error
|
||||
}
|
||||
|
||||
w.mtx.Lock()
|
||||
for _, ch := range w.subscriptions {
|
||||
close(ch)
|
||||
for _, sub := range w.subscriptions {
|
||||
close(sub.cancelled)
|
||||
sub.mtx.Lock()
|
||||
sub.err = errors.New("unsubscribed")
|
||||
sub.mtx.Unlock()
|
||||
}
|
||||
w.subscriptions = make(map[string]chan<- EventMessage)
|
||||
w.subscriptions = make(map[string]*subscription)
|
||||
w.mtx.Unlock()
|
||||
|
||||
return nil
|
||||
@@ -381,8 +418,8 @@ func (w *WSEvents) eventListener() {
|
||||
// NOTE: writing also happens inside mutex so we can't close a channel in
|
||||
// Unsubscribe/UnsubscribeAll.
|
||||
w.mtx.RLock()
|
||||
if ch, ok := w.subscriptions[result.Query]; ok {
|
||||
ch <- EventMessage{result.Data, result.Tags}
|
||||
if sub, ok := w.subscriptions[result.Query]; ok {
|
||||
sub.out <- tmpubsub.NewMessage(result.Data, result.Tags)
|
||||
}
|
||||
w.mtx.RUnlock()
|
||||
case <-w.Quit():
|
||||
|
||||
@@ -21,10 +21,7 @@ implementation.
|
||||
*/
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
cmn "github.com/tendermint/tendermint/libs/common"
|
||||
tmpubsub "github.com/tendermint/tendermint/libs/pubsub"
|
||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
@@ -94,9 +91,7 @@ type NetworkClient interface {
|
||||
// EventsClient is reactive, you can subscribe to any message, given the proper
|
||||
// string. see tendermint/types/events.go
|
||||
type EventsClient interface {
|
||||
Subscribe(ctx context.Context, subscriber string, query tmpubsub.Query, out chan<- interface{}) error
|
||||
Unsubscribe(ctx context.Context, subscriber string, query tmpubsub.Query) error
|
||||
UnsubscribeAll(ctx context.Context, subscriber string) error
|
||||
types.EventBusSubscriber
|
||||
}
|
||||
|
||||
// MempoolClient shows us data about current mempool state.
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package client
|
||||
|
||||
import "github.com/tendermint/tendermint/types"
|
||||
|
||||
// ABCIQueryOptions can be used to provide options for ABCIQuery call other
|
||||
// than the DefaultABCIQueryOptions.
|
||||
type ABCIQueryOptions struct {
|
||||
@@ -11,9 +9,3 @@ type ABCIQueryOptions struct {
|
||||
|
||||
// DefaultABCIQueryOptions are latest height (0) and prove false.
|
||||
var DefaultABCIQueryOptions = ABCIQueryOptions{Height: 0, Prove: false}
|
||||
|
||||
// EventMessage combines event data and tags.
|
||||
type EventMessage struct {
|
||||
Data types.TMEventData
|
||||
Tags map[string]string
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user