fix: VM 시간 변경 후 턴 lease를 안전하게 자동 복구

This commit is contained in:
2026-09-15 23:05:33 +00:00
parent 7dc1670935
commit 4fb1343943
11 changed files with 224 additions and 45 deletions
@@ -184,6 +184,7 @@ export class DatabaseTurnDaemonLease {
if (!token || this.lost) {
throw this.getLossError();
}
// CURRENT_TIMESTAMP는 transaction 시작에 고정되어 VM 정지 중 만료를 놓친다.
const db = transaction ?? this.db;
const rows = await db.$queryRaw<LeaseRow[]>(GamePrisma.sql`
SELECT "profile", "owner_id", "fencing_epoch"
@@ -192,7 +193,7 @@ export class DatabaseTurnDaemonLease {
"profile" = ${token.profile}
AND "owner_id" = ${token.ownerId}
AND "fencing_epoch" = ${token.fencingEpoch}
AND "lease_until" > CURRENT_TIMESTAMP AT TIME ZONE 'UTC'
AND "lease_until" > clock_timestamp() AT TIME ZONE 'UTC'
FOR UPDATE
`);
if (rows.length === 0) {
@@ -240,7 +240,8 @@ export class TurnDaemonLifecycle {
const wallDeadline = await this.stateStore.projectGameDeadline?.(nextRunTime);
const command = await this.controlQueue.waitFor(
Math.max(0, wallDeadline ? wallDeadline.getTime() - nowMs : nextTurnMs - gameNowMs)
// 벽시계가 뒤로 이동해도 다음 턴까지 장시간 잠들지 않고 lease/gate를 다시 확인한다.
Math.min(1000, Math.max(0, wallDeadline ? wallDeadline.getTime() - nowMs : nextTurnMs - gameNowMs))
);
if (command) {
await this.handleCommand(command);