feat: allow three cumulative selection timeouts per match

This commit is contained in:
2026-10-15 11:51:08 +09:00
parent fc5e475f24
commit 293ed7bcc4
14 changed files with 228 additions and 37 deletions
+4 -4
View File
@@ -414,7 +414,7 @@ test('finished matches retain results on reload then expire when abandoned', int
try {
await f.service.join('player-a', f.a.gameSessionId);
const id = (await f.service.join('player-b', f.b.gameSessionId)).match!.matchId;
await f.clock.advance(DEFAULT_GLOBAL_SETTINGS.matchingDelayMs + DEFAULT_GLOBAL_SETTINGS.matchSuccessDelayMs + MATCH_COUNTDOWN_MS + TURN_DURATION_MS);
await f.clock.advance(DEFAULT_GLOBAL_SETTINGS.matchingDelayMs + DEFAULT_GLOBAL_SETTINGS.matchSuccessDelayMs + MATCH_COUNTDOWN_MS + TURN_DURATION_MS * 3);
assert.equal((await f.service.status('player-a', f.a2.gameSessionId)).match?.finished?.reason, 'double_timeout');
await f.clock.advance(RANKED_FINISHED_TTL_MS - 1);
assert.equal((await f.service.status('player-a', f.a2.gameSessionId)).match?.matchId, id);
@@ -458,7 +458,7 @@ test('deadline rejects late actions and duplicate terminal writes survive an amb
await s.action('player-a', f.a.gameSessionId, id, 1, 'guard');
assert.equal((await s.leaderboard('player-a')).self, undefined);
// Jump to the deadline without executing timers: the request itself must settle it.
f.clock.time += TURN_DURATION_MS;
f.clock.time += TURN_DURATION_MS * 3;
await assert.rejects(s.action('player-b', f.b.gameSessionId, id, 1, 'guard'), /response lost after write/);
assert.equal((await s.profile('player-a')).stats.wins, 1);
assert.equal((await s.leaderboard('player-a')).self?.wins, 1);
@@ -509,7 +509,7 @@ test('timeouts progress without polling, unlock colors only from authoritative r
const id = (await s.join('player-b', b.gameSessionId)).match!.matchId;
await clock.advance(DEFAULT_GLOBAL_SETTINGS.matchingDelayMs + DEFAULT_GLOBAL_SETTINGS.matchSuccessDelayMs + MATCH_COUNTDOWN_MS);
await s.action('player-a', a.gameSessionId, id, 1, 'guard');
await clock.advance(TURN_DURATION_MS);
await clock.advance(TURN_DURATION_MS * 3);
assert.equal((await s.status('player-b', b.gameSessionId)).match?.finished?.reason, 'timeout');
await s.leave('player-a', a.gameSessionId, id); await s.leave('player-b', b.gameSessionId, id);
}
@@ -778,7 +778,7 @@ test('ranked timer reports only a safe failure code and retries persistence even
try {
await s.join('player-a', f.a.gameSessionId);
await s.join('player-b', f.b.gameSessionId);
await f.clock.advance(DEFAULT_GLOBAL_SETTINGS.matchingDelayMs + DEFAULT_GLOBAL_SETTINGS.matchSuccessDelayMs + MATCH_COUNTDOWN_MS + TURN_DURATION_MS);
await f.clock.advance(DEFAULT_GLOBAL_SETTINGS.matchingDelayMs + DEFAULT_GLOBAL_SETTINGS.matchSuccessDelayMs + MATCH_COUNTDOWN_MS + TURN_DURATION_MS * 3);
await logged;
assert.deepEqual(codes, ['RANKED_BACKGROUND_FAILED']);
assert.equal(await records.countDocuments(), 0);