Skip to content

Commit 965817c

Browse files
committed
add jobs data + executor spawn async
1 parent 3c4c8eb commit 965817c

File tree

4 files changed

+78
-30
lines changed

4 files changed

+78
-30
lines changed

src/_common/tasks/executor.task.ts

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,35 +10,32 @@ export async function executorTask(
1010
options?: ExecutorConfigInterface,
1111
): Promise<ExecutorResponseInterface> {
1212
return new Promise((resolve, reject) => {
13-
const child = spawn(join(command), [], {
13+
const jobDataArg = JSON.stringify(job.data);
14+
const escapedJobDataArg = `'${jobDataArg.replace(/'/g, "'\\''")}'`;
15+
16+
const child = spawn(join(command), [escapedJobDataArg], {
1417
shell: options?.shell ?? true,
1518
});
1619

17-
let output = '';
18-
let error = '';
20+
let outputChunk = '';
21+
let errorChunk = '';
1922

20-
// Ecoute pour la sortie standard (stdout)
2123
child.stdout.on('data', (data) => {
2224
console.log(`stdout: ${data}`);
23-
output += data;
25+
outputChunk += data;
2426
});
2527

26-
// Ecoute pour la sortie d'erreur (stderr)
2728
child.stderr.on('data', (data) => {
2829
console.error(`stderr: ${data}`);
29-
error += data;
30+
errorChunk += data;
3031
});
3132

32-
// Envoyer les données de job au processus enfant
33-
child.stdin.write(JSON.stringify(job.data));
34-
child.stdin.end();
35-
3633
child.on('close', (code) => {
3734
console.log(`Le processus enfant s'est terminé avec le code ${code}`);
3835
resolve({
3936
status: code,
40-
output: output,
41-
error: error,
37+
output: outputChunk?.toString(),
38+
error: errorChunk?.toString(),
4239
});
4340
});
4441

@@ -47,13 +44,4 @@ export async function executorTask(
4744
reject(spawnError);
4845
});
4946
});
50-
/**const out = spawnSync(join(command), [], {
51-
input: JSON.stringify(job.data),
52-
shell: options?.shell ?? true,
53-
});
54-
return Promise.resolve({
55-
status: out.status,
56-
output: out.stdout?.toString(),
57-
error: out.stderr?.toString(),
58-
});**/
5947
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { IsEnum, IsObject, IsOptional, IsString } from 'class-validator';
2+
import { BackendCodesEnum } from '../_interfaces/backend-codes.enum';
3+
4+
export class BackendResultInfoDto {
5+
@IsEnum(BackendCodesEnum)
6+
public status: number;
7+
8+
@IsString()
9+
@IsOptional()
10+
public message?: string;
11+
12+
@IsObject()
13+
@IsOptional()
14+
public data?: object;
15+
}

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

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ import { ExecutorExecuteResponseInterface, ExecutorInterface } from '../executor
44
import { join } from 'path';
55
import { Job } from 'bullmq';
66
import { BackendConfigV1Dto } from '../_dto/backend-config-v1.dto';
7-
import { BackendResultInterface } from '../_interfaces/backend-result.interface';
7+
import { BackendResultInfoInterface, BackendResultInterface } from '../_interfaces/backend-result.interface';
88
import { BackendCodesEnum } from '../_interfaces/backend-codes.enum';
9+
import { validateOrReject } from 'class-validator';
10+
import { BackendResultInfoDto } from '../_dto/backend-result-info.dto';
11+
import { plainToInstance } from 'class-transformer';
912

1013
export class CatchAllExecutor implements ExecutorInterface {
1114
public constructor(public service: BackendRunnerService) {}
@@ -46,29 +49,70 @@ export class CatchAllExecutor implements ExecutorInterface {
4649
try {
4750
if (process.status !== 0) {
4851
this.service.logger.error(`Error executing backend ${backend.name}`);
52+
const error = this.extractLastJsonImproved(process.error);
53+
const errorSchema = plainToInstance(BackendResultInfoDto, error);
54+
await validateOrReject(errorSchema);
55+
4956
return {
5057
backend: backend.name,
5158
status: process.status,
52-
error: JSON.parse(process.output),
59+
error,
5360
};
5461
}
5562

5663
this.service.logger.log(`Backend ${backend.name} executed successfully`);
64+
const output = this.extractLastJsonImproved(process.output);
65+
const outputSchema = plainToInstance(BackendResultInfoDto, output);
66+
await validateOrReject(outputSchema);
67+
5768
return {
5869
backend: backend.name,
5970
status: process.status,
60-
output: JSON.parse(process.output),
71+
output,
6172
};
6273
} catch (e) {
6374
this.service.logger.error(`Error parsing JSON output from backend ${backend.name}`);
75+
6476
return {
6577
backend: backend.name,
6678
status: BackendCodesEnum.INVALID_JSON_RESPONSE,
67-
error: {
68-
status: BackendCodesEnum.INVALID_JSON_RESPONSE,
69-
message: process.error,
70-
},
79+
message: `Invalid JSON response from backend: ${process.error || process.output}`,
7180
};
7281
}
7382
}
83+
84+
private extractLastJsonImproved(stdout: string): BackendResultInfoInterface {
85+
const jsonCandidates = [];
86+
let braceCount = 0,
87+
inString = false,
88+
escape = false,
89+
currentJson = '';
90+
91+
for (const char of stdout) {
92+
if (escape) {
93+
escape = false;
94+
} else if (char === '\\') {
95+
escape = true;
96+
} else if (char === '"') {
97+
inString = !inString;
98+
} else if (!inString && char === '{') {
99+
braceCount++;
100+
if (braceCount === 1) {
101+
currentJson = char;
102+
continue;
103+
}
104+
} else if (!inString && char === '}') {
105+
braceCount--;
106+
}
107+
108+
if (braceCount > 0) currentJson += char;
109+
if (braceCount === 0 && currentJson !== '') {
110+
currentJson += char;
111+
jsonCandidates.push(currentJson);
112+
currentJson = '';
113+
}
114+
}
115+
116+
return JSON.parse(jsonCandidates[jsonCandidates.length - 1]);
117+
}
74118
}
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export interface BackendResultInterface {
22
backend: string;
33
status: number;
4+
message?: string;
45
output?: BackendResultInfoInterface;
56
error?: BackendResultInfoInterface;
67
}
@@ -9,4 +10,4 @@ export interface BackendResultInfoInterface {
910
status: number;
1011
message?: string;
1112
data?: object;
12-
}
13+
}

0 commit comments

Comments
 (0)