From baed855c068793abe78eb1747575decc6b0c54c2 Mon Sep 17 00:00:00 2001 From: Chaos Zhou <672112429@qq.com> Date: Sun, 17 May 2026 18:30:47 +0800 Subject: [PATCH] fix: increment polling interval when GitHub device code flow returns slow_down --- src/renderer/routes/LoginWithDeviceFlow.tsx | 2 +- .../utils/forges/github/flows.test.ts | 19 +++++++++++++++++-- src/renderer/utils/forges/github/flows.ts | 7 ++++++- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/renderer/routes/LoginWithDeviceFlow.tsx b/src/renderer/routes/LoginWithDeviceFlow.tsx index 49c80f8bc..661fc3286 100644 --- a/src/renderer/routes/LoginWithDeviceFlow.tsx +++ b/src/renderer/routes/LoginWithDeviceFlow.tsx @@ -83,7 +83,6 @@ export const LoginWithDeviceFlowRoute: FC = () => { const startPolling = async () => { setIsPolling(true); - const intervalMs = Math.max(5000, session.intervalSeconds * 1000); try { while (isActive && Date.now() < session.expiresAt) { @@ -95,6 +94,7 @@ export const LoginWithDeviceFlowRoute: FC = () => { return; } + const intervalMs = Math.max(5000, session.intervalSeconds * 1000); await new Promise((resolve) => { timeoutId = setTimeout(resolve, intervalMs); }); diff --git a/src/renderer/utils/forges/github/flows.test.ts b/src/renderer/utils/forges/github/flows.test.ts index d5d316245..8d18913f5 100644 --- a/src/renderer/utils/forges/github/flows.test.ts +++ b/src/renderer/utils/forges/github/flows.test.ts @@ -102,15 +102,30 @@ describe('renderer/utils/forges/github/flows.ts', () => { expect(token).toBe('device-token-xyz'); }); - it('returns null when authorization is pending or slow_down', async () => { + it('returns null and does not change interval when authorization is pending', async () => { const pendingErr = Object.create(RequestError.prototype); pendingErr.response = { data: { error: 'authorization_pending' } }; exchangeDeviceCodeMock.mockRejectedValueOnce(pendingErr); - const token = await flows.pollGitHubDeviceFlow(baseSession as DeviceFlowSession); + const session = { ...baseSession } as DeviceFlowSession; + const token = await flows.pollGitHubDeviceFlow(session); + + expect(token).toBeNull(); + expect(session.intervalSeconds).toBe(5); + }); + + it('returns null and increases interval by 5 when slow_down', async () => { + const slowDownErr = Object.create(RequestError.prototype); + slowDownErr.response = { data: { error: 'slow_down' } }; + + exchangeDeviceCodeMock.mockRejectedValueOnce(slowDownErr); + + const session = { ...baseSession } as DeviceFlowSession; + const token = await flows.pollGitHubDeviceFlow(session); expect(token).toBeNull(); + expect(session.intervalSeconds).toBe(10); }); it('throws on other errors', async () => { diff --git a/src/renderer/utils/forges/github/flows.ts b/src/renderer/utils/forges/github/flows.ts index b6afc96cf..e13a2393b 100644 --- a/src/renderer/utils/forges/github/flows.ts +++ b/src/renderer/utils/forges/github/flows.ts @@ -141,7 +141,12 @@ export async function pollGitHubDeviceFlow(session: DeviceFlowSession): Promise< const response = err.response?.data as DeviceFlowErrorResponse; const errorCode = response.error; - if (errorCode === 'authorization_pending' || errorCode === 'slow_down') { + if (errorCode === 'authorization_pending') { + return null; + } + + if (errorCode === 'slow_down') { + session.intervalSeconds += 5; return null; } }