Skip to content

Commit 6a7c4da

Browse files
committed
refactor(connection): remove stale client recovery fallback
The SOCKET_DIED fallback in the stale disconnect handler is unreachable: in every code path that reassigns this.xmpp, the state machine has already transitioned out of `connected` (via a synchronous SOCKET_DIED) before any stale disconnect can fire. The connect() guard from the previous commit eliminates the only remaining scenario.
1 parent f98b6d0 commit 6a7c4da

2 files changed

Lines changed: 8 additions & 20 deletions

File tree

packages/fluux-sdk/src/core/modules/Connection.test.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2783,21 +2783,23 @@ describe('XMPPClient Connection', () => {
27832783
expect(mockClientFactory).toHaveBeenCalled()
27842784
})
27852785

2786-
it('should force reconnect recovery when stale disconnect arrives while still connected', async () => {
2786+
it('should ignore stale disconnect without triggering reconnect', async () => {
27872787
// Simulate the race: internal xmpp ref was already replaced/nulled,
27882788
// but the old socket disconnect event arrives while machine is connected.
27892789
;(xmppClient.connection as any).xmpp = null
27902790

2791+
vi.mocked(mockStores.connection.setStatus).mockClear()
2792+
27912793
mockXmppClientInstance._emit('disconnect', {
27922794
clean: false,
27932795
reason: { code: 1006, reason: 'ECONNERROR' },
27942796
})
27952797

2796-
expect(mockStores.console.addEvent).toHaveBeenCalledWith(
2797-
'Socket closed from stale client while connected, forcing reconnect recovery',
2798-
'connection'
2799-
)
2800-
expect(mockStores.connection.setStatus).toHaveBeenCalledWith('reconnecting')
2798+
// Stale disconnect should be logged and ignored — no reconnect triggered.
2799+
// In every real code path, the machine has already transitioned out of
2800+
// `connected` before any stale disconnect arrives (SOCKET_DIED is sent
2801+
// synchronously before forceDestroyClient strips listeners).
2802+
expect(mockStores.connection.setStatus).not.toHaveBeenCalledWith('reconnecting')
28012803
})
28022804

28032805
it('should schedule reconnect after SM verify timeout without disconnect event', async () => {

packages/fluux-sdk/src/core/modules/Connection.ts

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1676,20 +1676,6 @@ export class Connection extends BaseModule {
16761676
)
16771677
}
16781678

1679-
// Recovery fallback: if the machine still believes we're connected
1680-
// when a stale disconnect arrives, force reconnect transition instead
1681-
// of silently staying in a wedged connected state.
1682-
// Skip if already in a terminal state (e.g. conflict, authFailed) — the
1683-
// stale socket close from the conflicted session must not trigger a
1684-
// reconnect that would create another resource conflict loop.
1685-
if (typeof machineState === 'object' && 'connected' in machineState && !this.isInTerminalState()) {
1686-
logWarn(`Stale disconnect arrived while machine still connected (state=${JSON.stringify(machineState)}${closeInfo})`)
1687-
this.stores.console.addEvent(
1688-
'Socket closed from stale client while connected, forcing reconnect recovery',
1689-
'connection'
1690-
)
1691-
this.sendMachineEvent({ type: 'SOCKET_DIED' }, 'disconnect:stale-connected')
1692-
}
16931679
return
16941680
}
16951681

0 commit comments

Comments
 (0)