Commit eb3b2dc
committed
feat(remote): phase α.5 — RemoteClient outbound implementation
Closes Phase α. RemoteClient is the crab-proto outbound side, symmetric
to the RemoteServer from α.4.b. Same wire, same lifecycle, different
direction: client calls connect(), runs initialize, then issues typed
session.create / session.attach / session.sendInput / session.cancel
round-trips and subscribes to server -> client session.event
notifications via a broadcast channel.
Module layout under crates/remote/src/client/:
- mod.rs RemoteClient + dispatcher task. Cheap-to-clone (internally
Arc<Inner>) so a TUI and a logger can both subscribe
without fighting over the connection. Background task owns
the WebSocket and routes:
* outbound Request -> serialise + send + stash reply_tx
in a pending-map keyed by MessageId
* inbound Response -> pull reply_tx from map, fulfil
oneshot so the waiting caller unblocks
* inbound SESSION_EVENT notification -> broadcast::send
close() signals the dispatcher to emit a WS close frame
and exit; idempotent — second call returns AlreadyClosed.
- config.rs ClientConfig { url, auth_token, client_info, request_timeout,
event_buffer }. Durations serde as integer seconds so
web / mobile clients reading the same config file get a
predictable wire shape.
- error.rs ClientError enum: InvalidUrl / InvalidAuthToken / Handshake /
Transport / IncompatibleProtocol / ServerError /
ConnectionClosed / Serde / AlreadyClosed. Wire-level and
protocol-level failures split so callers can retry the
former but not the latter.
lib.rs re-exports RemoteClient / ClientConfig / ClientError at the
crate root.
Integration tests in tests/client_roundtrip.rs (4 cases, all green)
exercise a real RemoteClient against a real RemoteServer:
* handshake -> create -> backend event reaches client broadcast ->
client send_input observed on backend inbound_rx -> cancel same
* attach on a nonexistent session surfaces ServerError with the
SessionNotFound code (-32003)
* close is idempotent; second call returns AlreadyClosed
* wrong JWT secret rejected at handshake (tungstenite bubbles the
401 as Error::Http -> ClientError::Handshake)
Local totals for crab-remote: 33 unit + 4 server e2e + 4 client e2e =
41 green.
Phase α closes here. crab-proto now has both a working server and a
working client, validated against each other.1 parent 06ecea1 commit eb3b2dc
5 files changed
Lines changed: 670 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
0 commit comments