feat: RedisTurnDaemonTransport에서 lastId 초기값을 '0-0'으로 변경 및 RedisCommandStream에서 블록 시간 제한 추가

This commit is contained in:
2026-01-18 07:38:00 +00:00
parent 879104622a
commit e3f7758187
4 changed files with 18 additions and 9 deletions
+2 -2
View File
@@ -77,7 +77,7 @@ export class RedisTurnDaemonTransport implements TurnDaemonTransport {
const requestId = await this.sendCommand(command); const requestId = await this.sendCommand(command);
const deadline = Date.now() + (timeoutMs ?? this.requestTimeoutMs); const deadline = Date.now() + (timeoutMs ?? this.requestTimeoutMs);
let lastId = '$'; let lastId = '0-0';
while (Date.now() < deadline) { while (Date.now() < deadline) {
const remaining = Math.max(1, deadline - Date.now()); const remaining = Math.max(1, deadline - Date.now());
@@ -116,7 +116,7 @@ export class RedisTurnDaemonTransport implements TurnDaemonTransport {
await this.sendCommand({ type: 'getStatus', requestId }); await this.sendCommand({ type: 'getStatus', requestId });
const deadline = Date.now() + (timeoutMs ?? this.requestTimeoutMs); const deadline = Date.now() + (timeoutMs ?? this.requestTimeoutMs);
let lastId = '$'; let lastId = '0-0';
while (Date.now() < deadline) { while (Date.now() < deadline) {
const remaining = Math.max(1, deadline - Date.now()); const remaining = Math.max(1, deadline - Date.now());
@@ -137,11 +137,12 @@ export class RedisTurnDaemonCommandStream implements TurnDaemonControlQueue, Tur
} }
const blockMs = deadlineMs === null ? 0 : Math.max(0, deadlineMs - Date.now()); const blockMs = deadlineMs === null ? 0 : Math.max(0, deadlineMs - Date.now());
const cappedBlockMs = deadlineMs === null ? 0 : Math.min(blockMs, 1000);
if (deadlineMs !== null && blockMs === 0) { if (deadlineMs !== null && blockMs === 0) {
return null; return null;
} }
const remote = await this.readRemoteCommands(blockMs); const remote = await this.readRemoteCommands(cappedBlockMs);
if (remote.length === 0) { if (remote.length === 0) {
return null; return null;
} }
+6 -2
View File
@@ -327,9 +327,13 @@ export const createDatabaseTurnHooks = async (
...nations ...nations
.filter((nation) => !createdNationIds.has(nation.id)) .filter((nation) => !createdNationIds.has(nation.id))
.map((nation) => .map((nation) =>
prisma.nation.update({ prisma.nation.upsert({
where: { id: nation.id }, where: { id: nation.id },
data: buildNationUpdate(nation), update: buildNationUpdate(nation),
create: {
id: nation.id,
...buildNationUpdate(nation),
},
}) })
), ),
...troops ...troops
@@ -100,11 +100,11 @@ const truncateSchema = async (schema: string) => {
const resetDatabase = async () => { const resetDatabase = async () => {
await ensureSchema('public'); await ensureSchema('public');
await ensureSchema('che'); await ensureSchema('che');
await execCommand('pnpm', ['--filter', '@sammo-ts/infra', 'prisma:db:push:gateway'], { await execCommand('pnpm', ['--filter', '@sammo-ts/infra', 'prisma:db:push:gateway', '--accept-data-loss'], {
...process.env, ...process.env,
POSTGRES_SCHEMA: 'public', POSTGRES_SCHEMA: 'public',
}); });
await execCommand('pnpm', ['--filter', '@sammo-ts/infra', 'prisma:db:push:game'], { await execCommand('pnpm', ['--filter', '@sammo-ts/infra', 'prisma:db:push:game', '--accept-data-loss'], {
...process.env, ...process.env,
POSTGRES_SCHEMA: 'che', POSTGRES_SCHEMA: 'che',
}); });
@@ -160,6 +160,7 @@ describe('integration initialization flow', () => {
beforeAll(async () => { beforeAll(async () => {
await loadEnv(); await loadEnv();
process.chdir(workspaceRoot);
await resetDatabase(); await resetDatabase();
await resetRedis(); await resetRedis();
@@ -188,7 +189,7 @@ describe('integration initialization flow', () => {
if (gatewayServer) { if (gatewayServer) {
await gatewayServer.app.close(); await gatewayServer.app.close();
} }
}); }, 30_000);
it('seeds scenario, creates users, and validates founding flow', async () => { it('seeds scenario, creates users, and validates founding flow', async () => {
if (!gatewayServer || !gameServer) { if (!gatewayServer || !gameServer) {
@@ -392,9 +393,12 @@ describe('integration initialization flow', () => {
const runTurn = async () => { const runTurn = async () => {
const status = await waitForStatus(); const status = await waitForStatus();
const prevRunAt = status.lastRunAt; const prevRunAt = status.lastRunAt;
const targetTime = status.nextTurnTime
? new Date(new Date(status.nextTurnTime).getTime() + 5 * 60_000).toISOString()
: new Date(Date.now() + 5 * 60_000).toISOString();
await gameClient.turnDaemon.run.mutate({ await gameClient.turnDaemon.run.mutate({
reason: 'manual', reason: 'manual',
targetTime: status.nextTurnTime ?? undefined, targetTime,
}); });
const deadline = Date.now() + 20_000; const deadline = Date.now() + 20_000;
while (Date.now() < deadline) { while (Date.now() < deadline) {