diff --git a/api/apps/api/src/modules/scenarios/marxan-run/events.handler.ts b/api/apps/api/src/modules/scenarios/marxan-run/events.handler.ts index 679d161f13..ca8568b7e5 100644 --- a/api/apps/api/src/modules/scenarios/marxan-run/events.handler.ts +++ b/api/apps/api/src/modules/scenarios/marxan-run/events.handler.ts @@ -102,6 +102,9 @@ export class EventsHandler { await this.apiEvents.createIfNotExists({ topic: job.data.scenarioId, kind, + data: { + reason: job.failedReason, + }, externalId: eventId, }); } diff --git a/api/apps/api/src/modules/scenarios/marxan-run/run.service.spec.ts b/api/apps/api/src/modules/scenarios/marxan-run/run.service.spec.ts index ddbac02cc1..d9aa060f30 100644 --- a/api/apps/api/src/modules/scenarios/marxan-run/run.service.spec.ts +++ b/api/apps/api/src/modules/scenarios/marxan-run/run.service.spec.ts @@ -142,6 +142,9 @@ test(`failed job`, async () => { await fixtures.ThenEventCreatedIfNotExisted( API_EVENT_KINDS.scenario__run__failed__v1__alpha1, `eventid1`, + { + reason: 'fail description', + }, ); }); @@ -261,8 +264,10 @@ async function getFixtures() { const fakeAssets = { forScenario: jest.fn(), }; + class FakeOutputRepository implements FieldsOf { db: ScenariosOutputResultsApiEntity[] = []; + async saveOutput(job: { returnvalue: ExecutionResult | undefined; data: { scenarioId: string }; @@ -275,6 +280,7 @@ async function getFixtures() { }); } } + const testingModule = await Test.createTestingModule({ providers: [ RunHandler, @@ -500,6 +506,7 @@ async function getFixtures() { data: { scenarioId: `scenario-1`, }, + failedReason: `fail description`, }; }); }, diff --git a/api/apps/geoprocessing/src/marxan-sandboxed-runner/marxan-run.ts b/api/apps/geoprocessing/src/marxan-sandboxed-runner/marxan-run.ts index 8674fc54bd..a82ca9e1dc 100644 --- a/api/apps/geoprocessing/src/marxan-sandboxed-runner/marxan-run.ts +++ b/api/apps/geoprocessing/src/marxan-sandboxed-runner/marxan-run.ts @@ -37,13 +37,10 @@ export class MarxanRun extends MarxanRunEmitter implements Cancellable { this.#process = spawn(workspace.marxanBinaryPath, { cwd: workspace.workingDirectory, }); - assertDefined(this.#process); - this.#process.stderr.on('data', (chunk) => { this.#stdError.push(chunk.toString()); }); - const progressWatcher = new Progress(); this.#process.stdout.on('data', (chunk) => { const currentProgress = progressWatcher.read(chunk); @@ -51,6 +48,27 @@ export class MarxanRun extends MarxanRunEmitter implements Cancellable { this.#stdOut.push(chunk.toString()); }); + this.#process.on( + `error`, + ( + error: + | Error + | { + errno: number; + code: number; + path: string; + syscall: string; + spawnargs: string[]; + }, + ) => { + this.emit('error', { + signal: undefined, + code: 'code' in error ? error.code : undefined, + stdError: ['message' in error ? error.message : ''], + }); + return; + }, + ); this.#process.on('exit', (code, signal) => { if (signal) { this.emit('error', { diff --git a/api/apps/geoprocessing/src/marxan-sandboxed-runner/marxan-sandbox-runner.service.ts b/api/apps/geoprocessing/src/marxan-sandboxed-runner/marxan-sandbox-runner.service.ts index 08abd7bb91..6dafd04d79 100644 --- a/api/apps/geoprocessing/src/marxan-sandboxed-runner/marxan-sandbox-runner.service.ts +++ b/api/apps/geoprocessing/src/marxan-sandboxed-runner/marxan-sandbox-runner.service.ts @@ -79,7 +79,7 @@ export class MarxanSandboxRunnerService { marxanRun.stdError, ); await workspace.cleanup(); - reject(result); + reject(JSON.stringify(result)); }); marxanRun.on('finished', async () => { try { diff --git a/api/apps/geoprocessing/src/modules/scenarios/run.worker.ts b/api/apps/geoprocessing/src/modules/scenarios/run.worker.ts index e03554600b..d4a160c3ec 100644 --- a/api/apps/geoprocessing/src/modules/scenarios/run.worker.ts +++ b/api/apps/geoprocessing/src/modules/scenarios/run.worker.ts @@ -22,6 +22,7 @@ export const runWorkerQueueNameProvider: ValueProvider = { export class RunWorker { private worker: Worker; private queueEvents: QueueEvents; + constructor( queueEventsBuilder: QueueEventsBuilder, workerBuilder: WorkerBuilder, @@ -29,7 +30,13 @@ export class RunWorker { private readonly marxanRunner: MarxanSandboxRunnerService, ) { this.worker = workerBuilder.build(queueName, { - process: (job) => this.run(job), + process: async (job) => { + try { + return await this.run(job); + } catch (error) { + throw new Error(JSON.stringify(error)); + } + }, }); this.queueEvents = queueEventsBuilder.buildQueueEvents(queueName); this.queueEvents.on(`progress`, ({ data }: { data: ProgressData }) => { diff --git a/api/apps/geoprocessing/test/integration/marxan-run/marxan-run.e2e-spec.ts b/api/apps/geoprocessing/test/integration/marxan-run/marxan-run.e2e-spec.ts index 1ff5df9374..db5b362d94 100644 --- a/api/apps/geoprocessing/test/integration/marxan-run/marxan-run.e2e-spec.ts +++ b/api/apps/geoprocessing/test/integration/marxan-run/marxan-run.e2e-spec.ts @@ -75,7 +75,7 @@ describe(`given input data is available`, () => { done(`Shouldn't finish Marxan run.`); }) .catch((error) => { - expect(error.signal).toEqual('SIGTERM'); + expect(JSON.parse(error).signal).toEqual('SIGTERM'); done(); });