rpc: Add experimental config params to allow for subscription buffer size control (tm v0.34.x) (#7230)

A workaround for #6729. Add parameters to control buffer sizes for
event subscription RPC clients. On some networks, buffering causes
clients to be dropped and/or events to be lost.

For additional context, see the discussion on #7188.

- Add experimental_subscription_buffer_size config parameter
- Add experimental_websocket_write_buffer_size config parameter
- Add experimental_close_on_slow_client config parameter

Co-authored-by: M. J. Fromberger <fromberger@interchain.io>
This commit is contained in:
Thane Thomson
2021-11-09 15:35:45 -05:00
committed by GitHub
parent 9ec863f948
commit 12e3419f2b
17 changed files with 101 additions and 10 deletions

View File

@@ -2,6 +2,7 @@ package core
import (
"context"
"errors"
"fmt"
"time"
@@ -11,11 +12,6 @@ import (
rpctypes "github.com/tendermint/tendermint/rpc/jsonrpc/types"
)
const (
// Buffer on the Tendermint (server) side to allow some slowness in clients.
subBufferSize = 100
)
// Subscribe for events via WebSocket.
// More: https://docs.tendermint.com/master/rpc/#/Websocket/subscribe
func Subscribe(ctx *rpctypes.Context, query string) (*ctypes.ResultSubscribe, error) {
@@ -37,11 +33,13 @@ func Subscribe(ctx *rpctypes.Context, query string) (*ctypes.ResultSubscribe, er
subCtx, cancel := context.WithTimeout(ctx.Context(), SubscribeTimeout)
defer cancel()
sub, err := env.EventBus.Subscribe(subCtx, addr, q, subBufferSize)
sub, err := env.EventBus.Subscribe(subCtx, addr, q, env.Config.SubscriptionBufferSize)
if err != nil {
return nil, err
}
closeIfSlow := env.Config.CloseOnSlowClient
// Capture the current ID, since it can change in the future.
subscriptionID := ctx.JSONReq.ID
go func() {
@@ -57,6 +55,18 @@ func Subscribe(ctx *rpctypes.Context, query string) (*ctypes.ResultSubscribe, er
if err := ctx.WSConn.WriteRPCResponse(writeCtx, resp); err != nil {
env.Logger.Info("Can't write response (slow client)",
"to", addr, "subscriptionID", subscriptionID, "err", err)
if closeIfSlow {
var (
err = errors.New("subscription was cancelled (reason: slow client)")
resp = rpctypes.RPCServerError(subscriptionID, err)
)
if !ctx.WSConn.TryWriteRPCResponse(resp) {
env.Logger.Info("Can't write response (slow client)",
"to", addr, "subscriptionID", subscriptionID, "err", err)
}
return
}
}
case <-sub.Cancelled():
if sub.Err() != tmpubsub.ErrUnsubscribed {
@@ -70,7 +80,7 @@ func Subscribe(ctx *rpctypes.Context, query string) (*ctypes.ResultSubscribe, er
err = fmt.Errorf("subscription was cancelled (reason: %s)", reason)
resp = rpctypes.RPCServerError(subscriptionID, err)
)
if ok := ctx.WSConn.TryWriteRPCResponse(resp); !ok {
if !ctx.WSConn.TryWriteRPCResponse(resp) {
env.Logger.Info("Can't write response (slow client)",
"to", addr, "subscriptionID", subscriptionID, "err", err)
}