feat: add Server-Sent Events (SSE) streaming support#150
feat: add Server-Sent Events (SSE) streaming support#150SebastienMelki wants to merge 13 commits intomainfrom
Conversation
…erators - Add stream field to HttpConfig proto annotation (field 3) - Add Stream bool to shared HTTPConfig struct, populated from proto - Go HTTP server: SSESender interface, sseSender impl, SSEHandler generic function - Go HTTP server: SSE methods use (ctx, *Req, SSESender) error signature - Go client: EventStream[T] type with Next/Err/Close iterator pattern - Go client: SSE methods return *EventStream instead of *Response - TS client: async generator methods with ReadableStream SSE parsing - TS server: SSE handler returns ReadableStream wrapped as text/event-stream - OpenAPI: SSE operations use text/event-stream with x-sse-event-schema extension - Golden tests for all 5 generators with SSE + unary in same service
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
🔍 CI Pipeline Status✅ Lint: success 📊 Coverage Report: Available in checks above |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #150 +/- ##
========================================
- Coverage 3.03% 2.86% -0.18%
========================================
Files 47 47
Lines 7802 8273 +471
========================================
Hits 237 237
- Misses 7561 8032 +471
Partials 4 4
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Adds examples/sse-streaming/ with a complete market data service demonstrating SSE alongside standard unary RPCs. Includes `make demo` for end-to-end testing. Also bumps Go version in existing example go.mods. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Review feedback from local diff against
|
…ling 1. Replace bufio.Scanner with bufio.Reader in Go client EventStream to remove the 64 KiB token size limit on SSE events. 2. Track whether sseSender has written data. If handler errors before any Send(), use the normal errorHandler path (proper HTTP status) instead of sending an SSE error event on an HTTP 200. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove proto-compatibility matrix job — arduino/setup-protoc can no longer resolve old protoc versions (3.19.0, 3.20.0, 25.1). Proto validation is already covered by buf-lint and buf-breaking jobs. - Add codecov.yml with informational status checks — generator code is covered by golden tests (external binary), not Go unit test coverage. - Fix SSE example Makefile: redirect server output, poll for readiness. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Follow-up review after
|
sseSender.Flush() also commits the HTTP 200 response, so the committed flag must be set there too. A handler calling Flush() for a heartbeat before erroring now correctly gets an SSE error event instead of a broken writeErrorWithHandler after headers are already sent. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add SSE streaming annotation section showing stream: true usage - Add generated output examples for all 5 generators (Go server SSESender, Go client EventStream, TS client AsyncGenerator, TS server ReadableStream, OpenAPI text/event-stream) - Update annotation registry row for ext 50003 to mention SSE streaming flag
…mple Add client demos for both languages alongside the existing Go server: - go-client/main.go: Go client using generated EventStream API - ts-client/main.ts: TypeScript client using generated AsyncGenerator API - docs/MarketDataService.openapi.yaml: generated OpenAPI spec with SSE endpoints - Updated buf.gen.yaml with protoc-gen-ts-client and protoc-gen-openapiv3 - Updated Makefile with demo-go-client and demo-ts-client targets Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…E connections Breaking out of an async generator releases the reader lock but doesn't close the underlying TCP connection, keeping Node.js alive indefinitely. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Another full-pass review found two TypeScript streaming issues:
|
go run spawns a child process — killing its PID leaves the actual server orphaned on port 8080. Now we go build first, run the binary directly, and use a trap to guarantee cleanup even on failure. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Good job overall on the SSE support work — the Go-side fixes and the follow-up demo/cleanup changes are moving in the right direction. I still see two TypeScript streaming issues that look unresolved:
Once those two TS cleanup/cancellation paths are handled, I think this is in much better shape. |
Summary
stream: trueflag toHttpConfigproto annotation, enabling any RPC to be marked as an SSE streaming endpointSSESenderinterface +SSEHandler[Req]generic handler withtext/event-stream,http.Flusher, full request bindingEventStream[T]iterator withNext(T) bool/Err()/Close()(bufio.Scanner pattern)async *method()returningAsyncGenerator<T>withReadableStreamSSE parsingReadableStream<T>, route wraps into SSE-formattedResponsetext/event-streamcontent type withx-sse-event-schemavendor extensionMotivated by the Alpaca Go SDK use case which requires SSE for real-time market data streaming.
Test plan
./scripts/run_tests.sh --fast)make lint-fixreports 0 issuesstream: trueand verify the Go server SSE handler works end-to-end🤖 Generated with Claude Code