Repository navigation
feat: pass a consumed module's server-streaming methods through to the page - #41
Merged
Merged
Conversation
…e page
The passthrough refused every streaming method ("only unary methods pass
through"), so a page could not follow a module's live state. A
server-streaming method is now served as a Connect server-streaming
procedure at the same /modules/<as>/<pkg.Service>/<Method> path, under
exactly the unary rules:
- the authority minted for that method (or the bearer alone, for a
ViewerBearer module);
- the declared response fields applied to every streamed message.
Both bounds are declared per method: MaxStreamDuration (default 5 min, at
most 30 min; the stream then ends with deadline_exceeded) and
MaxStreamMessageBytes (default 1 MiB; a larger message ends the stream with
resource_exhausted and is never truncated). The page disconnecting cancels
the module request. Client-streaming methods, and stream bounds on a unary
method or out of range, are refused at boot.
A module answers a streamed method over its google.api.http binding with
grpc-gateway's server-streaming wire: newline-delimited JSON,
{"result": …} or {"error": {"code", "message"}} per line
(application/x-ndjson, or application/json). Gateway.TranscodedStream is the
same call for a solution handler. The interface artifact marks a streamed
operation (x-streaming: server).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Consumed-module passthrough now serves server-streaming methods. Until now
resolvePassthroughrefused every streaming method ("only unary methods pass through"), so a page could not follow a module's live state, such as a chat turn's progress. The first consumer is a composed module's turn events.What changes
/modules/<as>/<pkg.Service>/<Method>path. connect-es's generated client works unmodified.ViewerBearermodule. Both go through the new sharedauthorizehelper that unary now uses too.Response/WholeResponse) apply to every streamed message.ConsumedMethod, and a declaration is refused at boot when invalid.MaxStreamDuration: defaultDefaultStreamDuration(5m), at mostMaxStreamDurationLimit(30m). When it runs out the stream ends withdeadline_exceeded.MaxStreamMessageBytes: defaultDefaultStreamMessageLimit(1 MiB). A larger message ends the stream withresource_exhausted; it is never truncated.Timeoutbounds only the mint and the module's first answer, andMaxResponseBytesis refused on a streaming method.google.api.httpbinding. It is newline-delimited JSON (application/x-ndjson;application/jsonis accepted), one{"result": <protojson>}or{"error": {"code": <int>, "message": "…"}}per line. Blank lines are ignored.unavailable.Gateway.TranscodedStreamexposes the same call to a solution's own handlers.Operation.Streaming,x-streaming: server), and its behaviour text states the bounds and that the mask applies per message.Compatibility: additive. Two new fields on
ConsumedMethodandOperation, new constants andGateway.TranscodedStream; nothing existing changes shape. The only behaviour that changes is that a server-streaming declaration boots instead of being refused.Classification
Fix, at the owner. The refusal was this package's own limitation, and it is lifted here rather than worked around in each solution.
Verified
The repo's gate (
go mod verify,go test -race ./...,go vet ./..., gofmt) passes. New hermetic tests (stream_test.go) cover:resource_exhausted, never truncated;deadline_exceeded, with the module request cancelled;A mutation check (removing the mask) fails the mask test. The existing unary tests are unchanged and pass.
Not verified
httptestcounterparts only), and no real module has served the stream through a real host yet. The first live consumer is a composed module'sObserveTurn.module-saas-starterapp/api/solutions/[id]/proxy/[...path]/route.ts):upstream.bodyunbuffered.cache-control: no-store, no-transformandx-accel-buffering: noonly fortext/event-stream. A Connect stream isapplication/connect+json, so it gets neither header. An nginx-style ingress could buffer it, or something on the path could compress it.compressis left at its default (on). I did not verify whether that buffers a streamed route-handler response.application/connect+json/application/connect+proto. SSE is not needed.🤖 Generated with Claude Code