-
Notifications
You must be signed in to change notification settings - Fork 477
/
BaseTask.ts
84 lines (68 loc) · 2.38 KB
/
BaseTask.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
83
84
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import Logger from '../logger/Logger';
import OnceTask from './OnceTask';
import Task from './Task';
import TaskStatus from './TaskStatus';
/*
* [[BaseTask]] provides common utilities for task implementations.
*/
export default abstract class BaseTask implements Task {
protected taskName = 'BaseTask';
private parentTask: Task | null = null;
private status: TaskStatus = TaskStatus.IDLE;
abstract run(): Promise<void>;
constructor(protected logger: Logger) {
this.run = this.baseRun.bind(this, this.run);
this.cancel = this.baseCancel.bind(this, this.cancel);
}
once(...dependencies: (Task | undefined)[]): OnceTask {
return new OnceTask(this.logger, this, dependencies);
}
cancel(): void {}
name(): string {
return this.parentTask ? `${this.parentTask.name()}/${this.taskName}` : this.taskName;
}
setParent(parentTask: Task): void {
this.parentTask = parentTask;
}
protected getStatus(): TaskStatus {
return this.status;
}
protected logAndThrow(message: string): void {
this.logger.info(message);
throw new Error(message);
}
private async baseRun(originalRun: () => Promise<void>): Promise<void> {
try {
const startTime = Date.now();
this.logger.info(`running task ${this.name()}`);
switch (this.status) {
case TaskStatus.RUNNING:
this.logAndThrow(`${this.name()} is already running`);
case TaskStatus.CANCELED:
this.logAndThrow(`${this.name()} was canceled before running`);
case TaskStatus.FINISHED:
this.logAndThrow(`${this.name()} was already finished`);
}
this.status = TaskStatus.RUNNING;
await originalRun.call(this);
this.logger.info(`${this.name()} took ${Math.round(Date.now() - startTime)} ms`);
} catch (err) {
throw err;
} finally {
if (this.status !== TaskStatus.CANCELED) {
this.status = TaskStatus.FINISHED;
}
}
}
private baseCancel(originalCancel: () => void): void {
if (this.status === TaskStatus.CANCELED || this.status === TaskStatus.FINISHED) {
this.logger.info(`Not canceling ${this.name()}: state is ${this.status}`);
return;
}
this.logger.info(`canceling task ${this.name()}`);
this.status = TaskStatus.CANCELED;
originalCancel.call(this);
}
}