feat: add logical game clock
This commit is contained in:
@@ -14,7 +14,11 @@ const buildRedis = () => ({
|
||||
|
||||
const buildDb = (options: {
|
||||
updated: number;
|
||||
auction?: { status: 'OPEN' | 'FINALIZING' | 'FINISHED' | 'CANCELED'; closeAt: Date } | null;
|
||||
auction?: {
|
||||
status: 'OPEN' | 'FINALIZING' | 'FINISHED' | 'CANCELED';
|
||||
closeAt: Date;
|
||||
closeTick?: bigint | null;
|
||||
} | null;
|
||||
existingEvents?: Array<{
|
||||
requestId: string;
|
||||
target: 'ENGINE';
|
||||
@@ -69,6 +73,29 @@ describe('auction worker clock-shift race', () => {
|
||||
expect(transaction.inputEvent.create).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('requeues a tick-backed auction using its logical deadline score', async () => {
|
||||
const redis = buildRedis();
|
||||
const closeAt = new Date('2099-01-01T00:00:00.000Z');
|
||||
const { db } = buildDb({
|
||||
updated: 0,
|
||||
auction: { status: 'OPEN', closeAt, closeTick: 72_000_000n },
|
||||
});
|
||||
|
||||
await expect(
|
||||
processDueAuctionId({
|
||||
db,
|
||||
redis,
|
||||
timerKey: 'timer',
|
||||
historyKey: 'history',
|
||||
id: '7',
|
||||
nowMs: new Date('2042-01-01T00:00:00.000Z').getTime(),
|
||||
nowTick: 36_000_000,
|
||||
})
|
||||
).resolves.toBe('RESCHEDULED');
|
||||
|
||||
expect(redis.zAdd).toHaveBeenCalledWith('timer', [{ score: 72_000_000, value: '7' }]);
|
||||
});
|
||||
|
||||
it('commits the FINALIZING transition and durable command in one transaction before recording history', async () => {
|
||||
const redis = buildRedis();
|
||||
const closeAt = new Date('2026-07-30T11:00:00.000Z');
|
||||
|
||||
@@ -220,6 +220,25 @@ describe('tournament worker schedule compatibility', () => {
|
||||
expect(resolveNextAt(state)).toBe('2026-08-02T10:10:00.000Z');
|
||||
expect(resolveBettingCloseAt(state)).toBe('2026-08-02T11:00:00.000Z');
|
||||
});
|
||||
|
||||
it('uses the injected game clock, not the host wall clock, to close betting', async () => {
|
||||
const redis = new MemoryRedis();
|
||||
const store = new TournamentStore(redis, buildTournamentKeys('game-clock-deadline'));
|
||||
const bettingCloseAt = '2099-01-01T00:00:00.000Z';
|
||||
const state = createTournamentState({ stage: 6, bettingCloseAt, nextAt: bettingCloseAt });
|
||||
await store.setState(state);
|
||||
|
||||
const next = await applyPreBattleStage(
|
||||
store,
|
||||
createPrismaMock({ baseSeed: 'clock-seed' }),
|
||||
state,
|
||||
'clock-seed',
|
||||
createNoopDaemonTransport(),
|
||||
() => new Date('2100-01-01T00:00:00.000Z').getTime()
|
||||
);
|
||||
|
||||
expect(next).toMatchObject({ stage: 7, bettingCloseAt });
|
||||
});
|
||||
});
|
||||
|
||||
describe('tournament worker (in-memory)', () => {
|
||||
|
||||
Reference in New Issue
Block a user