EmbeddedTransport ignores recordedSince's cursor and returns the whole journal#178
Merged
Merged
Conversation
`EmbeddedTransport` inherited `RiftTransport`'s cursor-less `recordedSince` default, which discards the `since` argument and answers with the whole journal when no clause is given, and refuses outright when one is. Because `SpaceImpl` always prepends a flow-id clause, every Space cursor read threw and every Imposter cursor read silently over-delivered. Delegate `recordedSince` and the scoped `clearRecorded` to the same in-process admin server the transport already starts for `replaceAllImposters` and `events`; the C-ABI carries neither the cursor nor the clauses. The unfiltered clear stays on the C-ABI so the common case never starts a server it does not need. Closes #175
This was referenced Jul 23, 2026
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.
What
EmbeddedTransportnow overridesrecordedSince(delegated unconditionally) and the scopedclearRecorded(int, List<MatchClause>), routing both to the lazily-started in-process admin server — the pattern #174/#177 established forevents(). The unfilteredclearRecorded(int)deliberately stays on the direct C-ABI.Two different failures on one transport, from one missing override:
| Call | Before | After |
|---|---|
|
Imposter#recordedPage/recordedSince| whole journal,sinceignored, empty cursor (silent) | real paged read, real cursor ||
Space#recordedPage/recordedSince|UnsupportedOperationException(loud) | works ||
Imposter#clearRecorded(match)|UnsupportedOperationException| works, genuinely scoped |Why
recordedSincedelegates unconditionally butclearRecordeddoes notrecordedSincehas an observable return the C-ABI cannot supply — the cursor. Answering the barerecordedPage()baseline from the C-ABI would report no cursor on the first read and a real one on the second, which is exactly the signal a tail is written to treat as "this transport cannot tail".RecordedCursorIT's"0 is a cursor, not an absence"assertion fails under a conditional split.clearRecordedisvoid— no observable difference — so the empty-clause case stays on the C-ABI and never starts a server it does not need. Both arms mean the same thing: an empty clause list makes the admin form emitDELETE .../savedRequestswith no query, which isrift_clear_recorded's own behaviour, and oneImposterManagerbacks both routes.Gate
Confirmed red first on the EMBEDDED conformance lane — 5 distinct failures, Skipped 0, one per acceptance criterion — by flipping the gates before implementing:
EventStreamIT: deleted the EMBEDDED fork soassertEquals(page.nextIndex(), pushed.index())holds on both lanes, and removed theneedsCursorSPAWN-only gate so the reconcile-loop test runs on embedded. Both were tripwires planted by EmbeddedTransport: delegate events() to the in-process admin server instead of throwing #177 to fail the day this landed.RecordedCursorIT,SpaceCursorIT,MatchClauseIT: un-gated from SPAWN-only tolane.isAvailable().MatchClauseITis the one that matters most: it proves the whole clause grammar survives the delegation — clause intersection, header wire-encoding with a space and an=, method/path clauses, case-sensitivity, and that a filtered tail's cursor advances past entries the filter rejected. Without it, "embedded can filter" would only have been proven for single-clause cases.EMBEDDED coverage: 7 → 12 tests. Both lanes 12/12, Skipped 0. Full
mvn verifygreen on JDK 17 and JDK 21;javadoc:javadocclean.Stale claims retired
This gap was asserted as fact in nine places. All corrected:
docs/events.md(reconcile warning, transport table, start-up-cost line),docs/spaces.md,docs/design/sdk-api.md(§8.1, §8.2, FFI-mapping list), and javadoc onRiftTransport.recordedSince,Imposter,Space,EmbeddedTransport, plus three "like the in-process FFI one" glosses in core tests and a doubly-stale comment inEmbeddedTransportIT.Known follow-up
engine()/gated()scaffolding is now duplicated across four conformance ITs. Extraction is a separate refactor, filed rather than bundled here.Closes #175