1 | import { Mutant } from '@stryker-mutator/api/core';
|
2 | import { Logger } from '@stryker-mutator/api/logging';
|
3 |
|
4 | import { ChildProcessCrashedError } from '../child-proxy/child-process-crashed-error.js';
|
5 | import { OutOfMemoryError } from '../child-proxy/out-of-memory-error.js';
|
6 | import { ResourceDecorator } from '../concurrent/index.js';
|
7 |
|
8 | import { CheckerResource } from './checker-resource.js';
|
9 |
|
10 | export class CheckerRetryDecorator extends ResourceDecorator<CheckerResource> implements CheckerResource {
|
11 | constructor(producer: () => CheckerResource, private readonly log: Logger) {
|
12 | super(producer);
|
13 | }
|
14 |
|
15 | public async check(checkerName: string, mutants: Mutant[]): ReturnType<CheckerResource['check']> {
|
16 | return this.tryAction(() => this.innerResource.check(checkerName, mutants));
|
17 | }
|
18 |
|
19 | public async group(checkerName: string, mutants: Mutant[]): ReturnType<CheckerResource['group']> {
|
20 | return this.tryAction(() => this.innerResource.group(checkerName, mutants));
|
21 | }
|
22 |
|
23 | private async tryAction<T>(act: () => Promise<T>): Promise<T> {
|
24 | try {
|
25 | return await act();
|
26 | } catch (error) {
|
27 | if (error instanceof ChildProcessCrashedError) {
|
28 | if (error instanceof OutOfMemoryError) {
|
29 | this.log.warn(`Checker process [${error.pid}] ran out of memory. Retrying in a new process.`);
|
30 | } else {
|
31 | this.log.warn(`Checker process [${error.pid}] crashed with exit code ${error.exitCode}. Retrying in a new process.`, error);
|
32 | }
|
33 | await this.recover();
|
34 | return act();
|
35 | } else {
|
36 | throw error; //oops
|
37 | }
|
38 | }
|
39 | }
|
40 | }
|
41 |
|
\ | No newline at end of file |