Skip to content

fix(onlion): read the newest pending entries, not the oldest - #120

Merged
wefio merged 1 commit into
mainfrom
fix/v1.4-newest-pending-window
Oct 28, 2026
Merged

wefio merged 1 commit into
mainfrom
fix/v1.4-newest-pending-window

Conversation

@wefio

@wefio wefio commented Oct 28, 2026

Copy link
Copy Markdown
Owner

What this fixes

The search window read the oldest pending entries. Measured on the deployed service with
twenty sequential Adds to one user (below the fold trigger, so nothing folded):

pending_entries = 20
marker  0 -> FOUND      marker  8 -> MISSING
marker  3 -> FOUND      marker 12 -> MISSING
marker  7 -> FOUND      marker 19 -> MISSING

The window held the first eight entries and hid the rest, and nothing recovers them: a search
never folds (by design), and the fold is triggered by the pending counter, which only moves on
Add. In steady state pending sits between 16 and 23, so the affected entries are the newest
8–15
- exactly the ones a streaming update just added.

The change

  • listPending takes an optional newest: it slices the tail of the key list before reading
    any body (names sort in arrival order, so skipped entries cost no GET) and returns the tail
    of the matches.
  • pendingForSearch passes it. The fold does not, so entries are still applied in arrival
    order.
  • One test pins both directions, because pinning only one would look correct.

Cost: the newest branch reads every body in its tail window before slicing, since the
generation filter must see them - up to about fifteen small objects per search at the observed
pending ceiling. That is latency traded for correctness, and it is the only thing to watch.

Verification

  • npm run verify in onlion: 34 PASS (the new assertion included), eslint clean.
  • docs:check passes; the decision record gained a section with the measurement above.
  • After deployment: the same marker experiment, expecting marker 19 to be FOUND.

The search window took the head of the arrival order, which is the fold's order and the
wrong one for reading: with twenty pending entries, markers 0-7 were found and 8-19 were
missing, and nothing recovers them because a search never folds and the fold is triggered
by the counter. The newest entries - the ones a streaming update just added - were exactly
the invisible ones.

`listPending` takes an optional `newest`, which slices the tail of the key list before any
body is read (names sort in arrival order, so no skipped entry costs a GET) and returns the
tail of the matches. The search path passes it; the fold does not, so entries are still
applied in the order they arrived. One test pins both directions.

Cost: the newest branch reads every body in its tail window before slicing, because the
generation filter has to see them - up to about fifteen small objects per search at the
observed pending ceiling.

Verified: npm run verify passes (34 PASS) and the live marker experiment after deployment.
@wefio
wefio merged commit 61c9b38 into main Oct 28, 2026
8 checks passed
@wefio
wefio deleted the fix/v1.4-newest-pending-window branch October 28, 2026 17:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant