Repository navigation
This release makes the server release sockets and shut down reliably when handlers, hooks, clients or Redis misbehave. It also fixes client channels after disconnect(), presence after slow join hooks, and how oversized messages are handled. Upgrading is recommended for every application, especially those using a Redis transport.
Behavior changes
- A closed socket is released immediately. Before, a handler or
onLeavethat never settled kept the socket counted, subscribed and present forever, anddisconnectnever fired. Now the socket leaves its channels and presence as soon as it closes,disconnectis emitted, and the leave hooks run on the next turn without blocking the release. As a result,disconnectnow fires beforeonLeavefinishes. Messages still queued for a closed socket are dropped. - Oversized outbound messages no longer close recipients. A message over
maxOutboundPayloadused to close each recipient with1009, so a large broadcast kicked every subscriber. It is now dropped with a single warning, and the connections stay open. An oversized acknowledgement is replaced by an error,Response too big, so the client request rejects at once. The connection is still closed with1009only when even that error does not fit, which takes a very long request id. - Presence is announced after the join hooks. A presence subscription now takes a fresh snapshot after
onMemberJoinandonJoin, so a member who left during a slowonJoinis no longer re-added. With a transport, a presence subscribe now waits up to twicepresenceTimeout.
Shutdown
close()waits up toshutdownTimeoutfor pending hooks and handlers, including those of sockets that closed just before shutdown, then returns even if some never settle. A hook that is still running, for example on a timer, can keep the process alive until it ends.- Broadcasts made while the bus is closing are dropped instead of making the Redis disconnect fail. Before, a SIGTERM could exit with code 1.
- Slow consumers over
maxBufferedAmountare terminated if they ignore the close handshake, instead of being kept for 30 seconds. - An invalid retry queue option now fails before any Redis connection opens. Before, boot failed and the process stayed alive after SIGTERM.
Redis and the retry queue
@boringnode/busis now^0.10.0. The retry queue now drains as soon as Redis is back, even whenretryIntervalis not set. A duplicate publication no longer evicts an unrelated queued message. ioredis no longer prints "Unhandled error event" during an outage.retryQueue: { maxSize: undefined }keeps the default limit of 1000 instead of making the queue unbounded.- A zero
retryIntervalsuch as'0ms'disables the interval likefalseinstead of failing boot. - The README now explains what happens during a Redis outage. With ioredis defaults, publications wait in its offline buffer and are delivered after the reconnect. Events replayed after a full Redis restart can be lost.
If you use pnpm or another package manager that does not hoist dependencies, install @boringnode/bus next to ioredis. Your config imports the transport from it:
pnpm add @boringnode/bus@^0.10.0 ioredisClient
disconnect()no longer leaves stale channel instances behind. Unsubscribed channels are evicted, sosocket.channel(name)returns a fresh instance after reconnecting, and handlers registered on it fire again.- Channels held by a React or Vue hook keep their
listen(), whisper and presence callbacks acrossdisconnect()and resubscribe on the next connection. Don't callsubscribe()orunsubscribe()directly on a channel an adapter holds; remove your own handlers withstopListening()andstopListeningForWhisper(). useChannelEvent(React and Vue) now infers the handler payload from the event name. It used to be the union of every event of the channel.
Types and dependencies
@types/wsis now a dependency. Before, consumers withskipLibCheckoff got TS7016, and with it on the raw connection was typed asany.- The optional
@opentelemetry/instrumentationpeer now accepts>=0.200.0 <1.0.0. It can be installed next to@adonisjs/otel. - Our declarations no longer require
ioredisandmqttto type-check withskipLibCheckoff.
Known issue
With a Redis transport and the AdonisJS pino logger running in a worker transport, SIGTERM can occasionally leave the process running. This comes from pino's thread-stream and not from this package. Using a synchronous logger destination in production avoids it.