Repository navigation
feat: add native JSON streaming through a shared session interface #294
Description
Scope and ownership
The operator authorized a Rust-first client with a dependency-free core, an optional Tokio/tungstenite transport adapter, native WebSocket + JSON first, shared cross-language conformance, and coordination with the architecture agent on 2026-10-23. The stream-client chat owns the versioned contract, Rust implementation and shared scenarios; the architecture/server lane owns this HAPI integration. Coordinate with eosrio/hyperion-tools#24 and existing server compatibility issue #231.
Start from release/4.5 at ab38eaf94dafd14ea6e76404452cc1a3a69041be. Preserve merged #290/#291 lifecycle/filter/selector regressions. This is an additive stream transport lane; RabbitMQ, protocol-provider authority and existing history remain unchanged. The proposed /stream/v2 endpoint and hyperion-stream.v1.json subprotocol are working names pending the shared contract and route/proxy verification.
Required behavior
- Extract a transport-neutral session/history interface used by both the existing Socket.IO adapter and the native adapter. Share request validation, filter/selector semantics, history search and proof/readiness checks, cancellation, history/live coordination and terminal errors. Keep the existing internal
/routerand Redis fanout, with native subscriptions using the same registration/cancellation authority and relay outage/replacement cleanup. - Register the additive native endpoint on the existing stream listener with explicit protocol negotiation and bounded input validation. Verify route precedence against the Engine.IO path and the operator-facing reverse proxy. Preserve legacy
/streamwire behavior. - Bind each session/subscription to its connection incarnation and generation. Keep client request IDs, subscription IDs and sequence values distinct. Reject stale/foreign delivery, ACK/credit, cancellation and replacement frames. Preserve canonical decimal-string uint64 identities across JSON encode/decode without reconstructing unsafe numbers.
- Apply negotiated server-enforced count and encoded-byte budgets per subscription and connection, including queued and in-flight payloads and history/live overlap. Bound control frames, request counts, frame sizes and idle/ACK waits. Credit or packet acceptance does not establish durable application processing. Slow consumers or overflow fail explicitly with a replayable boundary; never silently discard events and advance progress.
- Preserve inclusive at-least-once replay and possible duplicates, scoped retryable unavailability, source-proof expiry and unrelated subscription progress. Cancel active searches, ACK waits and scrolls on request cancellation or connection retirement. History completion must not claim unqualified source coverage.
- Carry chain identity and explicit ordering/generation rules for fork, LIB and relay events. On outage, unconfirmed LIB-mode data must be replayed or rejected explicitly before later finality can release it.
Verification and delivery
- Pin the shared JSON contract/scenario revision from eosrio/hyperion-stream-client before freezing wire expectations. Conformance must cover action/delta filters and exact sequence strings, historical/live handoff, mid-block and repeated disconnects, fork replacement before LIB, old-generation frames, cancellation during search/ACK waits, retryable failures, overflow and cross-subscription isolation.
- Run the same applicable scenarios against the actual emitted HAPI adapters, including real loopback WebSocket negotiation/routing. Keep all existing native Node 22/24 stream tests. Shared fixtures supplement fix: qualify streaming filters, recovery and cancellation for 4.5 #231's real known-dataset Elasticsearch/source-count/fork/LIB acceptance; they do not close it.
- Use committed-lock installs, Bun 1.4.4 / TypeScript 7.0.2 complete checks, native artifacts, targeted tests and release CI. Retain exact source/runtime/protocol pins and independent Standards/Spec review.
- Publish operator configuration/proxy guidance, compatibility and limits. Introduce no automatic deployment, transport deprecation, public native-action activation or claim of complete Wire/Bun/runtime qualification.
Implementation branch: feat/native-stream-session. Endpoint routing, credit shape and session replacement details remain implementation questions to settle with the client owner and shared contract, within the approved behavior above.
Implementation checkpoint — 2026-10-23
- #295 shared history-delivery extraction is merged as
7e7f018bae39a255b787e3b3b884e31ffeca9bf3. Its tree matches reviewed heade21a54cf; all nine post-merge CI jobs pass. All 28 focused native Node 22/24 checks pass, including required disconnect cancellation of proof work. Legacy wire/ACK shape is preserved. - #296 is merged as
d665dc6a6211079cacd2bee6bba0a44c5f4ba321, with the reviewede8dd91a7tree unchanged. It adds JSON validation and count/full-encoded-byte credit foundations. All 91 focused native Node 22.23.3/24.19.0 checks and the whole Bun 1.4.4 check/build pass locally. Final independent Standards/Spec reviews have no remaining scoped findings; all nine final-head CI jobs passed. Post-merge CI is running. No native endpoint is registered by these modules. - The client contract/corpus is pinned to
346c473f55979ff2dd841aa2bbba4bcfebc49ef7: all 37 wire vectors run, SHA-256dfa5e6fc58ac3a9ef510c32e9cb2f9db6a05e2ef7a7dbe7d8be1678e79d58f49. The manifest, protocol, 24 state scenarios and two network-session fixtures are verified byte-for-byte; state/network server acceptance awaits integration. All eight exact-head Windows/Linux Rust/Node jobs pass for client draft #21; actual HAPI session/network qualification remains pending. Client #20 owns later scenario/corpus revisions; consume explicit immutable pins rather than working-tree changes.
Agreed v1 integration details: close native public WebSockets on relay replacement/outage; a new transport receives a fresh connection incarnation, with no in-band second hello. A pending subscribe can receive a server-assigned subscription ID before acceptance; cancellation may acknowledge that full scope with the original request ID without sending an artificial accepted. Resolve accepted.start_from from the real inclusive replay lower bound, independently of the first matching history hit. The endpoint/session/queue/deadline/query-memory/fork/proxy and complete shared conformance obligations above remain open, as does #231.
Activity