@guanghechen/task 1.0.0-alpha.1 → 1.0.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,28 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [1.0.0-alpha.3](https://github.com/guanghechen/sora/compare/@guanghechen/task@1.0.0-alpha.2...@guanghechen/task@1.0.0-alpha.3) (2023-08-30)
7
+
8
+
9
+ ### Performance Improvements
10
+
11
+ * 🎨 reuse constants and types ([5efb70e](https://github.com/guanghechen/sora/commit/5efb70e6df130dc870ccb5add632291dcbd94809))
12
+
13
+
14
+
15
+
16
+
17
+ # [1.0.0-alpha.2](https://github.com/guanghechen/sora/compare/@guanghechen/task@1.0.0-alpha.1...@guanghechen/task@1.0.0-alpha.2) (2023-08-28)
18
+
19
+
20
+ ### Features
21
+
22
+ * ✨ add @guanghechen/error & refactor other sub packages ([c50e94d](https://github.com/guanghechen/sora/commit/c50e94de4b9e6d7fd635c10e202eb8bdc4f4f8dd))
23
+
24
+
25
+
26
+
27
+
6
28
  # 1.0.0-alpha.1 (2023-08-27)
7
29
 
8
30
 
package/lib/cjs/index.cjs CHANGED
@@ -1,51 +1,35 @@
1
1
  'use strict';
2
2
 
3
+ var constant = require('@guanghechen/constant');
4
+ var error = require('@guanghechen/error');
3
5
  var monitor = require('@guanghechen/monitor');
4
6
 
5
- exports.TaskStatus = void 0;
6
- (function (TaskStatus) {
7
- TaskStatus[TaskStatus["PENDING"] = 1] = "PENDING";
8
- TaskStatus[TaskStatus["RUNNING"] = 2] = "RUNNING";
9
- TaskStatus[TaskStatus["SUSPENDED"] = 4] = "SUSPENDED";
10
- TaskStatus[TaskStatus["CANCELLED"] = 8] = "CANCELLED";
11
- TaskStatus[TaskStatus["FAILED"] = 16] = "FAILED";
12
- TaskStatus[TaskStatus["FINISHED"] = 32] = "FINISHED";
13
- TaskStatus[TaskStatus["ATTEMPT_SUSPENDING"] = 64] = "ATTEMPT_SUSPENDING";
14
- TaskStatus[TaskStatus["ATTEMPT_RESUMING"] = 128] = "ATTEMPT_RESUMING";
15
- TaskStatus[TaskStatus["ATTEMPT_CANCELING"] = 256] = "ATTEMPT_CANCELING";
16
- TaskStatus[TaskStatus["ATTEMPT_FINISHING"] = 512] = "ATTEMPT_FINISHING";
17
- })(exports.TaskStatus || (exports.TaskStatus = {}));
18
- exports.TaskStrategy = void 0;
19
- (function (TaskStrategy) {
20
- TaskStrategy[TaskStrategy["ABORT_ON_ERROR"] = 1] = "ABORT_ON_ERROR";
21
- TaskStrategy[TaskStrategy["CONTINUE_ON_ERROR"] = 2] = "CONTINUE_ON_ERROR";
22
- })(exports.TaskStrategy || (exports.TaskStrategy = {}));
23
- const active = exports.TaskStatus.RUNNING |
24
- exports.TaskStatus.ATTEMPT_SUSPENDING |
25
- exports.TaskStatus.ATTEMPT_RESUMING;
26
- const alive = exports.TaskStatus.PENDING |
27
- exports.TaskStatus.RUNNING |
28
- exports.TaskStatus.SUSPENDED |
29
- exports.TaskStatus.ATTEMPT_SUSPENDING |
30
- exports.TaskStatus.ATTEMPT_RESUMING;
31
- const terminated = exports.TaskStatus.CANCELLED |
32
- exports.TaskStatus.FAILED |
33
- exports.TaskStatus.FINISHED;
7
+ function noop(..._args) { }
34
8
 
35
- const noop = () => { };
9
+ const active = constant.TaskStatusEnum.RUNNING |
10
+ constant.TaskStatusEnum.ATTEMPT_SUSPENDING |
11
+ constant.TaskStatusEnum.ATTEMPT_RESUMING;
12
+ const alive = constant.TaskStatusEnum.PENDING |
13
+ constant.TaskStatusEnum.RUNNING |
14
+ constant.TaskStatusEnum.SUSPENDED |
15
+ constant.TaskStatusEnum.ATTEMPT_SUSPENDING |
16
+ constant.TaskStatusEnum.ATTEMPT_RESUMING;
17
+ const terminated = constant.TaskStatusEnum.CANCELLED |
18
+ constant.TaskStatusEnum.FAILED |
19
+ constant.TaskStatusEnum.FINISHED;
36
20
  class TaskState {
37
21
  name;
22
+ _errorCollector;
38
23
  _monitors;
39
- _errorDetails;
40
24
  _status;
41
25
  constructor(name) {
42
26
  this.name = name;
27
+ this._errorCollector = new error.SoraErrorCollector(name);
43
28
  this._monitors = {
44
29
  onAddError: new monitor.Monitor('onAddError'),
45
30
  onStatusChange: new monitor.Monitor('onStatusChange'),
46
31
  };
47
- this._errorDetails = [];
48
- this._status = exports.TaskStatus.PENDING;
32
+ this._status = constant.TaskStatusEnum.PENDING;
49
33
  }
50
34
  get status() {
51
35
  return this._status;
@@ -60,12 +44,12 @@ class TaskState {
60
44
  return (this._status & terminated) > 0;
61
45
  }
62
46
  get hasError() {
63
- return this._errorDetails.length > 0;
47
+ return this._errorCollector.size > 0;
64
48
  }
65
49
  get error() {
66
- if (this._errorDetails.length === 0)
50
+ if (this._errorCollector.size === 0)
67
51
  return undefined;
68
- return { from: this.name, details: this._errorDetails.slice() };
52
+ return { from: this.name, details: this._errorCollector.errors };
69
53
  }
70
54
  set status(status) {
71
55
  const curStatus = this._status;
@@ -84,12 +68,8 @@ class TaskState {
84
68
  if (this.terminated)
85
69
  return noop;
86
70
  const { onAddError, onStatusChange } = monitor;
87
- const unsubscribeOnAddError = onAddError
88
- ? this._monitors.onAddError.subscribe(onAddError)
89
- : noop;
90
- const unsubscribeOnStatusChange = onStatusChange
91
- ? this._monitors.onStatusChange.subscribe(onStatusChange)
92
- : noop;
71
+ const unsubscribeOnAddError = this._monitors.onAddError.subscribe(onAddError);
72
+ const unsubscribeOnStatusChange = this._monitors.onStatusChange.subscribe(onStatusChange);
93
73
  return () => {
94
74
  unsubscribeOnAddError();
95
75
  unsubscribeOnStatusChange();
@@ -98,30 +78,30 @@ class TaskState {
98
78
  check(nextStatus) {
99
79
  const status = this._status;
100
80
  switch (nextStatus) {
101
- case exports.TaskStatus.PENDING:
81
+ case constant.TaskStatusEnum.PENDING:
102
82
  return false;
103
- case exports.TaskStatus.RUNNING:
104
- return status === exports.TaskStatus.PENDING || status === exports.TaskStatus.ATTEMPT_RESUMING;
105
- case exports.TaskStatus.SUSPENDED:
106
- return status === exports.TaskStatus.ATTEMPT_SUSPENDING;
107
- case exports.TaskStatus.CANCELLED:
108
- return status === exports.TaskStatus.ATTEMPT_CANCELING;
109
- case exports.TaskStatus.FAILED:
110
- return (status !== exports.TaskStatus.PENDING &&
111
- status !== exports.TaskStatus.SUSPENDED &&
83
+ case constant.TaskStatusEnum.RUNNING:
84
+ return status === constant.TaskStatusEnum.PENDING || status === constant.TaskStatusEnum.ATTEMPT_RESUMING;
85
+ case constant.TaskStatusEnum.SUSPENDED:
86
+ return status === constant.TaskStatusEnum.ATTEMPT_SUSPENDING;
87
+ case constant.TaskStatusEnum.CANCELLED:
88
+ return status === constant.TaskStatusEnum.ATTEMPT_CANCELING;
89
+ case constant.TaskStatusEnum.FAILED:
90
+ return (status !== constant.TaskStatusEnum.PENDING &&
91
+ status !== constant.TaskStatusEnum.SUSPENDED &&
112
92
  (status & terminated) === 0);
113
- case exports.TaskStatus.FINISHED:
114
- return (status !== exports.TaskStatus.PENDING &&
115
- status !== exports.TaskStatus.SUSPENDED &&
93
+ case constant.TaskStatusEnum.FINISHED:
94
+ return (status !== constant.TaskStatusEnum.PENDING &&
95
+ status !== constant.TaskStatusEnum.SUSPENDED &&
116
96
  (status & terminated) === 0);
117
- case exports.TaskStatus.ATTEMPT_SUSPENDING:
118
- return status === exports.TaskStatus.RUNNING;
119
- case exports.TaskStatus.ATTEMPT_RESUMING:
120
- return status === exports.TaskStatus.SUSPENDED;
121
- case exports.TaskStatus.ATTEMPT_CANCELING:
97
+ case constant.TaskStatusEnum.ATTEMPT_SUSPENDING:
98
+ return status === constant.TaskStatusEnum.RUNNING;
99
+ case constant.TaskStatusEnum.ATTEMPT_RESUMING:
100
+ return status === constant.TaskStatusEnum.SUSPENDED;
101
+ case constant.TaskStatusEnum.ATTEMPT_CANCELING:
122
102
  return (status & alive) > 0;
123
- case exports.TaskStatus.ATTEMPT_FINISHING:
124
- return status !== exports.TaskStatus.PENDING && (status & alive) > 0;
103
+ case constant.TaskStatusEnum.ATTEMPT_FINISHING:
104
+ return status !== constant.TaskStatusEnum.PENDING && (status & alive) > 0;
125
105
  default:
126
106
  return false;
127
107
  }
@@ -129,13 +109,13 @@ class TaskState {
129
109
  cleanup() {
130
110
  if (!this.terminated)
131
111
  throw new Error(`[cleanup] task(${this.name}) is not terminated`);
132
- this._errorDetails.length = 0;
112
+ this._errorCollector.cleanup();
133
113
  this._monitors.onStatusChange.destroy();
134
114
  this._monitors.onAddError.destroy();
135
115
  }
136
- _addError(type, error) {
137
- this._errorDetails.push({ type, error });
138
- this._monitors.onAddError.notify(type, error);
116
+ _addError(type, error, level = constant.ErrorLevelEnum.ERROR) {
117
+ this._errorCollector.add(type, error, level);
118
+ this._monitors.onAddError.notify(type, error, level);
139
119
  }
140
120
  }
141
121
 
@@ -146,15 +126,15 @@ class AtomicTask extends TaskState {
146
126
  this._promise = undefined;
147
127
  }
148
128
  async start() {
149
- if (this.status === exports.TaskStatus.PENDING) {
150
- this.status = exports.TaskStatus.RUNNING;
129
+ if (this.status === constant.TaskStatusEnum.PENDING) {
130
+ this.status = constant.TaskStatusEnum.RUNNING;
151
131
  this._promise = this.run()
152
132
  .then(() => {
153
- this.status = exports.TaskStatus.FINISHED;
133
+ this.status = constant.TaskStatusEnum.FINISHED;
154
134
  })
155
135
  .catch(error => {
156
- this.status = exports.TaskStatus.FAILED;
157
136
  this._addError('AtomicTaskError', error);
137
+ this.status = constant.TaskStatusEnum.FAILED;
158
138
  });
159
139
  }
160
140
  return this._promise;
@@ -166,20 +146,20 @@ class AtomicTask extends TaskState {
166
146
  await this._promise;
167
147
  }
168
148
  async cancel() {
169
- if (this.status === exports.TaskStatus.PENDING) {
170
- this.status = exports.TaskStatus.ATTEMPT_CANCELING;
171
- this.status = exports.TaskStatus.CANCELLED;
149
+ if (this.status === constant.TaskStatusEnum.PENDING) {
150
+ this.status = constant.TaskStatusEnum.ATTEMPT_CANCELING;
151
+ this.status = constant.TaskStatusEnum.CANCELLED;
172
152
  return;
173
153
  }
174
154
  if (this.alive)
175
- this.status = exports.TaskStatus.ATTEMPT_CANCELING;
155
+ this.status = constant.TaskStatusEnum.ATTEMPT_CANCELING;
176
156
  await this._promise;
177
157
  }
178
158
  async finish() {
179
- if (this.status === exports.TaskStatus.PENDING)
159
+ if (this.status === constant.TaskStatusEnum.PENDING)
180
160
  await this.start();
181
161
  if (this.alive)
182
- this.status = exports.TaskStatus.ATTEMPT_FINISHING;
162
+ this.status = constant.TaskStatusEnum.ATTEMPT_FINISHING;
183
163
  await this._promise;
184
164
  }
185
165
  }
@@ -197,63 +177,63 @@ class ResumableTask extends TaskState {
197
177
  this._step = undefined;
198
178
  }
199
179
  async start() {
200
- if (this.status === exports.TaskStatus.PENDING) {
201
- this.status = exports.TaskStatus.RUNNING;
180
+ if (this.status === constant.TaskStatusEnum.PENDING) {
181
+ this.status = constant.TaskStatusEnum.RUNNING;
202
182
  this._execution = this.run();
203
183
  this.launchStep();
204
184
  await this._step;
205
185
  }
206
186
  }
207
187
  async pause() {
208
- if (this.status === exports.TaskStatus.RUNNING) {
209
- this.status = exports.TaskStatus.ATTEMPT_SUSPENDING;
188
+ if (this.status === constant.TaskStatusEnum.RUNNING) {
189
+ this.status = constant.TaskStatusEnum.ATTEMPT_SUSPENDING;
210
190
  await this._step;
211
- if (this.status === exports.TaskStatus.ATTEMPT_SUSPENDING) {
212
- this.status = exports.TaskStatus.SUSPENDED;
191
+ if (this.status === constant.TaskStatusEnum.ATTEMPT_SUSPENDING) {
192
+ this.status = constant.TaskStatusEnum.SUSPENDED;
213
193
  }
214
194
  }
215
195
  }
216
196
  async resume() {
217
- if (this.status === exports.TaskStatus.SUSPENDED) {
218
- this.status = exports.TaskStatus.ATTEMPT_RESUMING;
197
+ if (this.status === constant.TaskStatusEnum.SUSPENDED) {
198
+ this.status = constant.TaskStatusEnum.ATTEMPT_RESUMING;
219
199
  await this._step;
220
- if (this.status === exports.TaskStatus.ATTEMPT_RESUMING) {
221
- this.status = exports.TaskStatus.RUNNING;
200
+ if (this.status === constant.TaskStatusEnum.ATTEMPT_RESUMING) {
201
+ this.status = constant.TaskStatusEnum.RUNNING;
222
202
  this.queueStep();
223
203
  }
224
204
  }
225
205
  }
226
206
  async cancel() {
227
207
  if (this.alive) {
228
- this.status = exports.TaskStatus.ATTEMPT_CANCELING;
208
+ this.status = constant.TaskStatusEnum.ATTEMPT_CANCELING;
229
209
  await this._step;
230
- if (this.status === exports.TaskStatus.ATTEMPT_CANCELING) {
231
- this.status = exports.TaskStatus.CANCELLED;
210
+ if (this.status === constant.TaskStatusEnum.ATTEMPT_CANCELING) {
211
+ this.status = constant.TaskStatusEnum.CANCELLED;
232
212
  }
233
213
  }
234
214
  }
235
215
  async finish() {
236
- if (this.status === exports.TaskStatus.PENDING)
216
+ if (this.status === constant.TaskStatusEnum.PENDING)
237
217
  await this.start();
238
218
  if (this.alive) {
239
- this.status = exports.TaskStatus.ATTEMPT_FINISHING;
219
+ this.status = constant.TaskStatusEnum.ATTEMPT_FINISHING;
240
220
  await this._step;
241
221
  const execution = this._execution;
242
222
  if (execution) {
243
- while (this.status === exports.TaskStatus.ATTEMPT_FINISHING) {
223
+ while (this.status === constant.TaskStatusEnum.ATTEMPT_FINISHING) {
244
224
  const step = execution.next();
245
225
  if (step.done) {
246
- this.status = this.hasError ? exports.TaskStatus.FAILED : exports.TaskStatus.FINISHED;
226
+ this.status = this.hasError ? constant.TaskStatusEnum.FAILED : constant.TaskStatusEnum.FINISHED;
247
227
  break;
248
228
  }
249
229
  await step.value.catch(error => {
250
230
  this._addError('ResumableTaskError', error);
251
231
  switch (this.strategy) {
252
- case exports.TaskStrategy.ABORT_ON_ERROR:
232
+ case constant.TaskStrategyEnum.ABORT_ON_ERROR:
253
233
  if (!this.terminated)
254
- this.status = exports.TaskStatus.FAILED;
234
+ this.status = constant.TaskStatusEnum.FAILED;
255
235
  break;
256
- case exports.TaskStrategy.CONTINUE_ON_ERROR:
236
+ case constant.TaskStrategyEnum.CONTINUE_ON_ERROR:
257
237
  break;
258
238
  }
259
239
  });
@@ -262,10 +242,10 @@ class ResumableTask extends TaskState {
262
242
  }
263
243
  }
264
244
  launchStep() {
265
- if (this.status === exports.TaskStatus.RUNNING && this._step === undefined && this._execution) {
245
+ if (this.status === constant.TaskStatusEnum.RUNNING && this._step === undefined && this._execution) {
266
246
  const step = this._execution.next();
267
247
  if (step.done) {
268
- this.status = this.hasError ? exports.TaskStatus.FAILED : exports.TaskStatus.FINISHED;
248
+ this.status = this.hasError ? constant.TaskStatusEnum.FAILED : constant.TaskStatusEnum.FINISHED;
269
249
  return;
270
250
  }
271
251
  this._step = step.value
@@ -277,11 +257,11 @@ class ResumableTask extends TaskState {
277
257
  this._step = undefined;
278
258
  this._addError('ResumableTaskError', error);
279
259
  switch (this.strategy) {
280
- case exports.TaskStrategy.ABORT_ON_ERROR:
260
+ case constant.TaskStrategyEnum.ABORT_ON_ERROR:
281
261
  if (!this.terminated)
282
- this.status = exports.TaskStatus.FAILED;
262
+ this.status = constant.TaskStatusEnum.FAILED;
283
263
  break;
284
- case exports.TaskStrategy.CONTINUE_ON_ERROR:
264
+ case constant.TaskStrategyEnum.CONTINUE_ON_ERROR:
285
265
  this.queueStep();
286
266
  break;
287
267
  }
@@ -296,6 +276,3 @@ class ResumableTask extends TaskState {
296
276
  exports.AtomicTask = AtomicTask;
297
277
  exports.ResumableTask = ResumableTask;
298
278
  exports.TaskState = TaskState;
299
- exports.active = active;
300
- exports.alive = alive;
301
- exports.terminated = terminated;
package/lib/esm/index.mjs CHANGED
@@ -1,49 +1,33 @@
1
+ import { TaskStatusEnum, ErrorLevelEnum, TaskStrategyEnum } from '@guanghechen/constant';
2
+ import { SoraErrorCollector } from '@guanghechen/error';
1
3
  import { Monitor } from '@guanghechen/monitor';
2
4
 
3
- var TaskStatus;
4
- (function (TaskStatus) {
5
- TaskStatus[TaskStatus["PENDING"] = 1] = "PENDING";
6
- TaskStatus[TaskStatus["RUNNING"] = 2] = "RUNNING";
7
- TaskStatus[TaskStatus["SUSPENDED"] = 4] = "SUSPENDED";
8
- TaskStatus[TaskStatus["CANCELLED"] = 8] = "CANCELLED";
9
- TaskStatus[TaskStatus["FAILED"] = 16] = "FAILED";
10
- TaskStatus[TaskStatus["FINISHED"] = 32] = "FINISHED";
11
- TaskStatus[TaskStatus["ATTEMPT_SUSPENDING"] = 64] = "ATTEMPT_SUSPENDING";
12
- TaskStatus[TaskStatus["ATTEMPT_RESUMING"] = 128] = "ATTEMPT_RESUMING";
13
- TaskStatus[TaskStatus["ATTEMPT_CANCELING"] = 256] = "ATTEMPT_CANCELING";
14
- TaskStatus[TaskStatus["ATTEMPT_FINISHING"] = 512] = "ATTEMPT_FINISHING";
15
- })(TaskStatus || (TaskStatus = {}));
16
- var TaskStrategy;
17
- (function (TaskStrategy) {
18
- TaskStrategy[TaskStrategy["ABORT_ON_ERROR"] = 1] = "ABORT_ON_ERROR";
19
- TaskStrategy[TaskStrategy["CONTINUE_ON_ERROR"] = 2] = "CONTINUE_ON_ERROR";
20
- })(TaskStrategy || (TaskStrategy = {}));
21
- const active = TaskStatus.RUNNING |
22
- TaskStatus.ATTEMPT_SUSPENDING |
23
- TaskStatus.ATTEMPT_RESUMING;
24
- const alive = TaskStatus.PENDING |
25
- TaskStatus.RUNNING |
26
- TaskStatus.SUSPENDED |
27
- TaskStatus.ATTEMPT_SUSPENDING |
28
- TaskStatus.ATTEMPT_RESUMING;
29
- const terminated = TaskStatus.CANCELLED |
30
- TaskStatus.FAILED |
31
- TaskStatus.FINISHED;
5
+ function noop(..._args) { }
32
6
 
33
- const noop = () => { };
7
+ const active = TaskStatusEnum.RUNNING |
8
+ TaskStatusEnum.ATTEMPT_SUSPENDING |
9
+ TaskStatusEnum.ATTEMPT_RESUMING;
10
+ const alive = TaskStatusEnum.PENDING |
11
+ TaskStatusEnum.RUNNING |
12
+ TaskStatusEnum.SUSPENDED |
13
+ TaskStatusEnum.ATTEMPT_SUSPENDING |
14
+ TaskStatusEnum.ATTEMPT_RESUMING;
15
+ const terminated = TaskStatusEnum.CANCELLED |
16
+ TaskStatusEnum.FAILED |
17
+ TaskStatusEnum.FINISHED;
34
18
  class TaskState {
35
19
  name;
20
+ _errorCollector;
36
21
  _monitors;
37
- _errorDetails;
38
22
  _status;
39
23
  constructor(name) {
40
24
  this.name = name;
25
+ this._errorCollector = new SoraErrorCollector(name);
41
26
  this._monitors = {
42
27
  onAddError: new Monitor('onAddError'),
43
28
  onStatusChange: new Monitor('onStatusChange'),
44
29
  };
45
- this._errorDetails = [];
46
- this._status = TaskStatus.PENDING;
30
+ this._status = TaskStatusEnum.PENDING;
47
31
  }
48
32
  get status() {
49
33
  return this._status;
@@ -58,12 +42,12 @@ class TaskState {
58
42
  return (this._status & terminated) > 0;
59
43
  }
60
44
  get hasError() {
61
- return this._errorDetails.length > 0;
45
+ return this._errorCollector.size > 0;
62
46
  }
63
47
  get error() {
64
- if (this._errorDetails.length === 0)
48
+ if (this._errorCollector.size === 0)
65
49
  return undefined;
66
- return { from: this.name, details: this._errorDetails.slice() };
50
+ return { from: this.name, details: this._errorCollector.errors };
67
51
  }
68
52
  set status(status) {
69
53
  const curStatus = this._status;
@@ -82,12 +66,8 @@ class TaskState {
82
66
  if (this.terminated)
83
67
  return noop;
84
68
  const { onAddError, onStatusChange } = monitor;
85
- const unsubscribeOnAddError = onAddError
86
- ? this._monitors.onAddError.subscribe(onAddError)
87
- : noop;
88
- const unsubscribeOnStatusChange = onStatusChange
89
- ? this._monitors.onStatusChange.subscribe(onStatusChange)
90
- : noop;
69
+ const unsubscribeOnAddError = this._monitors.onAddError.subscribe(onAddError);
70
+ const unsubscribeOnStatusChange = this._monitors.onStatusChange.subscribe(onStatusChange);
91
71
  return () => {
92
72
  unsubscribeOnAddError();
93
73
  unsubscribeOnStatusChange();
@@ -96,30 +76,30 @@ class TaskState {
96
76
  check(nextStatus) {
97
77
  const status = this._status;
98
78
  switch (nextStatus) {
99
- case TaskStatus.PENDING:
79
+ case TaskStatusEnum.PENDING:
100
80
  return false;
101
- case TaskStatus.RUNNING:
102
- return status === TaskStatus.PENDING || status === TaskStatus.ATTEMPT_RESUMING;
103
- case TaskStatus.SUSPENDED:
104
- return status === TaskStatus.ATTEMPT_SUSPENDING;
105
- case TaskStatus.CANCELLED:
106
- return status === TaskStatus.ATTEMPT_CANCELING;
107
- case TaskStatus.FAILED:
108
- return (status !== TaskStatus.PENDING &&
109
- status !== TaskStatus.SUSPENDED &&
81
+ case TaskStatusEnum.RUNNING:
82
+ return status === TaskStatusEnum.PENDING || status === TaskStatusEnum.ATTEMPT_RESUMING;
83
+ case TaskStatusEnum.SUSPENDED:
84
+ return status === TaskStatusEnum.ATTEMPT_SUSPENDING;
85
+ case TaskStatusEnum.CANCELLED:
86
+ return status === TaskStatusEnum.ATTEMPT_CANCELING;
87
+ case TaskStatusEnum.FAILED:
88
+ return (status !== TaskStatusEnum.PENDING &&
89
+ status !== TaskStatusEnum.SUSPENDED &&
110
90
  (status & terminated) === 0);
111
- case TaskStatus.FINISHED:
112
- return (status !== TaskStatus.PENDING &&
113
- status !== TaskStatus.SUSPENDED &&
91
+ case TaskStatusEnum.FINISHED:
92
+ return (status !== TaskStatusEnum.PENDING &&
93
+ status !== TaskStatusEnum.SUSPENDED &&
114
94
  (status & terminated) === 0);
115
- case TaskStatus.ATTEMPT_SUSPENDING:
116
- return status === TaskStatus.RUNNING;
117
- case TaskStatus.ATTEMPT_RESUMING:
118
- return status === TaskStatus.SUSPENDED;
119
- case TaskStatus.ATTEMPT_CANCELING:
95
+ case TaskStatusEnum.ATTEMPT_SUSPENDING:
96
+ return status === TaskStatusEnum.RUNNING;
97
+ case TaskStatusEnum.ATTEMPT_RESUMING:
98
+ return status === TaskStatusEnum.SUSPENDED;
99
+ case TaskStatusEnum.ATTEMPT_CANCELING:
120
100
  return (status & alive) > 0;
121
- case TaskStatus.ATTEMPT_FINISHING:
122
- return status !== TaskStatus.PENDING && (status & alive) > 0;
101
+ case TaskStatusEnum.ATTEMPT_FINISHING:
102
+ return status !== TaskStatusEnum.PENDING && (status & alive) > 0;
123
103
  default:
124
104
  return false;
125
105
  }
@@ -127,13 +107,13 @@ class TaskState {
127
107
  cleanup() {
128
108
  if (!this.terminated)
129
109
  throw new Error(`[cleanup] task(${this.name}) is not terminated`);
130
- this._errorDetails.length = 0;
110
+ this._errorCollector.cleanup();
131
111
  this._monitors.onStatusChange.destroy();
132
112
  this._monitors.onAddError.destroy();
133
113
  }
134
- _addError(type, error) {
135
- this._errorDetails.push({ type, error });
136
- this._monitors.onAddError.notify(type, error);
114
+ _addError(type, error, level = ErrorLevelEnum.ERROR) {
115
+ this._errorCollector.add(type, error, level);
116
+ this._monitors.onAddError.notify(type, error, level);
137
117
  }
138
118
  }
139
119
 
@@ -144,15 +124,15 @@ class AtomicTask extends TaskState {
144
124
  this._promise = undefined;
145
125
  }
146
126
  async start() {
147
- if (this.status === TaskStatus.PENDING) {
148
- this.status = TaskStatus.RUNNING;
127
+ if (this.status === TaskStatusEnum.PENDING) {
128
+ this.status = TaskStatusEnum.RUNNING;
149
129
  this._promise = this.run()
150
130
  .then(() => {
151
- this.status = TaskStatus.FINISHED;
131
+ this.status = TaskStatusEnum.FINISHED;
152
132
  })
153
133
  .catch(error => {
154
- this.status = TaskStatus.FAILED;
155
134
  this._addError('AtomicTaskError', error);
135
+ this.status = TaskStatusEnum.FAILED;
156
136
  });
157
137
  }
158
138
  return this._promise;
@@ -164,20 +144,20 @@ class AtomicTask extends TaskState {
164
144
  await this._promise;
165
145
  }
166
146
  async cancel() {
167
- if (this.status === TaskStatus.PENDING) {
168
- this.status = TaskStatus.ATTEMPT_CANCELING;
169
- this.status = TaskStatus.CANCELLED;
147
+ if (this.status === TaskStatusEnum.PENDING) {
148
+ this.status = TaskStatusEnum.ATTEMPT_CANCELING;
149
+ this.status = TaskStatusEnum.CANCELLED;
170
150
  return;
171
151
  }
172
152
  if (this.alive)
173
- this.status = TaskStatus.ATTEMPT_CANCELING;
153
+ this.status = TaskStatusEnum.ATTEMPT_CANCELING;
174
154
  await this._promise;
175
155
  }
176
156
  async finish() {
177
- if (this.status === TaskStatus.PENDING)
157
+ if (this.status === TaskStatusEnum.PENDING)
178
158
  await this.start();
179
159
  if (this.alive)
180
- this.status = TaskStatus.ATTEMPT_FINISHING;
160
+ this.status = TaskStatusEnum.ATTEMPT_FINISHING;
181
161
  await this._promise;
182
162
  }
183
163
  }
@@ -195,63 +175,63 @@ class ResumableTask extends TaskState {
195
175
  this._step = undefined;
196
176
  }
197
177
  async start() {
198
- if (this.status === TaskStatus.PENDING) {
199
- this.status = TaskStatus.RUNNING;
178
+ if (this.status === TaskStatusEnum.PENDING) {
179
+ this.status = TaskStatusEnum.RUNNING;
200
180
  this._execution = this.run();
201
181
  this.launchStep();
202
182
  await this._step;
203
183
  }
204
184
  }
205
185
  async pause() {
206
- if (this.status === TaskStatus.RUNNING) {
207
- this.status = TaskStatus.ATTEMPT_SUSPENDING;
186
+ if (this.status === TaskStatusEnum.RUNNING) {
187
+ this.status = TaskStatusEnum.ATTEMPT_SUSPENDING;
208
188
  await this._step;
209
- if (this.status === TaskStatus.ATTEMPT_SUSPENDING) {
210
- this.status = TaskStatus.SUSPENDED;
189
+ if (this.status === TaskStatusEnum.ATTEMPT_SUSPENDING) {
190
+ this.status = TaskStatusEnum.SUSPENDED;
211
191
  }
212
192
  }
213
193
  }
214
194
  async resume() {
215
- if (this.status === TaskStatus.SUSPENDED) {
216
- this.status = TaskStatus.ATTEMPT_RESUMING;
195
+ if (this.status === TaskStatusEnum.SUSPENDED) {
196
+ this.status = TaskStatusEnum.ATTEMPT_RESUMING;
217
197
  await this._step;
218
- if (this.status === TaskStatus.ATTEMPT_RESUMING) {
219
- this.status = TaskStatus.RUNNING;
198
+ if (this.status === TaskStatusEnum.ATTEMPT_RESUMING) {
199
+ this.status = TaskStatusEnum.RUNNING;
220
200
  this.queueStep();
221
201
  }
222
202
  }
223
203
  }
224
204
  async cancel() {
225
205
  if (this.alive) {
226
- this.status = TaskStatus.ATTEMPT_CANCELING;
206
+ this.status = TaskStatusEnum.ATTEMPT_CANCELING;
227
207
  await this._step;
228
- if (this.status === TaskStatus.ATTEMPT_CANCELING) {
229
- this.status = TaskStatus.CANCELLED;
208
+ if (this.status === TaskStatusEnum.ATTEMPT_CANCELING) {
209
+ this.status = TaskStatusEnum.CANCELLED;
230
210
  }
231
211
  }
232
212
  }
233
213
  async finish() {
234
- if (this.status === TaskStatus.PENDING)
214
+ if (this.status === TaskStatusEnum.PENDING)
235
215
  await this.start();
236
216
  if (this.alive) {
237
- this.status = TaskStatus.ATTEMPT_FINISHING;
217
+ this.status = TaskStatusEnum.ATTEMPT_FINISHING;
238
218
  await this._step;
239
219
  const execution = this._execution;
240
220
  if (execution) {
241
- while (this.status === TaskStatus.ATTEMPT_FINISHING) {
221
+ while (this.status === TaskStatusEnum.ATTEMPT_FINISHING) {
242
222
  const step = execution.next();
243
223
  if (step.done) {
244
- this.status = this.hasError ? TaskStatus.FAILED : TaskStatus.FINISHED;
224
+ this.status = this.hasError ? TaskStatusEnum.FAILED : TaskStatusEnum.FINISHED;
245
225
  break;
246
226
  }
247
227
  await step.value.catch(error => {
248
228
  this._addError('ResumableTaskError', error);
249
229
  switch (this.strategy) {
250
- case TaskStrategy.ABORT_ON_ERROR:
230
+ case TaskStrategyEnum.ABORT_ON_ERROR:
251
231
  if (!this.terminated)
252
- this.status = TaskStatus.FAILED;
232
+ this.status = TaskStatusEnum.FAILED;
253
233
  break;
254
- case TaskStrategy.CONTINUE_ON_ERROR:
234
+ case TaskStrategyEnum.CONTINUE_ON_ERROR:
255
235
  break;
256
236
  }
257
237
  });
@@ -260,10 +240,10 @@ class ResumableTask extends TaskState {
260
240
  }
261
241
  }
262
242
  launchStep() {
263
- if (this.status === TaskStatus.RUNNING && this._step === undefined && this._execution) {
243
+ if (this.status === TaskStatusEnum.RUNNING && this._step === undefined && this._execution) {
264
244
  const step = this._execution.next();
265
245
  if (step.done) {
266
- this.status = this.hasError ? TaskStatus.FAILED : TaskStatus.FINISHED;
246
+ this.status = this.hasError ? TaskStatusEnum.FAILED : TaskStatusEnum.FINISHED;
267
247
  return;
268
248
  }
269
249
  this._step = step.value
@@ -275,11 +255,11 @@ class ResumableTask extends TaskState {
275
255
  this._step = undefined;
276
256
  this._addError('ResumableTaskError', error);
277
257
  switch (this.strategy) {
278
- case TaskStrategy.ABORT_ON_ERROR:
258
+ case TaskStrategyEnum.ABORT_ON_ERROR:
279
259
  if (!this.terminated)
280
- this.status = TaskStatus.FAILED;
260
+ this.status = TaskStatusEnum.FAILED;
281
261
  break;
282
- case TaskStrategy.CONTINUE_ON_ERROR:
262
+ case TaskStrategyEnum.CONTINUE_ON_ERROR:
283
263
  this.queueStep();
284
264
  break;
285
265
  }
@@ -291,4 +271,4 @@ class ResumableTask extends TaskState {
291
271
  }
292
272
  }
293
273
 
294
- export { AtomicTask, ResumableTask, TaskState, TaskStatus, TaskStrategy, active, alive, terminated };
274
+ export { AtomicTask, ResumableTask, TaskState };
@@ -1,104 +1,23 @@
1
- declare enum TaskStatus {
2
- PENDING = 1,
3
- RUNNING = 2,
4
- SUSPENDED = 4,
5
- CANCELLED = 8,
6
- FAILED = 16,
7
- FINISHED = 32,
8
- ATTEMPT_SUSPENDING = 64,
9
- ATTEMPT_RESUMING = 128,
10
- ATTEMPT_CANCELING = 256,
11
- ATTEMPT_FINISHING = 512
12
- }
13
- declare enum TaskStrategy {
14
- ABORT_ON_ERROR = 1,
15
- CONTINUE_ON_ERROR = 2
16
- }
17
- declare const active: number;
18
- declare const alive: number;
19
- declare const terminated: number;
20
-
21
- interface ITaskErrorDetail {
22
- type: string;
23
- error: unknown;
24
- }
25
- interface ITaskError {
26
- from: string;
27
- details: ITaskErrorDetail[];
28
- }
29
- interface ITaskMonitor {
30
- onAddError(type: string, error: unknown): void;
31
- onStatusChange(status: TaskStatus, prevStatus: TaskStatus): void;
32
- }
33
- type IUnMonitorTask = () => void;
34
- interface ITaskState {
35
- readonly status: TaskStatus;
36
- readonly active: boolean;
37
- readonly alive: boolean;
38
- readonly terminated: boolean;
39
- }
40
- interface ITask extends ITaskState {
41
- /**
42
- * Task name.
43
- */
44
- readonly name: string;
45
- /**
46
- * Task error.
47
- */
48
- readonly error: ITaskError | undefined;
49
- /**
50
- * Indicate if the task has error.
51
- */
52
- readonly hasError: boolean;
53
- /**
54
- * Start the task.
55
- */
56
- start(): Promise<void>;
57
- /**
58
- * Pause the task.
59
- */
60
- pause(): Promise<void>;
61
- /**
62
- * Resume the task.
63
- */
64
- resume(): Promise<void>;
65
- /**
66
- * Cancel the task.
67
- */
68
- cancel(): Promise<void>;
69
- /**
70
- * finish the task: run to completed no matter if the task started or not.
71
- */
72
- finish(): Promise<void>;
73
- /**
74
- * Perform a clean up.
75
- * Will thrown an error if the task is not terminated.
76
- */
77
- cleanup(): void;
78
- /**
79
- * Register a monitor to subscribe the task changes.
80
- * @param monitor
81
- */
82
- monitor(monitor: Partial<ITaskMonitor>): IUnMonitorTask;
83
- }
1
+ import { ITaskState, ISoraErrorCollector, ITaskError, ITaskMonitor, IUnMonitorTask, ITask } from '@guanghechen/types';
2
+ import { TaskStatusEnum, ErrorLevelEnum, TaskStrategyEnum } from '@guanghechen/constant';
84
3
 
85
4
  declare class TaskState implements ITaskState {
86
5
  readonly name: string;
6
+ protected readonly _errorCollector: ISoraErrorCollector;
87
7
  private readonly _monitors;
88
- private readonly _errorDetails;
89
8
  private _status;
90
9
  constructor(name: string);
91
- get status(): TaskStatus;
10
+ get status(): TaskStatusEnum;
92
11
  get active(): boolean;
93
12
  get alive(): boolean;
94
13
  get terminated(): boolean;
95
14
  get hasError(): boolean;
96
15
  get error(): ITaskError | undefined;
97
- set status(status: TaskStatus);
16
+ set status(status: TaskStatusEnum);
98
17
  monitor(monitor: Partial<ITaskMonitor>): IUnMonitorTask;
99
- check(nextStatus: TaskStatus): boolean;
18
+ check(nextStatus: TaskStatusEnum): boolean;
100
19
  cleanup(): void;
101
- protected _addError(type: string, error: unknown): void;
20
+ protected _addError(type: string, error: unknown, level?: ErrorLevelEnum): void;
102
21
  }
103
22
 
104
23
  declare abstract class AtomicTask extends TaskState implements ITask {
@@ -114,11 +33,11 @@ declare abstract class AtomicTask extends TaskState implements ITask {
114
33
 
115
34
  interface IResumableTaskProps {
116
35
  name: string;
117
- strategy: TaskStrategy;
36
+ strategy: TaskStrategyEnum;
118
37
  pollInterval: number;
119
38
  }
120
39
  declare abstract class ResumableTask extends TaskState implements ITask {
121
- readonly strategy: TaskStrategy;
40
+ readonly strategy: TaskStrategyEnum;
122
41
  private readonly _pollInterval;
123
42
  private _execution;
124
43
  private _step;
@@ -133,4 +52,4 @@ declare abstract class ResumableTask extends TaskState implements ITask {
133
52
  private queueStep;
134
53
  }
135
54
 
136
- export { AtomicTask, type ITask, type ITaskError, type ITaskErrorDetail, type ITaskMonitor, type ITaskState, type IUnMonitorTask, ResumableTask, TaskState, TaskStatus, TaskStrategy, active, alive, terminated };
55
+ export { AtomicTask, ResumableTask, TaskState };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guanghechen/task",
3
- "version": "1.0.0-alpha.1",
3
+ "version": "1.0.0-alpha.3",
4
4
  "description": "Atomic and resumable tasks",
5
5
  "author": {
6
6
  "name": "guanghechen",
@@ -8,10 +8,10 @@
8
8
  },
9
9
  "repository": {
10
10
  "type": "git",
11
- "url": "https://github.com/guanghechen/sora/tree/@guanghechen/task@5.1.0",
11
+ "url": "https://github.com/guanghechen/sora/tree/@guanghechen/task@1.0.0-alpha.2",
12
12
  "directory": "packages/task"
13
13
  },
14
- "homepage": "https://github.com/guanghechen/sora/tree/@guanghechen/task@5.1.0/packages/task#readme",
14
+ "homepage": "https://github.com/guanghechen/sora/tree/@guanghechen/task@1.0.0-alpha.2/packages/task#readme",
15
15
  "type": "module",
16
16
  "main": "./lib/cjs/index.cjs",
17
17
  "module": "./lib/esm/index.mjs",
@@ -39,13 +39,16 @@
39
39
  "test": "node --experimental-vm-modules ../../node_modules/.bin/jest --config ../../jest.config.mjs --rootDir ."
40
40
  },
41
41
  "dependencies": {
42
- "@guanghechen/monitor": "^1.0.0-alpha.1"
42
+ "@guanghechen/constant": "^1.0.0-alpha.1",
43
+ "@guanghechen/error": "^1.0.0-alpha.3",
44
+ "@guanghechen/monitor": "^1.0.0-alpha.3"
43
45
  },
44
46
  "devDependencies": {
47
+ "@guanghechen/shared": "^1.0.0-alpha.3",
45
48
  "cross-env": "^7.0.3",
46
49
  "jest": "^29.6.4",
47
50
  "rimraf": "^5.0.1",
48
51
  "rollup": "^3.28.1"
49
52
  },
50
- "gitHead": "39cf17711022736f580c1dff68a535cea6ffa3ef"
53
+ "gitHead": "6209b28c7340c77e5954b697dddfa2893d8f30df"
51
54
  }