Replies: 1 comment 1 reply
|
I'm in favor of the architectural direction here. AimX should be the default JSON protocol over every current transport. Removing the second WebSocket envelope, codec and browser-side demux gives us one place for correlation, subscriptions, reconnect behavior and future transport adapters. I also compared your feat/retire-aimdb-ws-protocol branch with my #156 representation benchmark branch. Those results do not justify keeping a separate WS protocol or changing the current wire to CBOR. They point toward optimizing the direct JSON path now, while preserving an explicitly negotiated native-binary edge for a future binary-heavy consumer. In other words: one protocol today should not mean one serialization forever. Before treating the migration as ready, I think we should close a few contracts:
This changes more than raw WS framing: query results move from
The current branch still has different
The wildcard grammar needs to be specified and validated. It is described as MQTT-style, but currently uses The end-to-end loss contract also needs work: events can be dropped before a useful sequence number is assigned,
The existing WS path serializes a shared frame once. The AimX path in this branch appears to serialize the full envelope once per subscriber. I would like a 1/10/100/500-client fan-out benchmark before we claim the new path preserves O(1)-style sharing. I ran the focused core, client, persistence, WebSocket and wasm-target checks successfully. There are still a few branch blockers: With those boundaries addressed, I think the desired end state is right: AimX as the default JSON protocol over every transport, with future binary representations introduced through explicit negotiation rather than another parallel protocol stack. |
Uh oh!
There was an error while loading. Please reload this page.
AimDB currently carries two wire protocols for one feature: AimX (tagged NDJSON frames) on UDS/serial/TCP and a separate WebSocket protocol for the WS connector and the browser bridge. Both already run on the same session engine, the fork is only the envelope.
What could change:
aimdb-ws-protocol,the WS codec and the browser bridge's hand-rolled demux (~1,700 lines total) go away;
correlation, reconnect, keepalive and the offline queue would exist exactly once, in core.
subwith an MQTT-style pattern (#,*)fans in all matching records — events tagged with the record that fired, one late-join
snapshot per match.
aimdb-cli watch '#'would work against any AimDB instance.record.query→{records: [{topic, payload, ts}], total};record.listrows carryname/schema_type/entity.WsBridgeAPI stays unchanged, only the wire underneath moves. Raw (non-bridge) WSclients are the surface that breaks.
The architecture this would leave us with:
flowchart TB subgraph S ["server"] DB["AimDb — typed records · buffers"] AX["AimxDispatch (UDS · serial · TCP)"] WS["WsDispatch (HTTP auth · fan-out bus)"] ENG["serve / run_session — subs · acks · snapshots"] C1["AimxCodec"] DB --> AX --> ENG DB --> WS --> ENG ENG --> C1 end W(["AimX frames — req · reply · sub · subscribed · unsub · event · snap · write · ping · pong"]) subgraph C ["clients"] C2["AimxCodec"] RC["run_client — demux · reconnect · keepalive · offline queue"] CLI["aimdb-cli / aimdb-mcp"] MIR["AimDB ↔ AimDB mirrors"] BR["WsBridge (browser, WASM)"] C2 --> RC RC --> CLI RC --> MIR RC --> BR end C1 === W === C2What a wildcard subscription would look like on the wire:
→ {"t":"sub","id":1,"topic":"temp/#"} ← {"t":"subscribed","sub":"1"} // WS only ← {"t":"snap","sub":"1","topic":"temp/vienna","data":{...}} // one per matched record ← {"t":"event","sub":"1","seq":1,"topic":"temp/berlin","data":{...}}The payoff would be: AimX is how you talk to AimDB, over UDS, serial, TCP or WebSocket and cheap future transports (WebTransport, Web Serial, …): only a
Connection/Dialershim per transport. Protocol, codec and engines come for free.@thaodt what do you think?
All reactions