Sidecar: shard link (Rust)
First cut of the Rust sidecar, in sidecar/. It is the TCP listener the shard
dials out to; that asymmetry is what keeps the game unreachable from the website.
shard.rs: serve() binds 127.0.0.1:7788 and accepts shard connections in a loop,
re-accepting on disconnect. Each connection splits read/write: the reader parses
newline-JSON into ShardEvent { kind, value } and forwards over an mpsc; the writer
drains a command mpsc. ShardHandle::send posts to whichever shard is connected and
drops with a warning if none is -- a website query during an outage should fail
fast, not queue; live events that must survive an outage are buffered by the shard.
main.rs wires it up, logs events by kind, and runs a 15s heartbeat ping to
exercise the command path. Later phases fan events out to a WebSocket broadcaster
and SQLite, and turn REST calls into shard commands.
Verified against the live shard: the sidecar received the shard's server.hello
(parsed, fields intact), round-tripped its heartbeat ping -> pong, and after a
sidecar restart the shard reconnected on its own and re-sent hello. Tokio + serde;
axum/sqlx/tungstenite come with the WS and REST phases.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
37
sidecar/README.md
Normal file
37
sidecar/README.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# uo-link sidecar
|
||||
|
||||
The Rust half of the bridge. It terminates the loopback link to the ServUO shard and (as it grows) exposes WebSocket + REST to the website.
|
||||
|
||||
```
|
||||
website ──WS (live feed) / REST (queries)──► sidecar ──loopback TCP 127.0.0.1:7788──► shard
|
||||
(this) newline-JSON, bidirectional
|
||||
```
|
||||
|
||||
The sidecar is the TCP **listener**; the shard dials out to it. That is what keeps the game unreachable from the website — the game exposes no port of its own. See `../docs/PLAN.md` §2.
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
cargo run # info logging
|
||||
RUST_LOG=debug cargo run # see every event, incl. pong heartbeats
|
||||
```
|
||||
|
||||
Binds `127.0.0.1:7788` and waits for the shard to connect. Boot the shard (or it will reconnect on its own) and watch `server.hello` arrive.
|
||||
|
||||
## Status
|
||||
|
||||
| Piece | State |
|
||||
|-------|-------|
|
||||
| Shard link (`shard.rs`) | **done** — accepts the shard, reads events, sends commands, re-accepts on disconnect. Verified against the live shard: received `server.hello`, round-tripped a `ping`→`pong`, and reconnected after a sidecar restart. |
|
||||
| WebSocket feed (website ← live events) | not started |
|
||||
| REST queries (char profile, roster, vendor snapshot, link submit) | not started |
|
||||
| SQLite persistence (event history, economy, cached profiles, link map) | not started |
|
||||
|
||||
## Design
|
||||
|
||||
- **`shard.rs`** — `serve()` binds the listener and accepts shard connections in a loop. Each connection splits into read/write halves: the read half parses newline-JSON into `ShardEvent { kind, value }` and forwards them; the write half drains an mpsc of command lines. `ShardHandle::send` posts a command to whichever shard is currently connected, and **drops with a warning if none is** — a website query during a shard outage should fail fast and retry, not queue behind a reconnect. Live *events* that must survive an outage are buffered by the shard, not here.
|
||||
- **`main.rs`** — wires it together and, for now, logs events by kind. Later phases fan `ShardEvent`s out to the WebSocket broadcaster and SQLite, and turn REST calls into shard commands via `ShardHandle`.
|
||||
|
||||
## Wire protocol
|
||||
|
||||
Every line is one JSON object with `t` (epoch ms) and `kind`. The shard→sidecar events and sidecar→shard commands are catalogued in `../docs/PLAN.md` (§5 data catalog, §7 protocol) and were all validated end-to-end while building the plugin. Notable inbound commands the sidecar will issue: `char.request`, `account.roster`, `vendor.snapshot`, `link.confirm`, `towncrier.add`/`remove`, `ping`.
|
||||
Reference in New Issue
Block a user