Skip to main content

Gateway and events

Client combines discovery, REST, resource helpers, and the gateway. Use GatewayClient directly when you only need the WebSocket connection; it takes url and a raw token and emits the lower-level gateway events.

Subscribe to events

on() returns an unsubscribe function:
Use messageCreate for a wrapped Message. messageUpdate is a partial payload with id and channel_id; messageDelete contains IDs. Fetch a message if an update handler needs fields that were not included in the update. For other gateway events, onDispatch() gives typed data for a named dispatch:
The dispatch event exposes the frame itself: { op, t, s, d }. Its data is unknown; narrow it before using it. Known names and payload types live in gateway-types.ts. Listeners run in registration order, but their returned promises are not awaited. Async handlers can overlap, and a slow handler does not hold back the next dispatch. Thrown errors and rejected promises are forwarded to error. Register an error listener so you can see them.

Wait for a response

Register the wait before sending the prompt so a fast answer is not missed:
waitFor() rejects on timeout or cancellation and removes its listener. A predicate that throws also rejects the wait. To collect several events, use the bounded iterator:
A collector timeout ends iteration normally. Cancellation, a throwing filter, and buffer overflow reject. Breaking the loop removes the listener. The default buffer holds 100 events; this is a bound on unread events, not gateway traffic.

Reconnection

The gateway manages heartbeats and reconnects after recoverable interruptions. It attempts Resume when it has a usable session and sequence, and falls back to Identify when the session cannot be resumed. A new session emits ready; a successful Resume emits resumed. Reconnect delays grow exponentially and use jitter. The attempt counter resets when the gateway becomes ready. Fatal protocol/authentication close codes and an exhausted reconnect budget end the connection. Observe state for lifecycle changes, reconnect for { attempt, delayMs }, heartbeat for { latencyMs }, and close for the server’s code and reason. If state becomes closed, the client clears its current user and caches. The signal passed to connect() only applies during startup. Use disconnect() to stop an established client. Rotating credentials with client.updateToken() updates REST and future gateway authentication; it does not reconnect an existing socket by itself.

Persist work before advancing the sequence

Use gateway.processDispatch when Resume should reflect work saved to durable storage. Talos awaits this hook in dispatch order, then advances the sequence and emits the ordinary dispatch event. Ordinary listeners do not provide that ordering.
Implement put() as an idempotent write keyed by the message ID, then process saved work separately. If the hook rejects, Talos reports the error and restarts the connection. If Resume succeeds, unfinished dispatches can be replayed. Duplicates are possible; this is not an exactly-once delivery guarantee, and a session that cannot resume can leave gaps. maxPendingDispatches defaults to 1,000. Filling the queue causes a gateway failure. Honor the hook’s signal so interrupted connections do not leave work running indefinitely. ready and resumed are lifecycle events and can fire before their dispatch has completed this hook.

Shards and workers

ShardManager from talos-fluxer/shards reads /gateway/bot, creates clients, and coordinates startup. Its clients share a REST rate-limit store and an Identify limiter. count can override the recommended shard count. For worker threads, see the parent and the worker. They use WorkerSupervisor and share REST rate limits over IPC. Deployments with multiple managers or processes also need to coordinate Identify through identifyLimiter or gateway.beforeIdentify.