@chevre/domain 22.11.0-alpha.19 → 22.11.0-alpha.20
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.
|
@@ -33,7 +33,7 @@ interface IRunningTask {
|
|
|
33
33
|
*/
|
|
34
34
|
interface IExecutedTask {
|
|
35
35
|
id: string;
|
|
36
|
-
status: factory.taskStatus.Executed | factory.taskStatus.Running;
|
|
36
|
+
status: factory.taskStatus.Executed | factory.taskStatus.Running | factory.taskStatus.Aborted;
|
|
37
37
|
executionResult: factory.task.IExecutionResult;
|
|
38
38
|
/**
|
|
39
39
|
* 実行されたタスクの残り試行回数
|
|
@@ -70,6 +70,10 @@ export declare class TaskRepo {
|
|
|
70
70
|
*/
|
|
71
71
|
createDeleteTransactionTaskIfNotExist(params: Pick<factory.task.IAttributes<factory.taskName.DeleteTransaction>, 'data' | 'executionResults' | 'name' | 'numberOfTried' | 'project' | 'remainingNumberOfTries' | 'runsAt' | 'status'>, options: IOptionOnCreate): Promise<void>;
|
|
72
72
|
createOnAssetTransactionStatusChangedTaskIfNotExist(params: Pick<factory.task.IAttributes<factory.taskName.OnAssetTransactionStatusChanged>, 'data' | 'executionResults' | 'name' | 'numberOfTried' | 'project' | 'remainingNumberOfTries' | 'runsAt' | 'status'>, options: IOptionOnCreate): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Ready -> remainingNumberOfTriesが1減る
|
|
75
|
+
* Running -> findOneするだけ
|
|
76
|
+
*/
|
|
73
77
|
executeOneById(params: {
|
|
74
78
|
id: string;
|
|
75
79
|
status: factory.taskStatus.Ready | factory.taskStatus.Running;
|
|
@@ -79,7 +83,7 @@ export declare class TaskRepo {
|
|
|
79
83
|
expires?: Date;
|
|
80
84
|
}): Promise<IExecutableTask<factory.taskName> | null>;
|
|
81
85
|
/**
|
|
82
|
-
*
|
|
86
|
+
* Readyのタスクをname指定でひとつRunningに変更する
|
|
83
87
|
*/
|
|
84
88
|
executeOneIfExists(params: {
|
|
85
89
|
name?: {
|
|
@@ -126,21 +130,28 @@ export declare class TaskRepo {
|
|
|
126
130
|
numberOfTried?: factory.sortType;
|
|
127
131
|
runsAt: factory.sortType;
|
|
128
132
|
};
|
|
129
|
-
}, next
|
|
133
|
+
}, next?: INextFunction): Promise<Pick<factory.task.ITask<factory.taskName>, 'id' | 'name'> | null>;
|
|
130
134
|
/**
|
|
131
135
|
* emit OnTaskStatusChanged on delayed tasks
|
|
132
136
|
*/
|
|
133
137
|
/**
|
|
134
|
-
*
|
|
138
|
+
* Readyのままで期限切れのタスクをExpiredに変更する
|
|
135
139
|
*/
|
|
136
140
|
makeExpiredMany(params: {
|
|
137
141
|
expiresLt: Date;
|
|
138
142
|
}): Promise<UpdateWriteOpResult>;
|
|
139
143
|
/**
|
|
140
|
-
*
|
|
144
|
+
* Runningのまま一定期間超過し、かつ、remainingNumberOfTries>0のタスクをReadyに変更する
|
|
141
145
|
*/
|
|
142
|
-
|
|
146
|
+
retryMany(params: {
|
|
143
147
|
intervalInMinutes: number;
|
|
148
|
+
/**
|
|
149
|
+
* リトライ条件に残り試行回数条件を追加する
|
|
150
|
+
* 十分に小さい数値を指定すれば、実質残り試行回数に関係なくRunningがReadyに変更されることになる
|
|
151
|
+
*/
|
|
152
|
+
remainingNumberOfTries: {
|
|
153
|
+
$gt: number;
|
|
154
|
+
};
|
|
144
155
|
}): Promise<UpdateWriteOpResult>;
|
|
145
156
|
/**
|
|
146
157
|
* 実行中止済タスクを強制的にリトライ
|
|
@@ -154,17 +165,20 @@ export declare class TaskRepo {
|
|
|
154
165
|
intervalInMinutes: number;
|
|
155
166
|
}): Promise<UpdateWriteOpResult>;
|
|
156
167
|
/**
|
|
157
|
-
*
|
|
168
|
+
* タスクIDから実行結果とステータスを保管する
|
|
169
|
+
* Abortedの場合、dateAbortedもセットする
|
|
158
170
|
*/
|
|
159
|
-
|
|
171
|
+
setExecutionResultAndStatus(params: {
|
|
160
172
|
/**
|
|
161
173
|
* タスクID
|
|
162
174
|
*/
|
|
163
175
|
id: string;
|
|
164
|
-
status: factory.taskStatus.Executed | factory.taskStatus.Running;
|
|
165
176
|
remainingNumberOfTries: number;
|
|
166
177
|
name: factory.taskName;
|
|
167
|
-
},
|
|
178
|
+
}, update: {
|
|
179
|
+
status: factory.taskStatus.Executed | factory.taskStatus.Running | factory.taskStatus.Aborted;
|
|
180
|
+
executionResult: factory.task.IExecutionResult;
|
|
181
|
+
}, next?: INextFunction): Promise<void>;
|
|
168
182
|
count(params: factory.task.ISearchConditions): Promise<{
|
|
169
183
|
count: number;
|
|
170
184
|
}>;
|
package/lib/chevre/repo/task.js
CHANGED
|
@@ -352,6 +352,10 @@ class TaskRepo {
|
|
|
352
352
|
}
|
|
353
353
|
});
|
|
354
354
|
}
|
|
355
|
+
/**
|
|
356
|
+
* Ready -> remainingNumberOfTriesが1減る
|
|
357
|
+
* Running -> findOneするだけ
|
|
358
|
+
*/
|
|
355
359
|
executeOneById(params) {
|
|
356
360
|
return __awaiter(this, void 0, void 0, function* () {
|
|
357
361
|
const now = new Date();
|
|
@@ -386,7 +390,7 @@ class TaskRepo {
|
|
|
386
390
|
});
|
|
387
391
|
}
|
|
388
392
|
/**
|
|
389
|
-
*
|
|
393
|
+
* Readyのタスクをname指定でひとつRunningに変更する
|
|
390
394
|
*/
|
|
391
395
|
executeOneIfExists(params) {
|
|
392
396
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -489,7 +493,7 @@ class TaskRepo {
|
|
|
489
493
|
task_1.taskEventEmitter.emitTaskStatusChanged({
|
|
490
494
|
id: doc.id,
|
|
491
495
|
status: factory.taskStatus.Running
|
|
492
|
-
}, next);
|
|
496
|
+
}, (typeof next === 'function') ? next : undefined);
|
|
493
497
|
return doc;
|
|
494
498
|
});
|
|
495
499
|
}
|
|
@@ -595,7 +599,7 @@ class TaskRepo {
|
|
|
595
599
|
// return delayedTasks;
|
|
596
600
|
// }
|
|
597
601
|
/**
|
|
598
|
-
*
|
|
602
|
+
* Readyのままで期限切れのタスクをExpiredに変更する
|
|
599
603
|
*/
|
|
600
604
|
makeExpiredMany(params) {
|
|
601
605
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -615,20 +619,24 @@ class TaskRepo {
|
|
|
615
619
|
});
|
|
616
620
|
}
|
|
617
621
|
/**
|
|
618
|
-
*
|
|
622
|
+
* Runningのまま一定期間超過し、かつ、remainingNumberOfTries>0のタスクをReadyに変更する
|
|
619
623
|
*/
|
|
620
|
-
|
|
624
|
+
retryMany(params) {
|
|
621
625
|
return __awaiter(this, void 0, void 0, function* () {
|
|
622
626
|
const lastTriedAtShoudBeLessThan = moment()
|
|
623
627
|
.add(-params.intervalInMinutes, 'minutes')
|
|
624
628
|
.toDate();
|
|
625
|
-
|
|
629
|
+
const remainingNumberOfTriesGt = params.remainingNumberOfTries.$gt;
|
|
630
|
+
return this.taskModel.updateMany(
|
|
631
|
+
// name: 'retry'のindexと連動しているので、条件の順序などには注意すること
|
|
632
|
+
// @see schemas/task
|
|
633
|
+
{
|
|
626
634
|
status: { $eq: factory.taskStatus.Running },
|
|
627
635
|
lastTriedAt: {
|
|
628
636
|
$type: 'date',
|
|
629
637
|
$lt: lastTriedAtShoudBeLessThan
|
|
630
638
|
},
|
|
631
|
-
remainingNumberOfTries: { $gt:
|
|
639
|
+
remainingNumberOfTries: { $gt: remainingNumberOfTriesGt }
|
|
632
640
|
}, {
|
|
633
641
|
$set: {
|
|
634
642
|
status: factory.taskStatus.Ready // 実行前に変更
|
|
@@ -715,15 +723,18 @@ class TaskRepo {
|
|
|
715
723
|
});
|
|
716
724
|
}
|
|
717
725
|
/**
|
|
718
|
-
*
|
|
726
|
+
* タスクIDから実行結果とステータスを保管する
|
|
727
|
+
* Abortedの場合、dateAbortedもセットする
|
|
719
728
|
*/
|
|
720
|
-
|
|
729
|
+
setExecutionResultAndStatus(params, update,
|
|
721
730
|
// support customr function(2025-05-25~)
|
|
722
731
|
next) {
|
|
723
732
|
return __awaiter(this, void 0, void 0, function* () {
|
|
724
|
-
const { id,
|
|
733
|
+
const { id, remainingNumberOfTries, name } = params;
|
|
734
|
+
const { status, executionResult } = update;
|
|
725
735
|
yield this.taskModel.updateOne({ _id: { $eq: id } }, {
|
|
726
|
-
$set: { status },
|
|
736
|
+
$set: Object.assign({ status }, (status === factory.taskStatus.Aborted) ? { dateAborted: executionResult.endDate } : undefined // 2025-08-04~
|
|
737
|
+
),
|
|
727
738
|
$push: { executionResults: executionResult }
|
|
728
739
|
})
|
|
729
740
|
.exec();
|
|
@@ -14,6 +14,51 @@ const createDebug = require("debug");
|
|
|
14
14
|
const moment = require("moment");
|
|
15
15
|
const factory = require("../factory");
|
|
16
16
|
const debug = createDebug('chevre-domain:service:task');
|
|
17
|
+
/**
|
|
18
|
+
* タスク実行失敗時処理
|
|
19
|
+
*/
|
|
20
|
+
function onOperationFailed(params) {
|
|
21
|
+
return (repos) => __awaiter(this, void 0, void 0, function* () {
|
|
22
|
+
let error = params.error;
|
|
23
|
+
const { task, now, next } = params;
|
|
24
|
+
if (typeof error !== 'object') {
|
|
25
|
+
error = { message: String(error) };
|
|
26
|
+
}
|
|
27
|
+
// remainingNumberOfTries<=0ならAborted(2025-08-04~)
|
|
28
|
+
const isRetryable = task.remainingNumberOfTries > 0;
|
|
29
|
+
if (isRetryable) {
|
|
30
|
+
const result = {
|
|
31
|
+
executedAt: now,
|
|
32
|
+
endDate: new Date(),
|
|
33
|
+
error: Object.assign(Object.assign({}, error), { code: error.code, message: error.message, name: error.name, stack: error.stack })
|
|
34
|
+
};
|
|
35
|
+
// 失敗してもここではステータスを戻さない(Runningのまま待機)
|
|
36
|
+
yield repos.task.setExecutionResultAndStatus({
|
|
37
|
+
id: task.id,
|
|
38
|
+
remainingNumberOfTries: task.remainingNumberOfTries,
|
|
39
|
+
name: task.name
|
|
40
|
+
}, {
|
|
41
|
+
status: task.status,
|
|
42
|
+
executionResult: result
|
|
43
|
+
}, (typeof next === 'function') ? next : undefined);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
const result = {
|
|
47
|
+
executedAt: now,
|
|
48
|
+
endDate: new Date(),
|
|
49
|
+
error: Object.assign(Object.assign({}, error), { code: error.code, message: error.message, name: error.name, stack: error.stack })
|
|
50
|
+
};
|
|
51
|
+
yield repos.task.setExecutionResultAndStatus({
|
|
52
|
+
id: task.id,
|
|
53
|
+
remainingNumberOfTries: task.remainingNumberOfTries,
|
|
54
|
+
name: task.name
|
|
55
|
+
}, {
|
|
56
|
+
status: factory.taskStatus.Aborted,
|
|
57
|
+
executionResult: result
|
|
58
|
+
}, (typeof next === 'function') ? next : undefined);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
17
62
|
/**
|
|
18
63
|
* タスクを実行する
|
|
19
64
|
*/
|
|
@@ -32,6 +77,13 @@ function executeTask(task, next) {
|
|
|
32
77
|
throw new factory.errors.Internal(`task expired [expires:${task.expires}]`);
|
|
33
78
|
}
|
|
34
79
|
}
|
|
80
|
+
// remainingNumberOfTries<0ならcallを実行しない(2025-08-04~)
|
|
81
|
+
// リトライを繰り返した後、不明の原因でRunningのまま残ってしまったタスクがリトライされたケース
|
|
82
|
+
const { remainingNumberOfTries } = task;
|
|
83
|
+
const isCallable = remainingNumberOfTries >= 0;
|
|
84
|
+
if (!isCallable) {
|
|
85
|
+
throw new factory.errors.Internal(`task remainingNumberOfTries < 0 [remainingNumberOfTries:${remainingNumberOfTries}]`);
|
|
86
|
+
}
|
|
35
87
|
// タスク名の関数が定義されていなければ、TypeErrorとなる
|
|
36
88
|
let callResult;
|
|
37
89
|
const { call } = yield Promise.resolve(`${`./task/${task.name}`}`).then(s => require(s));
|
|
@@ -70,31 +122,18 @@ function executeTask(task, next) {
|
|
|
70
122
|
error: ((callResult === null || callResult === void 0 ? void 0 : callResult.error) instanceof Error)
|
|
71
123
|
? Object.assign(Object.assign({}, callResult.error), { message: callResult.error.message }) : ''
|
|
72
124
|
};
|
|
73
|
-
yield taskRepo.
|
|
125
|
+
yield taskRepo.setExecutionResultAndStatus({
|
|
74
126
|
id: task.id,
|
|
75
|
-
|
|
76
|
-
remainingNumberOfTries: task.remainingNumberOfTries,
|
|
127
|
+
remainingNumberOfTries,
|
|
77
128
|
name: task.name
|
|
78
|
-
},
|
|
129
|
+
}, {
|
|
130
|
+
status: factory.taskStatus.Executed,
|
|
131
|
+
executionResult: result
|
|
132
|
+
}, (typeof next === 'function') ? next : undefined);
|
|
79
133
|
}
|
|
80
134
|
catch (error) {
|
|
81
135
|
debug('service.task.execute throwed an error. task:', task.name, task.id, 'error:', error === null || error === void 0 ? void 0 : error.name, error === null || error === void 0 ? void 0 : error.message);
|
|
82
|
-
|
|
83
|
-
error = { message: String(error) };
|
|
84
|
-
}
|
|
85
|
-
// 実行結果追加
|
|
86
|
-
const result = {
|
|
87
|
-
executedAt: now,
|
|
88
|
-
endDate: new Date(),
|
|
89
|
-
error: Object.assign(Object.assign({}, error), { code: error.code, message: error.message, name: error.name, stack: error.stack })
|
|
90
|
-
};
|
|
91
|
-
// 失敗してもここではステータスを戻さない(Runningのまま待機)
|
|
92
|
-
yield taskRepo.pushExecutionResultById({
|
|
93
|
-
id: task.id,
|
|
94
|
-
status: task.status,
|
|
95
|
-
remainingNumberOfTries: task.remainingNumberOfTries,
|
|
96
|
-
name: task.name
|
|
97
|
-
}, result, (typeof next === 'function') ? next : undefined);
|
|
136
|
+
yield onOperationFailed(Object.assign({ task, now, error }, (typeof next === 'function') ? { next } : undefined))({ task: taskRepo });
|
|
98
137
|
}
|
|
99
138
|
});
|
|
100
139
|
}
|
package/package.json
CHANGED