mirror of
https://github.com/stablyai/orca.git
synced 2026-09-27 16:02:35 +00:00
fix(ssh): bound the background provider-miss throttle map
The git and filesystem dispatchers pass every SSH connection id in the app, and scheduleSshProviderMissRecovery recorded each one before asking the owner whether it claimed the connection. Ids the recovery declined were therefore retained forever, and the stale entry also swallowed the next miss for that id until the interval elapsed. Consult the recovery first and record only once it accepts, and prune entries past the throttle interval (an expired entry no longer throttles anything).
This commit is contained in:
committed by
Neil
parent
d680f9eb10
commit
f47828d3cb
@@ -7,7 +7,8 @@ import { SSH_GIT_PROVIDER_UNAVAILABLE_MESSAGE, requireSshGitProvider } from './s
|
||||
import {
|
||||
recoverSshProviderMiss,
|
||||
scheduleSshProviderMissRecovery,
|
||||
setSshProviderMissRecovery
|
||||
setSshProviderMissRecovery,
|
||||
sshProviderMissRecoveryThrottleEntryCount
|
||||
} from './ssh-provider-miss-recovery'
|
||||
|
||||
const TARGET = 'runtime-ssh-orca-1'
|
||||
@@ -85,4 +86,32 @@ describe('scheduleSshProviderMissRecovery', () => {
|
||||
expect(recovery).toHaveBeenCalledWith('ssh-user-target')
|
||||
expect(recoverSshProviderMiss('ssh-user-target')).toBeUndefined()
|
||||
})
|
||||
|
||||
it('keeps re-consulting the owner for declined connections and retains none of them', () => {
|
||||
// Why: these dispatchers are called with every SSH connection id in the app, most of
|
||||
// which no owner claims. A declined id was never dialed, so there is nothing to back
|
||||
// off from — throttling it would both retain it forever and swallow the next miss.
|
||||
const recovery = vi.fn(() => undefined)
|
||||
setSshProviderMissRecovery(recovery)
|
||||
|
||||
scheduleSshProviderMissRecovery('ssh-user-a')
|
||||
scheduleSshProviderMissRecovery('ssh-user-a')
|
||||
scheduleSshProviderMissRecovery('ssh-user-b')
|
||||
|
||||
expect(recovery).toHaveBeenCalledTimes(3)
|
||||
expect(sshProviderMissRecoveryThrottleEntryCount()).toBe(0)
|
||||
})
|
||||
|
||||
it('prunes claimed connections once their throttle interval has passed', () => {
|
||||
setSshProviderMissRecovery(() => Promise.resolve())
|
||||
|
||||
scheduleSshProviderMissRecovery('runtime-ssh-orca-1')
|
||||
scheduleSshProviderMissRecovery('runtime-ssh-orca-2')
|
||||
expect(sshProviderMissRecoveryThrottleEntryCount()).toBe(2)
|
||||
|
||||
vi.advanceTimersByTime(5_000)
|
||||
scheduleSshProviderMissRecovery('runtime-ssh-orca-3')
|
||||
|
||||
expect(sshProviderMissRecoveryThrottleEntryCount()).toBe(1)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -40,14 +40,28 @@ export function scheduleSshProviderMissRecovery(connectionId: string): void {
|
||||
if (startedAt !== undefined && now - startedAt < BACKGROUND_RECOVERY_THROTTLE_MS) {
|
||||
return
|
||||
}
|
||||
backgroundRecoveryStartedAt.set(connectionId, now)
|
||||
// Why prune before recording: an expired entry no longer throttles anything, and these
|
||||
// dispatchers are called with every SSH connection id in the app.
|
||||
for (const [id, at] of backgroundRecoveryStartedAt) {
|
||||
if (now - at >= BACKGROUND_RECOVERY_THROTTLE_MS) {
|
||||
backgroundRecoveryStartedAt.delete(id)
|
||||
}
|
||||
}
|
||||
const pending = recovery(connectionId)
|
||||
if (!pending) {
|
||||
// Declined: the owner does not claim this connection, so there is nothing to throttle
|
||||
// and recording it would retain an id this map will never act on.
|
||||
return
|
||||
}
|
||||
backgroundRecoveryStartedAt.set(connectionId, now)
|
||||
pending.catch((error: unknown) => {
|
||||
console.warn(
|
||||
`[ssh] Background provider re-attach failed for ${connectionId}: ${error instanceof Error ? error.message : String(error)}`
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/** Test-only: the throttle map is a memory bound, which is not observable from behaviour. */
|
||||
export function sshProviderMissRecoveryThrottleEntryCount(): number {
|
||||
return backgroundRecoveryStartedAt.size
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user