mirror of
https://github.com/simstudioai/sim.git
synced 2026-09-24 15:45:35 +08:00
fix(oauth): follower last-chance read after poll deadline (#4718)
* fix(oauth): follower last-chance read after poll deadline * test(oauth): exercise last-chance read in follower timeout test
This commit is contained in:
@@ -117,6 +117,30 @@ describe('withLeaderLock', () => {
|
||||
expect(onFollower.mock.calls.length).toBeGreaterThanOrEqual(2)
|
||||
})
|
||||
|
||||
it('follower does a final read after timeout to catch a just-finished leader', async () => {
|
||||
redisConfigMockFns.mockAcquireLock.mockResolvedValueOnce(false)
|
||||
|
||||
// pollInterval=5, maxWait=9 → loop exits after 2 in-loop polls (T+5, T+10);
|
||||
// the third call (polls=3) is the post-deadline last-chance read.
|
||||
let polls = 0
|
||||
const onFollower = vi.fn(async () => {
|
||||
polls += 1
|
||||
if (polls <= 2) return null
|
||||
return 'late-leader'
|
||||
})
|
||||
|
||||
const result = await withLeaderLock<string>({
|
||||
key: 'k',
|
||||
pollIntervalMs: 5,
|
||||
maxWaitMs: 9,
|
||||
onLeader: async () => 'should-not-run',
|
||||
onFollower,
|
||||
})
|
||||
|
||||
expect(result).toBe('late-leader')
|
||||
expect(onFollower).toHaveBeenCalledTimes(3)
|
||||
})
|
||||
|
||||
it('follower returns null after timeout', async () => {
|
||||
redisConfigMockFns.mockAcquireLock.mockResolvedValueOnce(false)
|
||||
|
||||
|
||||
@@ -64,6 +64,10 @@ export async function withLeaderLock<T>(opts: LeaderLockOptions<T>): Promise<T |
|
||||
if (value !== null) return value
|
||||
}
|
||||
|
||||
// The leader may have persisted between our final poll and now; one last check.
|
||||
const lastChance = await onFollower()
|
||||
if (lastChance !== null) return lastChance
|
||||
|
||||
logger.warn('Follower timed out waiting for leader', { key, maxWaitMs })
|
||||
return null
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user