Page MenuHomePhabricator

[Chronik] Add block WebSocket messages at `/ws`
ClosedPublic

Authored by tobias_ruck on Apr 12 2023, 21:39.

Details

Reviewers
Fabien
Group Reviewers
Restricted Project
Commits
rABC2ab2289f3d1c: [Chronik] Add block WebSocket messages at `/ws`
Summary

Send updates about (for now, only) blocks via WebSocket.

The indexer handles subscriptions using the Subs struct, which allows to get tokio::sync::broadcast::Receivers for BlockMsg. When a block is connected/disconnected/finalized, the indexer tells Subs to broadcast a BlockMsg to all the subscribers.

In the indexer, we put the Subs behind a separate RwLock, as adding subscribers will need &mut access. Since we don't want to lock the entire indexer for adding a single WS subscription (potential DoS vector), we put it behind a separate lock.

When a client connects via WebSocket, we handle that connection's livecycle in handle_subscribe_socket. We listen to both messages from the client as well as from the indexer using select!. To separate the ws handling and the subscription logic, we add WsMsg.

Errors (e.g. the client sending an unknown/invalid message) are handled by sending the client a proto::Error message.

For testing, we add websocket-client via pip, and add a ws method to ChronikClient.

Test Plan

ninja && ./test/functional/test_runner.py chronik_ws

Event Timeline

rebase on master, rename SubAction -> WsAction

test/functional/chronik_ws.py
65 ↗(On Diff #39689)

you should use a wait_until here or to avoid issues with the network latency on slow machines (e.g. qemu is very slow for networking)

add height to BlockMsg, make ws timeout default to None

This revision is now accepted and ready to land.Apr 14 2023, 13:42