backport: add event subscription options and defaults config (#7930) (#9491)

* config: add event subscription options and defaults (#7930)

* Apply suggestions from code review

Co-authored-by: M. J. Fromberger <fromberger@interchain.io>
This commit is contained in:
mmsqe
2022-09-28 16:27:19 +02:00
committed by GitHub
co-authored by M. J. Fromberger
parent f1a57adee4
commit 069e402aa1
4 changed files with 89 additions and 19 deletions
+1
View File
@@ -36,6 +36,7 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi
### BREAKING CHANGES
- CLI/RPC/Config
- [config] \#9491 Add new event subscription options and defaults. (@creachadair)
- [config] \#9259 Rename the fastsync section and the fast_sync key blocksync and block_sync respectively
- Apps
+43 -5
View File
@@ -382,6 +382,33 @@ type RPCConfig struct {
// predictability in subscription behavior.
CloseOnSlowClient bool `mapstructure:"experimental_close_on_slow_client"`
// If true, disable the websocket interface to the RPC service. This has
// the effect of disabling the /subscribe, /unsubscribe, and /unsubscribe_all
// methods for event subscription.
//
// EXPERIMENTAL: This setting will be removed in Tendermint v0.37.
ExperimentalDisableWebsocket bool `mapstructure:"experimental-disable-websocket"`
// The time window size for the event log. All events up to this long before
// the latest (up to EventLogMaxItems) will be available for subscribers to
// fetch via the /events method. If 0 (the default) the event log and the
// /events RPC method are disabled.
EventLogWindowSize time.Duration `mapstructure:"event-log-window-size"`
// The maxiumum number of events that may be retained by the event log. If
// this value is 0, no upper limit is set. Otherwise, items in excess of
// this number will be discarded from the event log.
//
// Warning: This setting is a safety valve. Setting it too low may cause
// subscribers to miss events. Try to choose a value higher than the
// maximum worst-case expected event load within the chosen window size in
// ordinary operation.
//
// For example, if the window size is 10 minutes and the node typically
// averages 1000 events per ten minutes, but with occasional known spikes of
// up to 2000, choose a value > 2000.
EventLogMaxItems int `mapstructure:"event-log-max-items"`
// How long to wait for a tx to be committed during /broadcast_tx_commit
// WARNING: Using a value larger than 10s will result in increasing the
// global HTTP write timeout, which applies to all connections and endpoints.
@@ -429,11 +456,16 @@ func DefaultRPCConfig() *RPCConfig {
Unsafe: false,
MaxOpenConnections: 900,
MaxSubscriptionClients: 100,
MaxSubscriptionsPerClient: 5,
SubscriptionBufferSize: defaultSubscriptionBufferSize,
TimeoutBroadcastTxCommit: 10 * time.Second,
WebSocketWriteBufferSize: defaultSubscriptionBufferSize,
SubscriptionBufferSize: defaultSubscriptionBufferSize,
WebSocketWriteBufferSize: defaultSubscriptionBufferSize,
// Settings for event subscription.
MaxSubscriptionClients: 100,
MaxSubscriptionsPerClient: 5,
ExperimentalDisableWebsocket: false, // compatible with TM v0.35 and earlier
EventLogWindowSize: 0, // disables /events RPC by default
EventLogMaxItems: 0,
TimeoutBroadcastTxCommit: 10 * time.Second,
MaxBodyBytes: int64(1000000), // 1MB
MaxHeaderBytes: 1 << 20, // same as the net/http default
@@ -479,6 +511,12 @@ func (cfg *RPCConfig) ValidateBasic() error {
cfg.SubscriptionBufferSize,
)
}
if cfg.EventLogWindowSize < 0 {
return errors.New("event-log-window-size must not be negative")
}
if cfg.EventLogMaxItems < 0 {
return errors.New("event-log-max-items must not be negative")
}
if cfg.TimeoutBroadcastTxCommit < 0 {
return errors.New("timeout_broadcast_tx_commit can't be negative")
}
+27
View File
@@ -233,6 +233,33 @@ experimental_websocket_write_buffer_size = {{ .RPC.WebSocketWriteBufferSize }}
# predictability in subscription behavior.
experimental_close_on_slow_client = {{ .RPC.CloseOnSlowClient }}
# If true, disable the websocket interface to the RPC service. This has
# the effect of disabling the /subscribe, /unsubscribe, and /unsubscribe_all
# methods for event subscription.
#
# EXPERIMENTAL: This setting will be removed in Tendermint v0.37.
experimental-disable-websocket = {{ .RPC.ExperimentalDisableWebsocket }}
# The time window size for the event log. All events up to this long before
# the latest (up to EventLogMaxItems) will be available for subscribers to
# fetch via the /events method. If 0 (the default) the event log and the
# /events RPC method are disabled.
event-log-window-size = "{{ .RPC.EventLogWindowSize }}"
# The maxiumum number of events that may be retained by the event log. If
# this value is 0, no upper limit is set. Otherwise, items in excess of
# this number will be discarded from the event log.
#
# Warning: This setting is a safety valve. Setting it too low may cause
# subscribers to miss events. Try to choose a value higher than the
# maximum worst-case expected event load within the chosen window size in
# ordinary operation.
#
# For example, if the window size is 10 minutes and the node typically
# averages 1000 events per ten minutes, but with occasional known spikes of
# up to 2000, choose a value > 2000.
event-log-max-items = {{ .RPC.EventLogMaxItems }}
# How long to wait for a tx to be committed during /broadcast_tx_commit.
# WARNING: Using a value larger than 10s will result in increasing the
# global HTTP write timeout, which applies to all connections and endpoints.
+18 -14
View File
@@ -1116,25 +1116,29 @@ func (n *Node) startRPC() ([]net.Listener, error) {
config.WriteTimeout = n.config.RPC.TimeoutBroadcastTxCommit + 1*time.Second
}
// we may expose the rpc over both a unix and tcp socket
// We may expose the RPC over both TCP and a Unix-domain socket.
listeners := make([]net.Listener, len(listenAddrs))
for i, listenAddr := range listenAddrs {
mux := http.NewServeMux()
rpcLogger := n.Logger.With("module", "rpc-server")
wmLogger := rpcLogger.With("protocol", "websocket")
wm := rpcserver.NewWebsocketManager(rpccore.Routes,
rpcserver.OnDisconnect(func(remoteAddr string) {
err := n.eventBus.UnsubscribeAll(context.Background(), remoteAddr)
if err != nil && err != tmpubsub.ErrSubscriptionNotFound {
wmLogger.Error("Failed to unsubscribe addr from events", "addr", remoteAddr, "err", err)
}
}),
rpcserver.ReadLimit(config.MaxBodyBytes),
rpcserver.WriteChanCapacity(n.config.RPC.WebSocketWriteBufferSize),
)
wm.SetLogger(wmLogger)
mux.HandleFunc("/websocket", wm.WebsocketHandler)
rpcserver.RegisterRPCFuncs(mux, rpccore.Routes, rpcLogger)
if n.config.RPC.ExperimentalDisableWebsocket {
rpcLogger.Info("Disabling websocket endpoints (experimental-disable-websocket=true)")
} else {
wmLogger := rpcLogger.With("protocol", "websocket")
wm := rpcserver.NewWebsocketManager(rpccore.Routes,
rpcserver.OnDisconnect(func(remoteAddr string) {
err := n.eventBus.UnsubscribeAll(context.Background(), remoteAddr)
if err != nil && err != tmpubsub.ErrSubscriptionNotFound {
wmLogger.Error("Failed to unsubscribe addr from events", "addr", remoteAddr, "err", err)
}
}),
rpcserver.ReadLimit(config.MaxBodyBytes),
rpcserver.WriteChanCapacity(n.config.RPC.WebSocketWriteBufferSize),
)
wm.SetLogger(wmLogger)
mux.HandleFunc("/websocket", wm.WebsocketHandler)
}
listener, err := rpcserver.Listen(
listenAddr,
config,