mirror of
https://github.com/tendermint/tendermint.git
synced 2026-08-20 22:26:15 +00:00
+29
-9
@@ -52,7 +52,13 @@ type wsEvents struct {
|
||||
ws *jsonrpcclient.WSClient
|
||||
|
||||
mtx tmsync.RWMutex
|
||||
subscriptions map[string]chan ctypes.ResultEvent // query -> chan
|
||||
subscriptions map[string]*wsSubscription
|
||||
}
|
||||
|
||||
type wsSubscription struct {
|
||||
res chan ctypes.ResultEvent
|
||||
id string
|
||||
query string
|
||||
}
|
||||
|
||||
var _ rpcclient.EventsClient = (*wsEvents)(nil)
|
||||
@@ -70,7 +76,7 @@ func newWsEvents(remote string, wso WSOptions) (*wsEvents, error) {
|
||||
}
|
||||
|
||||
w := &wsEvents{
|
||||
subscriptions: make(map[string]chan ctypes.ResultEvent),
|
||||
subscriptions: make(map[string]*wsSubscription),
|
||||
}
|
||||
w.BaseService = *service.NewBaseService(nil, "wsEvents", w)
|
||||
|
||||
@@ -136,10 +142,10 @@ func (w *wsEvents) Subscribe(ctx context.Context, subscriber, query string,
|
||||
|
||||
outc := make(chan ctypes.ResultEvent, outCap)
|
||||
w.mtx.Lock()
|
||||
defer w.mtx.Unlock()
|
||||
// subscriber param is ignored because Tendermint will override it with
|
||||
// remote IP anyway.
|
||||
w.subscriptions[query] = outc
|
||||
w.mtx.Unlock()
|
||||
w.subscriptions[query] = &wsSubscription{res: outc, query: query}
|
||||
|
||||
return outc, nil
|
||||
}
|
||||
@@ -158,9 +164,12 @@ func (w *wsEvents) Unsubscribe(ctx context.Context, subscriber, query string) er
|
||||
}
|
||||
|
||||
w.mtx.Lock()
|
||||
_, ok := w.subscriptions[query]
|
||||
info, ok := w.subscriptions[query]
|
||||
if ok {
|
||||
delete(w.subscriptions, query)
|
||||
if info.id != "" {
|
||||
delete(w.subscriptions, info.id)
|
||||
}
|
||||
delete(w.subscriptions, info.query)
|
||||
}
|
||||
w.mtx.Unlock()
|
||||
|
||||
@@ -181,7 +190,7 @@ func (w *wsEvents) UnsubscribeAll(ctx context.Context, subscriber string) error
|
||||
}
|
||||
|
||||
w.mtx.Lock()
|
||||
w.subscriptions = make(map[string]chan ctypes.ResultEvent)
|
||||
w.subscriptions = make(map[string]*wsSubscription)
|
||||
w.mtx.Unlock()
|
||||
|
||||
return nil
|
||||
@@ -196,7 +205,11 @@ func (w *wsEvents) redoSubscriptionsAfter(d time.Duration) {
|
||||
|
||||
w.mtx.Lock()
|
||||
defer w.mtx.Unlock()
|
||||
for q := range w.subscriptions {
|
||||
|
||||
for q, info := range w.subscriptions {
|
||||
if q != "" && q == info.id {
|
||||
continue
|
||||
}
|
||||
err := w.ws.Subscribe(ctx, q)
|
||||
if err != nil {
|
||||
w.Logger.Error("failed to resubscribe", "query", q, "err", err)
|
||||
@@ -240,10 +253,17 @@ func (w *wsEvents) eventListener() {
|
||||
|
||||
w.mtx.RLock()
|
||||
out, ok := w.subscriptions[result.Query]
|
||||
if ok {
|
||||
if _, idOk := w.subscriptions[result.SubscriptionID]; !idOk {
|
||||
out.id = result.SubscriptionID
|
||||
w.subscriptions[result.SubscriptionID] = out
|
||||
}
|
||||
}
|
||||
|
||||
w.mtx.RUnlock()
|
||||
if ok {
|
||||
select {
|
||||
case out <- *result:
|
||||
case out.res <- *result:
|
||||
case <-w.Quit():
|
||||
return
|
||||
}
|
||||
|
||||
@@ -248,7 +248,13 @@ func (c *Local) eventsRoutine(
|
||||
for {
|
||||
select {
|
||||
case msg := <-sub.Out():
|
||||
result := ctypes.ResultEvent{Query: q.String(), Data: msg.Data(), Events: msg.Events()}
|
||||
result := ctypes.ResultEvent{
|
||||
SubscriptionID: msg.SubscriptionID(),
|
||||
Query: q.String(),
|
||||
Data: msg.Data(),
|
||||
Events: msg.Events(),
|
||||
}
|
||||
|
||||
if cap(outc) == 0 {
|
||||
outc <- result
|
||||
} else {
|
||||
@@ -293,11 +299,18 @@ func (c *Local) resubscribe(subscriber string, q tmpubsub.Query) types.Subscript
|
||||
}
|
||||
|
||||
func (c *Local) Unsubscribe(ctx context.Context, subscriber, query string) error {
|
||||
q, err := tmquery.New(query)
|
||||
args := tmpubsub.UnsubscribeArgs{Subscriber: subscriber}
|
||||
var err error
|
||||
args.Query, err = tmquery.New(query)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse query: %w", err)
|
||||
// if this isn't a valid query it might be an ID, so
|
||||
// we'll try that. It'll turn into an error when we
|
||||
// try to unsubscribe. Eventually, perhaps, we'll want
|
||||
// to change the interface to only allow
|
||||
// unsubscription by ID, but that's a larger change.
|
||||
args.ID = query
|
||||
}
|
||||
return c.EventBus.Unsubscribe(ctx, subscriber, q)
|
||||
return c.EventBus.Unsubscribe(ctx, args)
|
||||
}
|
||||
|
||||
func (c *Local) UnsubscribeAll(ctx context.Context, subscriber string) error {
|
||||
|
||||
+10
-6
@@ -86,13 +86,17 @@ func (env *Environment) Subscribe(ctx *rpctypes.Context, query string) (*ctypes.
|
||||
// Unsubscribe from events via WebSocket.
|
||||
// More: https://docs.tendermint.com/master/rpc/#/Websocket/unsubscribe
|
||||
func (env *Environment) Unsubscribe(ctx *rpctypes.Context, query string) (*ctypes.ResultUnsubscribe, error) {
|
||||
addr := ctx.RemoteAddr()
|
||||
env.Logger.Info("Unsubscribe from query", "remote", addr, "query", query)
|
||||
q, err := tmquery.New(query)
|
||||
args := tmpubsub.UnsubscribeArgs{Subscriber: ctx.RemoteAddr()}
|
||||
env.Logger.Info("Unsubscribe from query", "remote", args.Subscriber, "subscription", query)
|
||||
|
||||
var err error
|
||||
args.Query, err = tmquery.New(query)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse query: %w", err)
|
||||
args.ID = query
|
||||
}
|
||||
err = env.EventBus.Unsubscribe(context.Background(), addr, q)
|
||||
|
||||
err = env.EventBus.Unsubscribe(ctx.Context(), args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -104,7 +108,7 @@ func (env *Environment) Unsubscribe(ctx *rpctypes.Context, query string) (*ctype
|
||||
func (env *Environment) UnsubscribeAll(ctx *rpctypes.Context) (*ctypes.ResultUnsubscribe, error) {
|
||||
addr := ctx.RemoteAddr()
|
||||
env.Logger.Info("Unsubscribe from all", "remote", addr)
|
||||
err := env.EventBus.UnsubscribeAll(context.Background(), addr)
|
||||
err := env.EventBus.UnsubscribeAll(ctx.Context(), addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
+3
-1
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
mempl "github.com/tendermint/tendermint/internal/mempool"
|
||||
tmpubsub "github.com/tendermint/tendermint/libs/pubsub"
|
||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
@@ -77,7 +78,8 @@ func (env *Environment) BroadcastTxCommit(ctx *rpctypes.Context, tx types.Tx) (*
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
if err := env.EventBus.Unsubscribe(context.Background(), subscriber, q); err != nil {
|
||||
args := tmpubsub.UnsubscribeArgs{Subscriber: subscriber, Query: q}
|
||||
if err := env.EventBus.Unsubscribe(context.Background(), args); err != nil {
|
||||
env.Logger.Error("Error unsubscribing from eventBus", "err", err)
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -258,7 +258,8 @@ type (
|
||||
|
||||
// Event data from a subscription
|
||||
type ResultEvent struct {
|
||||
Query string `json:"query"`
|
||||
Data types.TMEventData `json:"data"`
|
||||
Events map[string][]string `json:"events"`
|
||||
SubscriptionID string `json:"subscription_id"`
|
||||
Query string `json:"query"`
|
||||
Data types.TMEventData `json:"data"`
|
||||
Events map[string][]string `json:"events"`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user