Make profile shutdown idempotent
This commit is contained in:
@@ -963,8 +963,12 @@ export class GatewayOrchestrator implements GatewayOrchestratorHandle {
|
||||
private async stopProfile(profile: GatewayProfileRecord): Promise<void> {
|
||||
const apiName = buildProcessName(profile.profileName, 'api');
|
||||
const daemonName = buildProcessName(profile.profileName, 'daemon');
|
||||
const existingNames = new Set((await this.processManager.list()).map((process) => process.name));
|
||||
const failures: string[] = [];
|
||||
for (const name of [apiName, daemonName]) {
|
||||
if (!existingNames.has(name)) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
await this.processManager.stop(name);
|
||||
} catch {
|
||||
|
||||
@@ -36,7 +36,12 @@ const buildOperation = (type: 'START' | 'STOP'): GatewayOperationRecord => ({
|
||||
updatedAt: '2026-07-25T01:00:00.000Z',
|
||||
});
|
||||
|
||||
const createHarness = (operation: GatewayOperationRecord, failStart = false, failStop = false) => {
|
||||
const createHarness = (
|
||||
operation: GatewayOperationRecord,
|
||||
failStart = false,
|
||||
failStop = false,
|
||||
processesPresent = true
|
||||
) => {
|
||||
let nextOperation: GatewayOperationRecord | null = operation;
|
||||
const statuses: string[] = [];
|
||||
const completions: GatewayOperationStatus[] = [];
|
||||
@@ -77,7 +82,13 @@ const createHarness = (operation: GatewayOperationRecord, failStart = false, fai
|
||||
retryOperation: async () => null,
|
||||
};
|
||||
const processManager: ProcessManager = {
|
||||
list: async () => [],
|
||||
list: async () =>
|
||||
processesPresent
|
||||
? [
|
||||
{ name: 'sammo:che:2:game-api', status: 'online' },
|
||||
{ name: 'sammo:che:2:turn-daemon', status: 'online' },
|
||||
]
|
||||
: [],
|
||||
start: async (definition) => {
|
||||
if (failStart) {
|
||||
throw new Error('pm2 unavailable');
|
||||
@@ -145,6 +156,17 @@ describe('GatewayOrchestrator first-class operations', () => {
|
||||
expect(harness.completions).toEqual(['SUCCEEDED']);
|
||||
});
|
||||
|
||||
it('treats an already stopped profile as a successful idempotent stop', async () => {
|
||||
const harness = createHarness(buildOperation('STOP'), false, false, false);
|
||||
|
||||
await harness.orchestrator.runOperationsNow();
|
||||
|
||||
expect(harness.statuses).toEqual(['STOPPED']);
|
||||
expect(harness.stopped).toEqual([]);
|
||||
expect(harness.deleted).toEqual([]);
|
||||
expect(harness.completions).toEqual(['SUCCEEDED']);
|
||||
});
|
||||
|
||||
it('records a failed start instead of reporting a false success', async () => {
|
||||
const harness = createHarness(buildOperation('START'), true);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user