Skip to content

fix(fetchium): Recover relay after deactivation during in-flight refetch - #6

Merged
jimmy-phantom merged 3 commits into
mainfrom
jimmy/cor2-504-fetchium-relay-does-not-recover-after-deactivation-during
Apr 15, 2026
Merged

fix(fetchium): Recover relay after deactivation during in-flight refetch#6
jimmy-phantom merged 3 commits into
mainfrom
jimmy/cor2-504-fetchium-relay-does-not-recover-after-deactivation-during

Conversation

@jimmy-phantom

@jimmy-phantom jimmy-phantom commented Apr 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • When a relay deactivates mid-refetch, runDebounced() bails on reactivation because signalium's ReactivePromiseImpl still shows isPending=true from the doomed fetch. The AbortError then permanently poisons the relay to Rejected.
  • Detect the stale pending state (isPending && _abortController === undefined) on reactivation and call runQueryImmediately() instead, which replaces _promise so the old AbortError is silently discarded.
  • Add test covering the full lifecycle: deactivation during in-flight refetch followed by resubscription and recovery.

Test plan

  • New test "should recover after deactivation during in-flight refetch" passes
  • All 1125 existing tests pass (npm run test:unit)
  • Type check passes (npm run check-types)

🤖 Generated with Claude Code

jimmy-phantom and others added 3 commits April 10, 2026 10:39
When a relay deactivates mid-refetch, deactivate() aborts the fetch and
clears _abortController. The signalium ReactivePromiseImpl still shows
isPending=true until the AbortError settles async. On reactivation,
runDebounced() sees isPending=true and bails out, so no new fetch starts.
The AbortError then permanently poisons the relay to Rejected.

Detect this state (isPending && _abortController === undefined) on
reactivation and call runQueryImmediately() instead. The new setPromise()
call replaces _promise, causing the stale AbortError to hit signalium's
promise !== this._promise guard and be silently discarded.

Closes COR2-504

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

@pzuraq pzuraq left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My only thought is maybe it makes sense to set isPending false on abort, keeping the state “accurate”, but this seems ok too

@jimmy-phantom

Copy link
Copy Markdown
Collaborator Author

My only thought is maybe it makes sense to set isPending false on abort, keeping the state “accurate”, but this seems ok too

Signalium's RelayState does not currently offer a direct way to clear isPending since it is read-only. Would we want to add something like state.clearPending()?

@jimmy-phantom
jimmy-phantom merged commit f1145c8 into main Apr 15, 2026
1 check passed
@jimmy-phantom
jimmy-phantom deleted the jimmy/cor2-504-fetchium-relay-does-not-recover-after-deactivation-during branch April 21, 2026 16:12
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.

2 participants