feat: transport-reset recovery for server restarts - #89
Closed
gmaclennan wants to merge 1 commit into
Closed
Conversation
When the process hosting the server dies and restarts while the client stays alive (the Android foreground-service restart case), calls that were in flight hang until timeout and the restarted server has lost every event subscription. Add notifyCoreClientTransportReset / notifyServicesClientTransportReset (reject in-flight calls with a new TransportClosedError, code RPC_TRANSPORT_CLOSED) and resubscribeCoreClient / resubscribeServicesClient (replay event subscriptions once the transport is back up). The two phases are split deliberately: ON frames written into a still-down transport can nudge the native connection into a reconnect loop while the server stays down. Unlike the pre-v10 attempt (#87), no project wrappers are hard-closed and nothing is re-fetched: project channels are keyed by project id, which a restarted server serves identically, so held references stay valid and a replayed project subscription re-opens the project on the new server. Requires rpc-reflector >= 4.4 (rejectPending/resubscribe, digidem/rpc-reflector#52, unreleased) — the reset entry points throw a descriptive error on older versions; everything else is unaffected. Tests run against the built feat/reject-pending-and-resubscribe branch installed locally.
This was referenced Aug 19, 2026
Member
Author
|
Superseded: the transport-reset helpers now live directly on #88's branch ( |
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.
Stacked on #88; supersedes #87. The generic two-phase recovery for a server-process restart while the client stays alive (the Android FGS-kill case, digidem/comapeo-core-react-native#225/#226):
notifyCoreClientTransportReset/notifyServicesClientTransportResetreject every in-flight call — manager, routing, and per-project — with a newTransportClosedError(code: 'RPC_TRANSPORT_CLOSED'), andresubscribeCoreClient/resubscribeServicesClientreplay event subscriptions once the transport is back up. The phases stay split for the reason found in #87's review: ON frames written into a still-down transport can nudge the native connection into a reconnect loop.What #87 needed and this doesn't: hard-closing project wrappers,
emitLocal, and the reset-generation guard ingetProject. Under #88's stable project channels a restarted server serves the same channel ids, so held references stay valid and a replayed project subscription simply re-opens the project. The newProject references survive a server restarttest pins exactly the scenario (reminted ids after restart) that #87 could only handle by invalidating everything.Draft until digidem/rpc-reflector#52 is released:
createClient.rejectPending/resubscribeare unreleased; the reset entry points throw a descriptive error on rpc-reflector < 4.4 and the dependency bump lands here once the version exists. Local verification used the builtfeat/reject-pending-and-resubscribebranch: 50/50 tests,tsc,eslint,prettierclean.