Connection Handling
Purpose
Connection Handling addresses the critical challenge of managing individual WebSocket client connections within the broader real-time blockchain event subscription system. It ensures that each client can reliably establish, maintain, and terminate WebSocket connections while managing their subscription lifecycle and communication. This subtopic specifically focuses on the nuances of connection state, message parsing, heartbeat maintenance, and error handling — aspects not detailed in the parent topic or sibling subtopics.
Functionality
At its core, Connection Handling orchestrates the following key workflows:
Connection Lifecycle Management: When a WebSocket connection is initiated, a unique client identifier is created to track this connection instance independently. The handler establishes listeners for errors, closures, incoming messages, and ping/pong frames to maintain connection health.
Subscription Control: Clients communicate subscription requests via JSON messages specifying methods like
subscribe,unsubscribe, orpingalong with subscription IDs and subscription data (e.g., blockchain addresses to watch). The handler validates requests, manages active subscription IDs, and interacts with the Subscription Registry to add or remove subscriptions accordingly.Message Dispatching: Incoming messages are parsed and routed to appropriate handler functions based on the subscription topic (currently only 'txs' for transaction events). The handler sends responses or errors back to clients in a standardized JSON format.
Heartbeat and Connection Health: To detect and close stale or dead connections, periodic ping frames are sent to clients. If a pong response is not received within a timeout window, the connection is terminated. This mechanism ensures resources are freed promptly for disconnected clients.
Prometheus Metrics Integration: The handler increments and decrements counters tracking active WebSocket connections, feeding observability into the monitoring stack without polluting the parent topic.
Graceful Cleanup: Upon connection closure or errors, all client subscriptions are unsubscribed cleanly from the registry to prevent dangling references and ensure consistent subscription state.
Example Interaction Snippet
When a client sends a subscription request, the handler validates and delegates as follows:
private handleSubscribeTxs(subscriptionId: string, data?: TxsTopicData): void {
if (!subscriptionId) {
this.sendError('subscriptionId required', subscriptionId)
return
}
if (!data?.addresses?.length) {
this.sendError('addresses required', subscriptionId)
return
}
this.subscriptionIds.add(subscriptionId)
this.registry.subscribe(this.clientId, subscriptionId, this, data.addresses)
this.client.subscribeAddresses(this.registry.getAddresses())
}
This snippet highlights validation, subscription tracking, and interaction with both the central registry and the underlying WebSocket client.
Relationship
Connection Handling integrates tightly with the parent topic—real-time subscription management—by serving as the foundational interface between individual WebSocket clients and the subscription system. While the Subscription Registry manages the global mapping of subscriptions to blockchain addresses, Connection Handling manages per-client connection state and message workflows.
It complements the Subscription Registry by:
Forwarding subscription and unsubscription requests from clients to the registry.
Receiving event notifications from the registry to publish updates back to the client.
Maintaining client-specific metadata (such as active subscription IDs and heartbeat status) that the registry alone does not track.
This division of concerns enables scalable and maintainable real-time event handling where connection logic is decoupled from subscription bookkeeping.
Diagram
sequenceDiagram
participant Client
participant ConnectionHandler
participant Registry
participant WebsocketClient
Client->>ConnectionHandler: Send {"method":"subscribe","subscriptionId":"sub1","data":{"topic":"txs","addresses":["addr1"]}}
ConnectionHandler->>ConnectionHandler: Validate message & subscriptionId
ConnectionHandler->>Registry: subscribe(clientId, sub1, this, ["addr1"])
Registry->>WebsocketClient: subscribeAddresses(updatedAddresses)
ConnectionHandler->>Client: Acknowledge subscription or send error
Registry-->>ConnectionHandler: Event for address "addr1"
ConnectionHandler->>Client: JSON event message with subscriptionId "sub1"
Client->>ConnectionHandler: Send {"method":"ping","subscriptionId":"sub1"}
ConnectionHandler->>Client: Send "pong"
Note over ConnectionHandler: Periodic ping frames sent\nHeartbeat timeout triggers terminate
Client->>ConnectionHandler: Send {"method":"unsubscribe","subscriptionId":"sub1"}
ConnectionHandler->>Registry: unsubscribe(clientId, sub1, ["addr1"])
Registry->>WebsocketClient: subscribeAddresses(updatedAddresses)
ConnectionHandler->>Client: Acknowledge unsubscription
This sequence diagram illustrates the core message exchange flows, subscription lifecycle, and heartbeat interactions managed by Connection Handling.