Repository navigation
br-service-engine 0.3.4
0.3.4 - 2026-09-24
Engine services become reachable for subscriptions through the gateway. The
gateway reaches a subgraph for a subscription only as POST /graphql with
Accept: text/event-stream (graphql-sse over HTTP), never over a WebSocket;
through 0.3.3 the engine served subscriptions on GET /graphql/ws alone and
answered that request with the JSON error "Subscriptions are not supported on
this transport.", which the gateway reports as SUBGRAPH_REQUEST_ERROR — seen on
dev for every engine service. Additive: no adopter code changes.
Added
- The gateway's subscription transport on
POST /graphql. A request whose
Acceptnamestext/event-streamis authenticated and its body read exactly as
before — the passport from the headers first (401with the body never read,
the same status and body a JSON request gets), then the bounded body — and is
then answered as a graphql-sse "distinct connections" stream (graphql/sse.rs):
Content-Type: text/event-stream,Cache-Control: no-cache, oneevent: next
per GraphQL response (data:the response JSON on one line), one
event: complete(data:empty) at the end, and a:comment after 15 s
without a frame. Any operation may be sent this way: a query or a mutation
answers onenext, thencomplete; a coded refusal rides anext, then
complete, as on the WebSocket. A response that cannot be serialized is logged
and sent as a codedINTERNALresponse, never as an empty frame. A request
withouttext/event-streaminAccept(a wildcard does not count) is answered
as before. - Bounded like a WebSocket session, on the same session machinery. The stream
runs the same schema, so a subscription attaches the same engine session as on
/graphql/ws: sameReset/Upsert/Removewire and revision, same cohorts,
same principal-facts refresh. Atsession_max_age, measured from the request,
and when the engine shuts down (the signal that closes the WebSockets), it sends
completeand ends, so the gateway re-subscribes with a freshX-Passportand
an open stream never holds graceful shutdown; a stream requested during shutdown
answerscompletewithout executing. A client that goes away drops the
response, and with it the operation and its session. - Conformance:
bb16(black-box, the realexample-servicebinary) — over the
gateway's transport a subscriber gets theResetthen theUpserton a
contiguous revision, read withbr-test-harness'sSseSubscription(the client
service e2e suites use); a passport that is absent, undecodable or not a
passport is refused with the very401a JSON request gets, before a byte of
the body is read (a body the client never finishes sending is answered at once,
while an authenticated control is waited for); and pastsession_max_agethe
stream sendscomplete, ends, and a new request attaches afresh. TheReset
and max-age scenarios fail on 0.3.3 with the dev error; the401scenario
pins that the refusal still precedes the transport choice. Unit tests pin the
framing, a query over the stream, a refusal as anext, the keep-alive
cadence, the max-age and shutdown completions, the refusal to start during
shutdown, the release of the operation when the response is dropped, and which
Acceptvalues ask for a stream.
Changed
conformance-service-enginedev-depends onbr-test-harness1.2.0 (the
br-e2e-harnessrepository,ssefeature only);deny.tomlallows that git
source.- README: the ops contract names the WebSocket route
/graphql/ws(it read
/ws) and documents both subscription transports; the black-box command list
namesbb12tobb16.
Adopter migration
- None. Move the pin to
v0.3.4:appserves the event stream with no new
configuration and no environment variable, and a service's schema and SDL are
unchanged. Its subscriptions become reachable through the gateway as soon as
the new image rolls.
Known limitation
- Paging a gateway (SSE) session requires the session's pod. The
page
gesture serves only a live session this pod holds. Through the gateway the
session rides an event stream and thepagemutation is a separatePOST
that may reach another replica, where it is refused
(EngineError::NoLiveSession,NOT_FOUND). Paging a gateway (SSE) session
requires the session's pod (one replica) until 0.4.0 moves paging to
subscription arguments.
Engine services run one replica today.