lease 상실 데몬을 종료하고 관리자에게 즉시 오류 기록

This commit is contained in:
2026-09-09 23:04:02 +00:00
parent d191960ea1
commit 09f4e60df4
4 changed files with 62 additions and 3 deletions
@@ -90,7 +90,20 @@ export class TurnDaemonLifecycle {
start(): Promise<void> {
if (!this.loopPromise) {
this.loopPromise = this.runLoop();
this.loopPromise = this.runLoop().catch(async (error: unknown) => {
// 초기화와 pause gate 실패도 관리자에게 즉시 남긴다. lease를
// 잃은 runtime은 대기 상태로 살아 있으면 안전하게 재개할 수 없다.
this.status.state = 'stopping';
this.status.running = false;
this.status.paused = true;
this.status.lastError = error instanceof Error ? error.message : 'Unknown lifecycle error.';
try {
await this.hooks?.onRunError?.(error);
} catch {
// 장애 기록 실패가 원래 종료 원인을 덮어쓰지 않게 한다.
}
throw error;
});
}
return this.loopPromise;
}
+8 -2
View File
@@ -93,7 +93,11 @@ import {
createResetOfficerLockHandler,
} from './monthlyCoreEventAction.js';
import { buildCommandEnv } from './reservedTurnCommands.js';
import { DatabaseTurnDaemonLease, TurnDaemonLeaseUnavailableError } from '../lifecycle/databaseTurnDaemonLease.js';
import {
DatabaseTurnDaemonLease,
TurnDaemonLeaseLostError,
TurnDaemonLeaseUnavailableError,
} from '../lifecycle/databaseTurnDaemonLease.js';
import { EngineStateManager } from './engineStateManager.js';
import { applyRuntimeClockShift } from './runtimeClockShift.js';
import { applyRuntimeGameSettings } from './runtimeGameSettings.js';
@@ -1060,7 +1064,9 @@ const createTurnDaemonRuntimeWithLease = async (
hooks,
pauseGate: async () => {
if (turnDaemonLease?.isLost()) {
return true;
// 만료된 owner는 재개 명령도 처리할 수 없다. 현재 runtime을
// 끝내 PM2가 새 owner와 DB snapshot으로 시작하도록 한다.
throw new TurnDaemonLeaseLostError(options.profileName ?? options.profile);
}
const gatewayPaused = (await pauseGate?.()) ?? false;
const phase = world.getGameClockState().phase;