Tolerate concurrent PM2 profile cleanup
This commit is contained in:
@@ -273,6 +273,9 @@ const parseInstallOptions = (
|
|||||||
const buildProcessName = (profileName: string, role: 'api' | 'daemon'): string =>
|
const buildProcessName = (profileName: string, role: 'api' | 'daemon'): string =>
|
||||||
`sammo:${profileName}:${role === 'api' ? 'game-api' : 'turn-daemon'}`;
|
`sammo:${profileName}:${role === 'api' ? 'game-api' : 'turn-daemon'}`;
|
||||||
|
|
||||||
|
const isMissingProcessError = (error: unknown): boolean =>
|
||||||
|
error instanceof Error && /process or namespace not found/i.test(error.message);
|
||||||
|
|
||||||
export const buildProcessDefinitions = (
|
export const buildProcessDefinitions = (
|
||||||
profile: GatewayProfileRecord,
|
profile: GatewayProfileRecord,
|
||||||
config: GatewayProcessConfig
|
config: GatewayProcessConfig
|
||||||
@@ -980,7 +983,9 @@ export class GatewayOrchestrator implements GatewayOrchestratorHandle {
|
|||||||
try {
|
try {
|
||||||
await this.processManager.delete(name);
|
await this.processManager.delete(name);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
failures.push(`${name}: ${error instanceof Error ? error.message : String(error)}`);
|
if (!isMissingProcessError(error)) {
|
||||||
|
failures.push(`${name}: ${error instanceof Error ? error.message : String(error)}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (failures.length > 0) {
|
if (failures.length > 0) {
|
||||||
|
|||||||
@@ -40,7 +40,8 @@ const createHarness = (
|
|||||||
operation: GatewayOperationRecord,
|
operation: GatewayOperationRecord,
|
||||||
failStart = false,
|
failStart = false,
|
||||||
failStop = false,
|
failStop = false,
|
||||||
processesPresent = true
|
processesPresent = true,
|
||||||
|
missingOnDelete = false
|
||||||
) => {
|
) => {
|
||||||
let nextOperation: GatewayOperationRecord | null = operation;
|
let nextOperation: GatewayOperationRecord | null = operation;
|
||||||
const statuses: string[] = [];
|
const statuses: string[] = [];
|
||||||
@@ -103,6 +104,9 @@ const createHarness = (
|
|||||||
},
|
},
|
||||||
delete: async (name) => {
|
delete: async (name) => {
|
||||||
deleted.push(name);
|
deleted.push(name);
|
||||||
|
if (missingOnDelete) {
|
||||||
|
throw new Error('process or namespace not found');
|
||||||
|
}
|
||||||
if (failStop) {
|
if (failStop) {
|
||||||
throw new Error('pm2 delete failed');
|
throw new Error('pm2 delete failed');
|
||||||
}
|
}
|
||||||
@@ -168,6 +172,15 @@ describe('GatewayOrchestrator first-class operations', () => {
|
|||||||
expect(harness.completions).toEqual(['SUCCEEDED']);
|
expect(harness.completions).toEqual(['SUCCEEDED']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('treats a process removed concurrently as a successful stop', async () => {
|
||||||
|
const harness = createHarness(buildOperation('STOP'), false, false, true, true);
|
||||||
|
|
||||||
|
await harness.orchestrator.runOperationsNow();
|
||||||
|
|
||||||
|
expect(harness.deleted).toEqual(['sammo:che:2:game-api', 'sammo:che:2:turn-daemon']);
|
||||||
|
expect(harness.completions).toEqual(['SUCCEEDED']);
|
||||||
|
});
|
||||||
|
|
||||||
it('records a failed start instead of reporting a false success', async () => {
|
it('records a failed start instead of reporting a false success', async () => {
|
||||||
const harness = createHarness(buildOperation('START'), true);
|
const harness = createHarness(buildOperation('START'), true);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user