Skip to content

fix(transport): notify every subscriber and expose failureSignal when a confirmed subscription dies - #93

Merged
joeblau merged 1 commit into
mainfrom
fix/issue-89
Aug 4, 2026
Merged

fix(transport): notify every subscriber and expose failureSignal when a confirmed subscription dies#93
joeblau merged 1 commit into
mainfrom
fix/issue-89

Conversation

@joeblau

@joeblau joeblau commented Aug 4, 2026

Copy link
Copy Markdown

Summary

  • _failSubscription now notifies every live confirmed lease (previously: first-live-owner only, and only with onError passed) — each onError isolated in its own try/catch
  • New optional failureSignal?: AbortSignal on ISubscription — aborts with the failure TransportError as reason when a confirmed subscription dies, never on voluntary unsubscribe(); lazily allocated (common path pays nothing), always provided by WebSocketTransport
  • Notification runs off a pre-recorded snapshot, so a callback that re-enters unsubscribe() on a sibling lease cannot rob it of its notification
  • Docs updated (clients.md, transports.md) and 8 new tests including re-entrancy and post-failure signal-access semantics

Verification (3-agent agreement)

  • Claude (Opus/Fable, this session): APPROVE after line-by-line review
  • Kimi K3 Max: APPROVE ("No material defects found")
  • Codex gpt-5.6-sol @ xhigh: APPROVE ("The two-pass snapshot correctly closes the re-entrancy hole... no material regression or missing requirement") — its round-1 re-entrancy finding drove the snapshot design
  • Integration: all four fix branches merged together pass bun run check + 1965 offline tests, 0 fail

Fixes #89

🤖 Generated with Claude Code

… a confirmed subscription dies

_failSubscription used to notify exactly one confirmed lease per listener
registration (first-live-owner) and only when that caller had passed
options.onError - every other subscriber sharing the payload, and any
subscriber without onError, lost its feed silently while unsubscribe()
still appeared to work.

- _failSubscription now notifies EVERY live confirmed lease's onError,
  each call wrapped in its own try/catch so one throwing callback cannot
  silence the rest; unconfirmed leases still observe the failure solely
  through their subscribe() rejection, and voluntarily retired leases are
  never notified.
- ISubscription gains an optional failureSignal?: AbortSignal that aborts
  with the failure TransportError as its reason when an already confirmed
  subscription fails, and never on a voluntary unsubscribe(). It is
  optional for back-compat with external ISubscriptionTransport
  implementations, but the WebSocket transport always provides it: the
  handle returned by WebSocketSubscriptionManager.subscribe() carries a
  lazily materialized per-call AbortController - accessed before the
  failure it aborts at failure time, first accessed after the failure it
  comes back already aborted with the same recorded reason, and the
  common path that never reads the signal allocates nothing. Subscription
  and explorer API methods return the transport handle unchanged, so the
  signal reaches the public API without threading.
- Updated the invalidated comments (first-live-owner ownership text,
  RegistrationHandle.confirmed, _failSubscription, subscribe() option
  docs in the manager, transport, and ISubscriptionTransport) plus
  docs/clients.md and docs/transports.md failure semantics.
- Tests: shared-payload failures fan out to every onError (same and
  different listeners), failureSignal aborts with the
  WebSocketRequestError, stays inert on voluntary unsubscribe() and for
  leases retired before the failure, and post-failure first access
  returns an already-aborted signal with the identical reason.

Fixes #89
@joeblau
joeblau merged commit 1197ee7 into main Aug 4, 2026
6 checks passed
@joeblau joeblau mentioned this pull request Aug 4, 2026
joeblau added a commit that referenced this pull request Aug 4, 2026
Four fixes, each cross-verified to agreement by three independent
reviewers (Claude, Kimi K3 Max, Codex gpt-5.6-sol xhigh):

- #89 subscription failures notify every subscriber + failureSignal (#93)
- #90 WebSocket message pacing on by default, flush charging fixed (#96)
- #91 200-OK { type: "error" } envelopes throw HttpRequestError (#94)
- #92 wallet shape detection by member presence, not arity (#95)

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@joeblau
joeblau deleted the fix/issue-89 branch August 4, 2026 05:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Subscription failure notifies only one handle via opt-in onError — feeds can die silently

1 participant