지도 캐시는 coverage가 확인된 PostgreSQL map.world head만 사용하고 실패 시 전체 계산으로 복구한다. 토너먼트 Redis payload와 source revision은 Lua 한 번으로 갱신한다.
48 lines
1.7 KiB
TypeScript
48 lines
1.7 KiB
TypeScript
import { randomUUID } from 'node:crypto';
|
|
|
|
import { afterAll, beforeAll, describe, expect, it } from 'vitest';
|
|
import { createRedisConnector, resolveRedisConfigFromEnv, type RedisConnector } from '@sammo-ts/infra';
|
|
|
|
import { buildTournamentKeys } from '../src/tournament/keys.js';
|
|
import { TournamentStore } from '../src/tournament/store.js';
|
|
|
|
const integration = describe.skipIf(!process.env.REDIS_URL);
|
|
|
|
integration('TournamentStore Redis source revision', () => {
|
|
let connector: RedisConnector;
|
|
const profile = `test:tournament-revision:${randomUUID()}`;
|
|
const keys = buildTournamentKeys(profile);
|
|
|
|
beforeAll(async () => {
|
|
connector = createRedisConnector(resolveRedisConfigFromEnv());
|
|
await connector.connect();
|
|
});
|
|
|
|
afterAll(async () => {
|
|
if (!connector) return;
|
|
await connector.client.del([
|
|
keys.stateKey,
|
|
keys.participantsKey,
|
|
keys.matchesKey,
|
|
keys.bettingKey,
|
|
keys.sourceRevisionKey,
|
|
]);
|
|
await connector.disconnect();
|
|
});
|
|
|
|
it('commits concurrent payload writes with unique monotonic revisions', async () => {
|
|
const store = new TournamentStore(connector.client, keys);
|
|
const revisions = await Promise.all(
|
|
Array.from({ length: 20 }, (_, index) =>
|
|
store.setMatches([
|
|
{ id: index + 1, stage: 7, roundIndex: index, attackerId: 1, defenderId: 2 },
|
|
])
|
|
)
|
|
);
|
|
|
|
expect(new Set(revisions).size).toBe(20);
|
|
await expect(store.getSourceRevision()).resolves.toBe('20');
|
|
await expect(store.getMatches()).resolves.toHaveLength(1);
|
|
});
|
|
});
|