-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRunner.ts
82 lines (64 loc) · 1.48 KB
/
Runner.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import { type Executable } from "./Executable.ts";
export class RunnerExecutionError extends Error {
constructor(
message: string,
readonly name: string,
readonly retryable = false,
) {
super(message);
}
}
/**
* A wrapper class for task runners.
*/
export class Runner<TPayload = unknown, TResult = unknown> {
#executionnCount = 0;
#successCount = 0;
#failureCount = 0;
#busy = false;
constructor(
readonly runner: Executable<TPayload, TResult>,
readonly name: string,
) {}
get busy() {
return this.#busy;
}
get executionCount() {
return this.#executionnCount;
}
get successCount() {
return this.#successCount;
}
get failureCount() {
return this.#failureCount;
}
async execute(payload: TPayload): Promise<TResult> {
if (this.#busy) {
throw new Error(`Runner ${this.name} is busy.`);
}
this.#busy = true;
try {
const result = await this.runner.execute(payload);
this.#successCount++;
await this.runner.onSuccess?.(result);
return result;
} catch (error) {
if (!(error instanceof Error)) {
throw error;
}
this.#failureCount++;
const retryable = await this.runner.onFailure?.(error);
throw new RunnerExecutionError(
error.message,
error.name,
retryable ?? true,
);
} finally {
this.#executionnCount++;
this.#busy = false;
}
}
dispose() {
return this.runner.dispose?.();
}
}