-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(api): use scenario's blm in run service
- Loading branch information
Showing
10 changed files
with
231 additions
and
157 deletions.
There are no files selected for viewing
37 changes: 37 additions & 0 deletions
37
api/apps/api/src/modules/scenarios/marxan-run/cancel.handler.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { Inject, Injectable } from '@nestjs/common'; | ||
import { Job, Queue } from 'bullmq'; | ||
import { Either, left, right } from 'fp-ts/Either'; | ||
import { JobData } from '@marxan/scenario-run-queue'; | ||
import { isDefined } from '@marxan/utils'; | ||
import { runQueueToken } from './tokens'; | ||
|
||
export const notFound = Symbol('not found'); | ||
export type NotFound = typeof notFound; | ||
|
||
@Injectable() | ||
export class CancelHandler { | ||
constructor( | ||
@Inject(runQueueToken) | ||
private readonly queue: Queue<JobData>, | ||
) {} | ||
|
||
async cancel(scenarioId: string): Promise<Either<NotFound, void>> { | ||
const activeJobs: Job<JobData>[] = await this.queue.getJobs([ | ||
'active', | ||
'waiting', | ||
]); | ||
const scenarioJob = activeJobs.find( | ||
(job) => job.data.scenarioId === scenarioId, | ||
); | ||
if (!isDefined(scenarioJob)) return left(notFound); | ||
|
||
if (await scenarioJob.isActive()) | ||
await scenarioJob.updateProgress({ | ||
canceled: true, | ||
scenarioId, | ||
}); | ||
else if (await scenarioJob.isWaiting()) await scenarioJob.remove(); | ||
|
||
return right(void 0); | ||
} | ||
} |
86 changes: 86 additions & 0 deletions
86
api/apps/api/src/modules/scenarios/marxan-run/events.handler.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import { Inject, Injectable } from '@nestjs/common'; | ||
import { Job, Queue, QueueEvents } from 'bullmq'; | ||
import { JobData, ProgressData } from '@marxan/scenario-run-queue'; | ||
import { API_EVENT_KINDS } from '@marxan/api-events'; | ||
import { assertDefined } from '@marxan/utils'; | ||
import { ApiEventsService } from '@marxan-api/modules/api-events/api-events.service'; | ||
import { ScenarioRunProgressV1Alpha1DTO } from '@marxan-api/modules/api-events/dto/scenario-run-progress-v1-alpha-1'; | ||
import { runEventsToken, runQueueToken } from './tokens'; | ||
|
||
@Injectable() | ||
export class EventsHandler { | ||
constructor( | ||
@Inject(runQueueToken) | ||
private readonly queue: Queue<JobData>, | ||
@Inject(runEventsToken) | ||
queueEvents: QueueEvents, | ||
private readonly apiEvents: ApiEventsService, | ||
) { | ||
queueEvents.on(`completed`, ({ jobId }, eventId) => | ||
this.handleFinished(jobId, eventId), | ||
); | ||
queueEvents.on(`failed`, ({ jobId }, eventId) => | ||
this.handleFailed(jobId, eventId), | ||
); | ||
queueEvents.on( | ||
`progress`, | ||
async ( | ||
{ jobId, data }: { data: ProgressData; jobId: string }, | ||
eventId, | ||
) => { | ||
await this.handleProgress(jobId, eventId, data); | ||
}, | ||
); | ||
} | ||
|
||
private async handleProgress( | ||
jobId: string, | ||
eventId: string, | ||
progress: ProgressData | null, | ||
) { | ||
if ( | ||
typeof progress !== 'object' || | ||
progress === null || | ||
!('fractionalProgress' in progress) | ||
) | ||
return; | ||
const job = await this.getJob(jobId); | ||
const kind = API_EVENT_KINDS.scenario__run__progress__v1__alpha1; | ||
const eventData: ScenarioRunProgressV1Alpha1DTO = { | ||
kind, | ||
fractionalProgress: progress.fractionalProgress, | ||
}; | ||
await this.apiEvents.createIfNotExists({ | ||
topic: job.data.scenarioId, | ||
kind, | ||
externalId: eventId, | ||
data: eventData, | ||
}); | ||
} | ||
|
||
private async handleFinished(jobId: string, eventId: string) { | ||
const job = await this.getJob(jobId); | ||
const kind = API_EVENT_KINDS.scenario__run__finished__v1__alpha1; | ||
await this.apiEvents.createIfNotExists({ | ||
topic: job.data.scenarioId, | ||
kind, | ||
externalId: eventId, | ||
}); | ||
} | ||
|
||
private async handleFailed(jobId: string, eventId: string) { | ||
const job = await this.getJob(jobId); | ||
const kind = API_EVENT_KINDS.scenario__run__failed__v1__alpha1; | ||
await this.apiEvents.createIfNotExists({ | ||
topic: job.data.scenarioId, | ||
kind, | ||
externalId: eventId, | ||
}); | ||
} | ||
|
||
private async getJob(jobId: string): Promise<Job<JobData>> { | ||
const job = await this.queue.getJob(jobId); | ||
assertDefined(job); | ||
return job; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
export { RunService, notFound, NotFound } from './run.service'; | ||
export { RunService } from './run.service'; | ||
export { MarxanRunModule } from './marxan-run.module'; | ||
export { NotFound } from './cancel.handler'; | ||
export { notFound } from './cancel.handler'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 2 additions & 6 deletions
8
api/apps/api/src/modules/scenarios/marxan-run/run-service.providers.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
52 changes: 52 additions & 0 deletions
52
api/apps/api/src/modules/scenarios/marxan-run/run.handler.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { Inject, Injectable } from '@nestjs/common'; | ||
import { Queue } from 'bullmq'; | ||
import { Repository } from 'typeorm'; | ||
import { InjectRepository } from '@nestjs/typeorm'; | ||
|
||
import { JobData } from '@marxan/scenario-run-queue'; | ||
import { API_EVENT_KINDS } from '@marxan/api-events'; | ||
import { assertDefined } from '@marxan/utils'; | ||
import { ApiEventsService } from '@marxan-api/modules/api-events/api-events.service'; | ||
import { Scenario } from '../scenario.api.entity'; | ||
import { blmDefaultToken, runQueueToken } from './tokens'; | ||
import { AssetsService } from './assets.service'; | ||
|
||
@Injectable() | ||
export class RunHandler { | ||
constructor( | ||
@Inject(runQueueToken) | ||
private readonly queue: Queue<JobData>, | ||
private readonly apiEvents: ApiEventsService, | ||
@InjectRepository(Scenario) | ||
private readonly scenarios: Repository<Scenario>, | ||
private readonly assets: AssetsService, | ||
@Inject(blmDefaultToken) | ||
private readonly blmDefault: number, | ||
) {} | ||
|
||
async run( | ||
scenario: { | ||
id: string; | ||
boundaryLengthModifier?: number; | ||
}, | ||
overridingBlm?: number, | ||
): Promise<void> { | ||
const blm = | ||
overridingBlm ?? scenario.boundaryLengthModifier ?? this.blmDefault; | ||
const assets = await this.assets.forScenario(scenario.id, blm); | ||
assertDefined(assets); | ||
const job = await this.queue.add(`run-scenario`, { | ||
scenarioId: scenario.id, | ||
assets, | ||
}); | ||
await this.scenarios.update(scenario.id, { | ||
ranAtLeastOnce: true, | ||
}); | ||
const kind = API_EVENT_KINDS.scenario__run__submitted__v1__alpha1; | ||
await this.apiEvents.create({ | ||
topic: scenario.id, | ||
kind, | ||
externalId: job.id + kind, | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.