fix(gateway): 일시정지와 서버 중지 상태 계약 분리
This commit is contained in:
@@ -3,6 +3,7 @@ import { randomBytes } from 'node:crypto';
|
||||
import { TRPCError } from '@trpc/server';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { gatewayProfileCapabilities } from '@sammo-ts/common';
|
||||
import type { GatewayPrisma } from '@sammo-ts/infra';
|
||||
|
||||
import { procedure, router } from './trpc.js';
|
||||
@@ -2068,6 +2069,22 @@ export const adminRouter = router({
|
||||
message: 'Resume permission is required.',
|
||||
});
|
||||
}
|
||||
if (profile.currentScenario === null) {
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'An uninitialized profile must be reset before it can be resumed.',
|
||||
});
|
||||
}
|
||||
} else if (input.action === 'PAUSE' && profile.status !== 'RUNNING') {
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'Pause is allowed only for RUNNING profiles.',
|
||||
});
|
||||
} else if (input.action === 'STOP' && !gatewayProfileCapabilities(profile.status).runtimeExpected) {
|
||||
throw new TRPCError({
|
||||
code: 'BAD_REQUEST',
|
||||
message: 'Stop is allowed only while the profile runtime is available.',
|
||||
});
|
||||
} else if (input.action === 'OPEN_SURVEY') {
|
||||
if (!canOpenSurvey) {
|
||||
throw new TRPCError({
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { gatewayProfileCapabilities, type GatewayProfileCapabilities } from '@sammo-ts/common';
|
||||
import type { GatewayOrchestratorHandle } from '../orchestrator/gatewayOrchestrator.js';
|
||||
import type {
|
||||
GatewayProfileRecord,
|
||||
@@ -26,6 +27,9 @@ export type LobbyProfileStatus = {
|
||||
/** @deprecated Rollback-compatible mirror of currentScenario. */
|
||||
scenario: string;
|
||||
status: GatewayProfileStatus;
|
||||
lifecycle: GatewayProfileCapabilities & {
|
||||
dataInitialized: boolean;
|
||||
};
|
||||
apiPort: number;
|
||||
runtime: {
|
||||
apiRunning: boolean;
|
||||
@@ -94,6 +98,10 @@ export class RepositoryProfileStatusService implements GatewayProfileStatusServi
|
||||
currentScenario: row.currentScenario,
|
||||
scenario: row.scenario,
|
||||
status: row.status,
|
||||
lifecycle: {
|
||||
...gatewayProfileCapabilities(row.status),
|
||||
dataInitialized: row.currentScenario !== null,
|
||||
},
|
||||
apiPort: row.apiPort,
|
||||
runtime: runtimeMap.get(row.profileName) ?? {
|
||||
apiRunning: false,
|
||||
|
||||
@@ -5,6 +5,7 @@ import { createHash, randomBytes, randomUUID } from 'node:crypto';
|
||||
import { stripVTControlCharacters } from 'node:util';
|
||||
|
||||
import type { ScenarioInstallOptions } from '@sammo-ts/game-engine/scenario/scenarioSeeder.js';
|
||||
import { gatewayProfileCapabilities } from '@sammo-ts/common';
|
||||
import {
|
||||
createGamePostgresConnector,
|
||||
createRedisConnector,
|
||||
@@ -89,7 +90,7 @@ export const planProfileReconcile = (
|
||||
status: GatewayProfileStatus,
|
||||
runtime: ProfileRuntimeState
|
||||
): { shouldStart: boolean; shouldStop: boolean } => {
|
||||
if (status === 'RUNNING' || status === 'PREOPEN' || status === 'PAUSED' || status === 'COMPLETED') {
|
||||
if (gatewayProfileCapabilities(status).runtimeExpected) {
|
||||
return {
|
||||
shouldStart: !(
|
||||
runtime.frontendRunning &&
|
||||
@@ -1104,7 +1105,7 @@ export class GatewayOrchestrator implements GatewayOrchestratorHandle {
|
||||
return { ok: false, detail: 'build already in progress' };
|
||||
}
|
||||
this.buildInFlight = true;
|
||||
const shouldRun = ['RUNNING', 'PREOPEN', 'PAUSED', 'COMPLETED'].includes(profile.status);
|
||||
const shouldRun = gatewayProfileCapabilities(profile.status).runtimeExpected;
|
||||
const updateClaimedProfile = async (patch: GatewayClaimedProfileUpdate): Promise<GatewayProfileRecord> => {
|
||||
if (!this.repository.updateProfileForOperation) {
|
||||
throw new Error('Profile deploy requires lease-fenced profile updates.');
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
import { GATEWAY_PROFILE_STATUSES, type GatewayProfileStatus } from '@sammo-ts/common';
|
||||
import type { GatewayPrisma, GatewayPrismaClient } from '@sammo-ts/infra';
|
||||
|
||||
export const GATEWAY_PROFILE_STATUSES = [
|
||||
'RESERVED',
|
||||
'PREOPEN',
|
||||
'RUNNING',
|
||||
'PAUSED',
|
||||
'COMPLETED',
|
||||
'STOPPED',
|
||||
'DISABLED',
|
||||
] as const;
|
||||
export type GatewayProfileStatus = (typeof GATEWAY_PROFILE_STATUSES)[number];
|
||||
export { GATEWAY_PROFILE_STATUSES, type GatewayProfileStatus };
|
||||
|
||||
export const GATEWAY_BUILD_STATUSES = ['IDLE', 'QUEUED', 'RUNNING', 'FAILED', 'SUCCEEDED'] as const;
|
||||
export type GatewayBuildStatus = (typeof GATEWAY_BUILD_STATUSES)[number];
|
||||
|
||||
Reference in New Issue
Block a user