Skip to content

feat: streaming RPC results (return a ReadableStream/AsyncIterable from an action) #489

Description

@vivek7405

Sub-issue of #488. webjs's RPC is request/response only. An action cannot return a ReadableStream / AsyncIterable and have it stream to the client (AI token streams, progress, large result sets). TanStack Start supports this via a multiplexed frame protocol (packages/start-server-core/src/frame-protocol.ts) + a raw-response marker (x-tss-raw) + late stream registration, serialized with seroval's toCrossJSONStream.

Design / approach

When an action (any verb, typically GET or POST) returns a ReadableStream / AsyncIterable / async generator, stream it over the RPC wire instead of buffering. The client stub returns an async iterable / stream the component consumes. Reuse webjs's existing streaming infra where possible (<webjs-stream> / Suspense streaming are render-side; this is RPC-result-side). Consider a framed wire (length-prefixed chunks) so a stream can interleave with the serialized envelope. Compose with #472 seeding (a streamed result is not seeded) and the verb work in #488.

Acceptance criteria

  • An action returning a ReadableStream / AsyncIterable streams over the RPC; the client stub yields chunks as they arrive.
  • Back-pressure respected; the stream cancels when the client disconnects (ties into the AbortSignal sub-issue).
  • Rich values inside the stream round-trip through webjs's serializer.
  • Tests: unit (framed encode/decode), integration (createRequestHandler streams), browser/e2e (a token stream renders incrementally).
  • Docs updated (agent-docs/advanced.md, data-fetching page).

Activity

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

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

  • Status
    Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions