fix: 배포 중 화면 유지와 자동 재연결 적용

정상 DEPLOY 중에는 기존 정적 프론트엔드를 유지하고 새 artifact 준비 후 전환합니다. 게임 화면은 일시적인 gateway 오류를 별도 상태로 표시하고 읽기 전용 probe로 제한적으로 복구합니다.
This commit is contained in:
2026-08-27 02:08:44 +00:00
parent 9e01d24b5d
commit c1d5a80f79
13 changed files with 395 additions and 12 deletions
@@ -1857,7 +1857,7 @@ export class GatewayOrchestrator implements GatewayOrchestratorHandle {
await this.appendOperationLog(operationId, 'switch', '기존 profile process를 정지합니다.');
await assertLease();
await this.stopProfile(profile, assertLease);
await this.stopProfile(profile, assertLease, { preserveStaticFrontend: true });
oldRuntimeStopped = true;
const profileDatabaseUrl = this.resolveProfileDatabaseUrl(profile);
await this.appendOperationLog(operationId, 'migration', '선택 버전의 game migration을 적용합니다.');
@@ -2821,7 +2821,11 @@ export class GatewayOrchestrator implements GatewayOrchestratorHandle {
return false;
}
private async stopProfile(profile: GatewayProfileRecord, assertLease?: () => Promise<void>): Promise<void> {
private async stopProfile(
profile: GatewayProfileRecord,
assertLease?: () => Promise<void>,
options: { preserveStaticFrontend?: boolean } = {}
): Promise<void> {
const frontendName = buildProcessName(profile.profileName, 'frontend');
const apiName = buildProcessName(profile.profileName, 'api');
const daemonName = buildProcessName(profile.profileName, 'daemon');
@@ -2829,7 +2833,9 @@ export class GatewayOrchestrator implements GatewayOrchestratorHandle {
const battleSimName = buildProcessName(profile.profileName, 'battle-sim');
const tournamentName = buildProcessName(profile.profileName, 'tournament');
await assertLease?.();
if (this.frontendServeMode === 'static') {
// A normal DEPLOY keeps the last immutable page available while its API is replaced.
// STOP/RESET still remove the pointer because those operations intentionally close the profile.
if (this.frontendServeMode === 'static' && !options.preserveStaticFrontend) {
await this.artifactManager.deactivate(profile.profile);
}
await assertLease?.();