Skip to content

feat: add native JSON streaming through a shared session interface #294

Open

Description

@igorls

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 /router and 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 /stream wire 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 head e21a54cf; 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 reviewed e8dd91a7 tree 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-256 dfa5e6fc58ac3a9ef510c32e9cb2f9db6a05e2ef7a7dbe7d8be1678e79d58f49. 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions