Research first-class Datastar and SSE support - #208
Draft
lukewilliamboswell wants to merge 76 commits into
Draft
Conversation
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.
Purpose
Add first-class typed SSE and Datastar support to basic-webserver with
Go-comparable application ergonomics and explicit bounded ownership,
admission, backpressure, compression, cancellation, observability, and
shutdown behavior.
This remains a draft because it depends on the erased-callable ownership and
repacking work in roc-lang/roc#10530.
The experiment pins exact Roc commit
5a5f4c02; CI builds that revision untilthe compiler work lands and has a normal nightly artifact.
Accepted platform design
{ init!, respond!, shutdown! }and returnServer.stream(Sse.Source)when they need SSE.Sse.unfold!creates a typed retained functional machine. Each transitionreturns
Emit,Wait,End, or an application error; applications neverreceive a socket, writer, task, compressor, or host wake token.
Datastarowns canonical patch-elements, remove-elements, and patch-signalsevent names and fields, including selectors, patch modes, namespaces,
element-scoped view transitions, reconnect metadata, and signal options.
200 text/event-stream.Initial admission/timeout failures become
503; unacceptable coding becomes406; initial panic/application/size failures become ordinary bounded500responses. A successful initial
Emit,Wait, orEndmay commit.FIFO Roc executor. Parked sources use no Roc worker.
frames, timers, and queued execution are finite host resources. Active and
high-water SSE/Brotli gauges are exported through OpenMetrics.
SSE headers and
Vary: Accept-Encoding. Brotli uses fixed workers and lanes,recycled scratch, explicit per-event flush, clean normal finish, and
cancellation without finish.
transitions, reject new executor work, and drop eventual results from an
already-running synchronous transition while keeping it accounted until it
returns.
The enduring contract is in
design.md; the application and operational guideis
docs/sse.md.Correctness and ownership work
emitted-item drain, timer parking, cancellation, and normal end.
completion consumer. This prevents a one-worker/zero-queue stream from
rejecting its own first or immediately-following transition.
abandons Brotli rather than manufacturing a clean end.
Afteris capped at the documented 24-hour host timer bound, preventingcross-platform
Instantoverflow.by default, configurable through
Server.Config.with_sse_limits.capabilities from expired request-scoped resources such as
Server.Body.Roc versus Go evidence
The fixed-shape comparison and raw records live in
research/datastar-e2e/results/2026-08-03-operational.mdand its adjacentJSONL. Server and Python/curl clients are pinned to separate CPUs; timing
scenarios use one warmup and three samples.
requests, Roc ordinary p99 was 13.50 ms versus Go's 221.18 ms; Go completed
the SSE group in 221 ms versus Roc's 531 ms. The unified bounded pool trades
some aggregate event throughput for substantially better ordinary-request
fairness in this single-core workload.
102.33 ms for Roc and 110.84 ms for Go against a requested 100 ms.
503, recover after oneclose, and validate Brotli recovery with
Content-Encoding: br.Brotli lanes in both implementations.
cold-start ratios: identity is about 45.6 KB Roc versus 40.8 KB Go; Brotli is
about 49.3 KB Roc versus 75.5 KB Go.
Hot-path evidence remains one process/Roc allocation per pre-rendered event,
zero additional host hot allocations, and approximately Go-comparable matched
64 KiB Brotli behavior.
Validation
Waitheader commitment, precommitfailures, canonical Datastar output, identity/Brotli negotiation, and HTTP/2
5a5f4c02cross-build for arm64musl
release-matrix jobs
Deliberately deferred optimizations
Two ideas remain possible future measurements, not gates for this design:
Neither changes the application model, and corrected marginal-memory and
operational evidence does not currently justify taking either into this
research scope. If production evidence motivates more work, unified-pool
fairness versus aggregate transition throughput is the clearer next tuning
surface.