72 lines
2.4 KiB
TypeScript
72 lines
2.4 KiB
TypeScript
import { describe, expect, it, vi } from 'vitest';
|
|
|
|
import type { GamePrismaClient } from '@sammo-ts/infra';
|
|
|
|
import { processDueAuctionId } from '../src/auction/worker.js';
|
|
|
|
const buildRedis = () => ({
|
|
zRangeByScore: vi.fn(async () => []),
|
|
zRangeWithScores: vi.fn(async () => []),
|
|
zAdd: vi.fn(async () => 1),
|
|
zRem: vi.fn(async () => 0),
|
|
zRemRangeByScore: vi.fn(async () => 0),
|
|
});
|
|
|
|
describe('auction worker clock-shift race', () => {
|
|
it('requeues an OPEN auction at its current DB deadline when an old due score loses the race', async () => {
|
|
const redis = buildRedis();
|
|
const closeAt = new Date('2026-07-30T12:15:00.000Z');
|
|
const db = {
|
|
$executeRaw: vi.fn(async () => 0),
|
|
auction: {
|
|
findFirst: vi.fn(async () => ({ closeAt })),
|
|
},
|
|
} as unknown as GamePrismaClient;
|
|
const sendCommand = vi.fn(async () => {});
|
|
|
|
await expect(
|
|
processDueAuctionId({
|
|
db,
|
|
redis,
|
|
timerKey: 'timer',
|
|
historyKey: 'history',
|
|
id: '7',
|
|
nowMs: new Date('2026-07-30T12:00:00.000Z').getTime(),
|
|
sendCommand,
|
|
})
|
|
).resolves.toBe('RESCHEDULED');
|
|
|
|
expect(redis.zAdd).toHaveBeenCalledTimes(1);
|
|
expect(redis.zAdd).toHaveBeenCalledWith('timer', [{ score: closeAt.getTime(), value: '7' }]);
|
|
expect(sendCommand).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('records history and finalizes only after the guarded DB transition succeeds', async () => {
|
|
const redis = buildRedis();
|
|
const db = {
|
|
$executeRaw: vi.fn(async () => 1),
|
|
auction: {
|
|
findFirst: vi.fn(),
|
|
},
|
|
} as unknown as GamePrismaClient;
|
|
const sendCommand = vi.fn(async () => {});
|
|
const nowMs = new Date('2026-07-30T12:00:00.000Z').getTime();
|
|
|
|
await expect(
|
|
processDueAuctionId({
|
|
db,
|
|
redis,
|
|
timerKey: 'timer',
|
|
historyKey: 'history',
|
|
id: '7',
|
|
nowMs,
|
|
sendCommand,
|
|
})
|
|
).resolves.toBe('FINALIZING');
|
|
|
|
expect(redis.zAdd).toHaveBeenCalledWith('history', [{ score: nowMs, value: '7' }]);
|
|
expect(db.auction.findFirst).not.toHaveBeenCalled();
|
|
expect(sendCommand).toHaveBeenCalledWith({ type: 'auctionFinalize', auctionId: 7 });
|
|
});
|
|
});
|