Skip to content

Latest commit

 

History

History
19 lines (16 loc) · 6.33 KB

sse-streaming.md

File metadata and controls

19 lines (16 loc) · 6.33 KB

sse-streaming — notes

Hand-written. ../harvested/sse-streaming.md is what the documents say; this file is what the implementation found, and it wins. Each entry names the harvested entry it answers by that entry's stable key.

Superseded

  • Only the BOM-consumed flag persists across Reader#next_event calls; the last event id and the current retry value do not. Supersedes sse-streaming/2dba42b0 ("The convenience view reuses one reader instance so per-stream state (consumed BOM, current retry value, last event id) is preserved across pulls"), harvested verbatim from design §7.2's parenthesis at docs/sdk-design-ruby/07-pagination-sse-and-serialization.md:79-84. SSE-16 is a MUST — "only the 'BOM already consumed' flag persists across calls; the last-event-id is NOT carried forward" — and SSE-38 is a MUST that the subsystem "MUST NOT persist a last-event-id across events"; carrying a "current retry value" across events is forbidden by the same "only". SSE-40's own canonical text says "per-stream state (e.g. BOM consumption)" and names nothing else. The view does reuse one reader instance, which is SSE-40's actual clause; what that preserves is the BOM flag. Built that way on 2026-09-20: Dexpace::SSE::Reader resets all five accumulators — id, event, data, comment and retry — at every dispatch, and gems/dexpace-core/test/dexpace/sse/reader_test.rb's DispatchTest asserts the two prohibitions directly ("nothing but the BOM flag persists across calls -- no carried retry value"; "no last-event-id is carried forward") beside the one persistence ("the BOM flag DOES persist"). review · docs/work/mvp/phase7/phase7b/2026-09-10-phase7b-server-sent-events-design.md · high · sha:manual-phase7b-sse16-only-bom
  • The SSE line machine is built over Dexpace::IO::BufferedSource#getbyte, not over phase 3a's #read_line_utf8, because IO-14 and SSE-2 disagree about a lone CR. Corrects sse-streaming/8c25db7d and sse-streaming/e98a0668 insofar as either reads as "the SSE machine sits on the hand-written line primitive": the reason both give is right — the primitive was hand-written rather than delegated to IO#gets because SSE-2 wants LF, CR and CRLF all recognised — but what phase 3a hand-wrote follows IO-14's grammar ("a lone '\r' not followed by '\n' MUST be kept as part of the line's content"; gems/dexpace-core/lib/dexpace/io/typed_reads.rb, read_line_utf8("a\rb\n") is "a\rb" on every supported Ruby), and SSE-2 requires that CR to terminate a line by itself. Post-processing a #read_line_utf8 result cannot rescue it either: a conforming CR-only stream contains no \n, so the method would buffer the whole stream before returning anything — the read-ahead SSE-39 forbids and the unbounded allocation the line cap exists to prevent. Built as Dexpace::SSE::LineReader (phase 7b, P7-20), which recognises the three terminators natively with a one-byte pushback; #read_line_utf8 ends v1 with no in-repository caller, and its YARD now says so. review · docs/work/mvp/phase7/phase7b/2026-09-10-phase7b-server-sent-events-design.md · high · sha:manual-phase7b-line-reader-not-read-line-utf8

Reference

  • sse-streaming/5f4803a0 and sse-streaming/b94ce49e are SSE-26 and SSE-40's rules, filed under PAGE-14 alone. Adds to both: the @viewed latch on the SSE view — "must not be taken twice over the same source … latching a @viewed flag on first call and raising on a second" — and the conclusion that the single-use guard is a SHOULD the port implements outright are the Ruby realisation of SSE-26 and SSE-40's second clause, and --req SSE-26 / --req SSE-40 return neither; a pagination author querying PAGE-14 receives two SSE rules instead. A harvest attribution artefact of a design sentence that mentions a neighbouring ID, not a defect in the rules. Built as Dexpace::SSE::Stream#take_view! (gems/dexpace-core/lib/dexpace/sse/stream.rb), one flag for both consumption shapes and the typed layer's, asserted in stream_test.rb's and typed_stream_test.rb's ViewTest classes. review · docs/work/mvp/phase7/phase7b/2026-09-10-phase7b-server-sent-events-checklist.md · high · sha:manual-phase7b-viewed-latch-attribution
  • sse-streaming/dff112ad is SSE-11's conclusion and not SSE-19's, and sse-streaming/7adc2212 is SSE-12's and not SSE-11's. Adds to both: the first files the 2^31−1 millisecond retry cap under (SSE-11, SSE-19), so --req SSE-19 returns an entry entirely about the retry field and nothing about line length — the corpus-level origin of the line-cap finding's mis-citation, which phase 7b's design (R4) corrects: the requirement obliging the line cap is SSE-19, a MAY, and SSE-11 is a MUST about the retry field's value. The second files the BOM lookahead under (SSE-12, SSE-11), the same artefact in the other direction. Built as two constants and two checklist rows: Dexpace::SSE::MAX_LINE_BYTES / MAX_EVENT_BYTES (SSE-19) and Dexpace::SSE::MAX_RETRY_MS (SSE-11), each YARD stating which cap it is not. review · docs/work/mvp/phase7/phase7b/2026-09-10-phase7b-server-sent-events-checklist.md · high · sha:manual-phase7b-cap-attribution
  • Enumerator#next on a fiber that died by exception starts #each over. Adds to sse-streaming/4d83311b (SSE-29) and to io-and-byte-streams' .over rule: after a Dexpace::IO::BufferedSource.over(chunked) has raised a mid-stream failure out of #getbyte, the NEXT #getbyte does not answer nil and does not raise a second time — the enumerator's fiber is dead, Enumerator#next creates a fresh one, and the body's #each runs again from its first chunk, so the pull re-delivers the stream's first byte. Measured on 2026-09-20 on 3.2.11, 3.3.12, 3.4.10 and 4.0.6 (gems/dexpace-core/test/dexpace/sse/matrix_facts_test.rb, "after a mid-stream failure BufferedSource.over's enumerator RESTARTS instead of ending"). The SSE facade never meets it because SSE-27's closed? check runs before every pull and the facade closed itself on the failure; a bare Reader driven again after a raise would. Phase 3a's residue, routed to phase 10's inbound list by phase 7b's checklist. review · docs/work/mvp/phase7/phase7b/2026-09-10-phase7b-server-sent-events-checklist.md · high · sha:manual-phase7b-enumerator-restart