Skip to content

Commit f50cb20

Browse files
committed
chore: Refactor CatchAllExecutor to improve error handling and validation
1 parent 4ac7327 commit f50cb20

File tree

3 files changed

+71
-9
lines changed

3 files changed

+71
-9
lines changed

src/backend-runner/_executors/catch-all.executor.ts

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,23 @@ import { Job } from 'bullmq';
66
import { BackendConfigV1Dto } from '../_dto/backend-config-v1.dto';
77
import { BackendResultInfoInterface, BackendResultInterface } from '../_interfaces/backend-result.interface';
88
import { BackendCodesEnum } from '../_interfaces/backend-codes.enum';
9-
import { validateOrReject } from 'class-validator';
9+
import { ValidationError, validateOrReject } from 'class-validator';
1010
import { BackendResultInfoDto } from '../_dto/backend-result-info.dto';
1111
import { plainToInstance } from 'class-transformer';
1212

13+
interface ValidationRecursive {
14+
[key: string]: string;
15+
}
16+
1317
export class CatchAllExecutor implements ExecutorInterface {
14-
public constructor(public service: BackendRunnerService) {}
18+
public constructor(public service: BackendRunnerService) { }
1519

1620
public async execute({ job }): Promise<ExecutorExecuteResponseInterface> {
1721
let status = 0;
1822
const data = [];
1923

24+
const numberOfBackends = this.service.backendsConfig.backendsConfigData.length;
25+
2026
for await (const backend of this.service.backendsConfig.backendsConfigData) {
2127
if (!backend.active) {
2228
this.service.logger.warn(`backend ${backend.name} is not active`);
@@ -32,6 +38,8 @@ export class CatchAllExecutor implements ExecutorInterface {
3238
this.service.logger.log('stop on Error');
3339
break;
3440
}
41+
42+
await job.updateProgress(100 / numberOfBackends);
3543
}
3644

3745
return {
@@ -49,7 +57,7 @@ export class CatchAllExecutor implements ExecutorInterface {
4957
try {
5058
if (process.status !== 0) {
5159
this.service.logger.error(`Error executing backend ${backend.name}`);
52-
const error = this.extractLastJsonImproved(process.error);
60+
const error = this.extractLastJsonImproved(process.error || process.output);
5361
const errorSchema = plainToInstance(BackendResultInfoDto, error);
5462
await validateOrReject(errorSchema);
5563

@@ -70,18 +78,34 @@ export class CatchAllExecutor implements ExecutorInterface {
7078
status: process.status,
7179
output,
7280
};
73-
} catch (e) {
74-
this.service.logger.error(`Error parsing JSON output from backend ${backend.name}`);
81+
} catch (errors) {
82+
console.log('errors', errors)
83+
let validations: ValidationRecursive = {};
84+
for (const error of errors) {
85+
validations = { ...validations, ...this.validationRecursive(error) };
86+
}
87+
88+
this.service.logger.error(`Invalid JSON response from backend ${backend.name}, erreur de validation : ${Object.keys(validations).join(', ')}`.trim());
7589

7690
return {
7791
backend: backend.name,
7892
status: BackendCodesEnum.INVALID_JSON_RESPONSE,
79-
message: `Invalid JSON response from backend: ${process.error || process.output}`,
93+
message: `Erreur de validation : ${Object.keys(validations).join(', ')}`.trim(),
94+
error: {
95+
status: BackendCodesEnum.INVALID_JSON_RESPONSE,
96+
message: `Erreur de validation : ${Object.keys(validations).join(', ')}`.trim(),
97+
data: validations,
98+
},
8099
};
81100
}
82101
}
83102

84103
private extractLastJsonImproved(stdout: string): BackendResultInfoInterface {
104+
if (!stdout) return {
105+
status: BackendCodesEnum.INVALID_JSON_RESPONSE,
106+
message: 'No output',
107+
}
108+
85109
const jsonCandidates = [];
86110
let braceCount = 0,
87111
inString = false,
@@ -113,6 +137,32 @@ export class CatchAllExecutor implements ExecutorInterface {
113137
}
114138
}
115139

140+
if (jsonCandidates.length === 0) return {
141+
status: BackendCodesEnum.INVALID_JSON_RESPONSE,
142+
message: 'No JSON output',
143+
}
144+
116145
return JSON.parse(jsonCandidates[jsonCandidates.length - 1]);
117146
}
147+
148+
private validationRecursive(error: ValidationError, prefix = ''): ValidationRecursive {
149+
let validations = {};
150+
if (error.constraints) {
151+
validations[`${prefix + error.property}`] = Object.values(error.constraints)[0];
152+
}
153+
if (error.children.length > 0) {
154+
for (const errorChild of error.children) {
155+
if (errorChild.constraints) {
156+
validations[`${prefix + error.property}.${errorChild.property}`] = Object.values(errorChild.constraints)[0];
157+
}
158+
if (errorChild.children.length > 0) {
159+
validations = {
160+
...validations,
161+
...this.validationRecursive(errorChild, `${prefix + error.property}.${errorChild.property}.`),
162+
};
163+
}
164+
}
165+
}
166+
return validations;
167+
}
118168
}

src/backend-runner/backend-runner.service.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { InjectRedis } from '@nestjs-modules/ioredis';
22
import { Injectable, Logger, OnApplicationBootstrap, OnModuleInit } from '@nestjs/common';
33
import { ConfigService } from '@nestjs/config';
4-
import { Worker } from 'bullmq';
4+
import { UnrecoverableError, Worker } from 'bullmq';
55
import { CatchAllExecutor } from './_executors/catch-all.executor';
66
import { ListBackendsExecutor } from './_executors/list-backends.executor';
77
import { ExecutorExecuteResponseInterface, ExecutorInterface } from './executors.interface';
@@ -50,7 +50,19 @@ export class BackendRunnerService implements OnApplicationBootstrap, OnModuleIni
5050
this.logger.log(`Job ${job.name} received. Try to execute...`);
5151

5252
const result = await this.executors.get(jobName).execute({ job });
53-
await job.updateProgress(100);
53+
this.logger.verbose(`Job ${job.name} executed with status ${result.status}`);
54+
55+
if (result.status !== 0) {
56+
this.logger.error(`Job ${job.name} failed with status ${result.status}`);
57+
const errMsg = []
58+
for (const data of result.data) {
59+
errMsg.push(data?.error?.message || 'No error message');
60+
}
61+
62+
throw new UnrecoverableError(`Job ${job.name} failed with status ${result.status}: ${errMsg.join(', ')}`);
63+
}
64+
65+
this.logger.log(`Job ${job.name} success with status ${result.status}`);
5466
return result;
5567
},
5668
{

src/backend-runner/executors.interface.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export interface ExecutorExecuteOptionsInterface {
88
export interface ExecutorExecuteResponseInterface {
99
jobId: string;
1010
status: number;
11-
data: object;
11+
data: Array<any>;
1212
}
1313

1414
export interface ExecutorInterface {

0 commit comments

Comments
 (0)