Skip to content

feat: transport-reset recovery for server restarts - #89

Closed
gmaclennan wants to merge 1 commit into
feat/backend-owned-lifecyclefrom
feat/transport-reset-v10
Closed

feat: transport-reset recovery for server restarts#89
gmaclennan wants to merge 1 commit into
feat/backend-owned-lifecyclefrom
feat/transport-reset-v10

Conversation

@gmaclennan

Copy link
Copy Markdown
Member

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 / notifyServicesClientTransportReset reject every in-flight call — manager, routing, and per-project — with a new TransportClosedError (code: 'RPC_TRANSPORT_CLOSED'), and resubscribeCoreClient / resubscribeServicesClient replay 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 in getProject. 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 new Project references survive a server restart test 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/resubscribe are 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 built feat/reject-pending-and-resubscribe branch: 50/50 tests, tsc, eslint, prettier clean.

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.
@gmaclennan

Copy link
Copy Markdown
Member Author

Superseded: the transport-reset helpers now live directly on #88's branch (notifyTransportReset/resubscribe, rejecting with the shipped RPC_CHANNEL_CLOSED code rather than a new error class). Closing so review happens in one place.

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