Skip to content

fix(bridge-redis): close subscribe-readiness race that could drop a live message#5

Merged
sharpTrick merged 1 commit into
mainfrom
fix/redis-subscribe-race
Jul 3, 2026
Merged

fix(bridge-redis): close subscribe-readiness race that could drop a live message#5
sharpTrick merged 1 commit into
mainfrom
fix/redis-subscribe-race

Conversation

@sharpTrick

Copy link
Copy Markdown
Owner

Fixes the intermittent Redis conformance failure seen on main (run) — and it was a real bug, not just a slow test.

Root cause

bridge-redis subscribe() started its XREAD loop at '$' and returned without awaiting the first (blocking) read (void loop()). '$' only resolves to the stream's last id when that read actually registers server-side. A post() (XADD) racing in during that startup window gets an id below the resolved '$' and is dropped forever — so the subscriber receives 0 messages (hence the 3s vi.waitFor timeout, not a late arrival). Rare; it slipped through under Node 24 CI load.

Fix

Capture a concrete stream tail id via XINFO STREAM, awaited before subscribe() resolves, and read strictly after it. A concrete id has no gap — XREAD returns everything after it, including messages added during startup. Falls back to '0' when the stream doesn't exist yet (no history to skip). Only touches packages/bridge-redis.

Verification

  • redis conformance suite: 20/20 consecutive runs green (was intermittently failing the live-push test).
  • Full npm test: 26 files passed / 5 skipped, Redis running for real.
  • tsc -b clean.

Note

fix: title → this cuts a 0.2.1 patch release on merge, republishing the corrected bridge-redis (with provenance), and returns main to green.

🤖 Generated with Claude Code

…ive message

subscribe() started its XREAD loop at '$' and returned without awaiting the
first (blocking) read. '$' only resolves to the stream's last id when that read
registers server-side, so a post() (XADD) racing in during the startup window
got an id below the resolved '$' and was dropped forever — it never reached the
subscriber. Surfaced as an intermittent failure of the "identical backendMsgId +
cursor via live push and via catch-up" conformance test under CI load (Node 24).

Fix: capture a concrete stream tail id via XINFO STREAM, awaited before
subscribe() resolves, and read strictly after it. A concrete id has no gap, so a
message added during startup is still delivered. Falls back to '0' when the
stream doesn't exist yet (no history to skip). Verified: redis conformance 20/20.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@sharpTrick sharpTrick merged commit d587ed4 into main Jul 3, 2026
3 checks passed
@sharpTrick sharpTrick deleted the fix/redis-subscribe-race branch July 3, 2026 11:31
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