Subscription Registry
Purpose
The Subscription Registry addresses the challenge of efficiently managing real-time blockchain event subscriptions on a per-client and per-address basis. Within the broader context of real-time subscription management, it provides a centralized mechanism to track which WebSocket clients have subscribed to updates for specific blockchain addresses. This ensures that when new transactions or blocks arrive, only the relevant clients receive notifications, optimizing resource usage and improving event delivery precision.
Functionality
At its core, the Subscription Registry maintains two complementary mappings:
Client-to-Addresses: Which blockchain addresses each client connection has subscribed to.
Address-to-Clients: Which WebSocket client connections are interested in updates for each blockchain address.
This bidirectional structure allows quick lookup and efficient broadcasting of events.
Key Workflows
Subscription Management:
When a client subscribes to a set of addresses, the registry:
Normalizes addresses (e.g., lowercasing) for consistent matching.
Records the client’s unique subscription ID alongside each subscribed address.
Updates internal maps to reflect these associations.
Unsubscription:
Clients can unsubscribe from specific addresses or all addresses associated with a subscription. The registry removes these links and cleans up any empty records to avoid stale entries.
Event Handling:
Upon receiving new blockchain data (blocks or individual transactions) from the server-side WebSocket connection to the blockchain node or indexer, the registry:
Uses a customizable transaction handler to extract the relevant addresses involved in the transaction.
Identifies clients subscribed to those addresses.
Dispatches the transaction payloads directly to those clients via their connection handlers.
This targeted event propagation ensures clients receive timely updates only for the addresses they monitor.
Core Methods (Illustrative Snippets)
subscribe(clientId, subscriptionId, connection, addresses) {
addresses.forEach(address => {
address = this.formatAddress(address)
this.clients[id].add(address)
this.addresses[address].set(id, connection)
})
}
async onTransaction(msg) {
const { addresses, tx } = await this.handleTransaction(msg)
this.publishTransaction(addresses, tx)
}
private publishTransaction(addresses, tx) {
addresses.forEach(address => {
address = this.formatAddress(address)
for (const [id, connection] of this.addresses[address].entries()) {
const { subscriptionId } = Registry.fromId(id)
connection.publish(subscriptionId, address, tx)
}
})
}
Integration
The Subscription Registry operates as a core component within the parent topic of real-time subscription management. It complements the **Connection Handling** subtopic, which manages the lifecycle and health of WebSocket client connections, by focusing specifically on the subscriptions clients hold.
Together, these subtopics form a layered architecture:
Connection Handling: Maintains active client connections, manages heartbeats, and routes messages.
Subscription Registry: Keeps track of which clients want updates for which blockchain addresses and dispatches events accordingly.
Unlike Connection Handling, which deals with connection state and messaging protocols, the Registry specializes in subscription data structures and event filtering logic. This separation of concerns enhances modularity and scalability.
The Registry also interfaces with blockchain node or indexer event streams by consuming raw block or transaction messages and transforming them into filtered notifications tailored to client subscriptions. Its use of customizable address formatters and transaction handlers allows adaptation across multiple blockchain implementations supported in the platform’s multi-blockchain architecture.
Diagram
flowchart TD
subgraph Client Side
C1[WebSocket Client 1]
C2[WebSocket Client 2]
end
subgraph Subscription Registry
SR1[clients: Map<ClientSubId, Set<Addresses>>]
SR2[addresses: Map<Address, Map<ClientSubId, ConnectionHandler>>]
end
subgraph Blockchain Event Stream
BlockEvent[New Block / Transaction Message]
TxHandler[Transaction Handler extracts addresses]
end
C1 -->|subscribe(addrs)| SR1
C1 -->|subscribe(addrs)| SR2
C2 -->|subscribe(addrs)| SR1
C2 -->|subscribe(addrs)| SR2
BlockEvent --> TxHandler
TxHandler -->|addresses + tx| SR2
SR2 -->|publish to matching clients| C1
SR2 -->|publish to matching clients| C2
The flowchart illustrates how clients register subscriptions for addresses, the registry maintains bidirectional maps, and how incoming blockchain transaction events are processed and dispatched only to interested clients. This targeted delivery mechanism is key to efficient real-time event subscription management in the system.