@chevre/domain 26.0.0-alpha.16 → 26.0.0-alpha.17
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/lib/chevre/repo/adminTask.d.ts +8 -0
- package/lib/chevre/repo/adminTask.js +16 -0
- package/lib/chevre/repo/task.d.ts +2 -57
- package/lib/chevre/repo/task.js +0 -167
- package/lib/chevre/repo/taskDelayed.d.ts +22 -1
- package/lib/chevre/repo/taskDelayed.js +77 -0
- package/lib/chevre/repo/taskRunning.d.ts +35 -0
- package/lib/chevre/repo/taskRunning.js +89 -0
- package/lib/chevre/service/task.js +2 -2
- package/lib/chevre/service/taskHandler/onOperationFailed.d.ts +2 -0
- package/lib/chevre/service/taskHandler/onOperationFailed.js +2 -13
- package/lib/chevre/service/taskHandler.js +3 -7
- package/package.json +2 -2
|
@@ -28,6 +28,14 @@ export declare class AdminTaskRepo {
|
|
|
28
28
|
}): Promise<{
|
|
29
29
|
count: number;
|
|
30
30
|
}>;
|
|
31
|
+
/**
|
|
32
|
+
* 不要なタスクを削除する
|
|
33
|
+
*/
|
|
34
|
+
deleteRunsAtPassedCertainPeriod(params: {
|
|
35
|
+
runsAt: {
|
|
36
|
+
$lt: Date;
|
|
37
|
+
};
|
|
38
|
+
}): Promise<import("mongodb").DeleteResult>;
|
|
31
39
|
getCursor(conditions: FilterQuery<factory.task.ITask<factory.taskName>>, projection: ProjectionType<factory.task.ITask<factory.taskName>>): import("mongoose").Cursor<import("mongoose").Document<unknown, Record<string, never>, IDocType, import("./mongoose/virtuals").IVirtuals, {}> & Omit<import("@chevre/factory/lib/chevre/task").ITask | import("@chevre/factory/lib/chevre/task/confirmPayTransaction").ITask | import("@chevre/factory/lib/chevre/task/confirmReserveTransaction").ITask | import("@chevre/factory/lib/chevre/task/createAccountingReport").ITask | import("@chevre/factory/lib/chevre/task/onAssetTransactionStatusChanged").ITask | import("@chevre/factory/lib/chevre/task/onAuthorizationCreated").ITask | import("@chevre/factory/lib/chevre/task/onEventChanged").ITask | import("@chevre/factory/lib/chevre/task/onResourceDeleted").ITask | import("@chevre/factory/lib/chevre/task/onResourceUpdated").ITask | import("@chevre/factory/lib/chevre/task/onOrderPaymentCompleted").ITask | import("@chevre/factory/lib/chevre/task/placeOrder").ITask | import("@chevre/factory/lib/chevre/task/returnOrder").ITask | import("@chevre/factory/lib/chevre/task/returnPayTransaction").ITask | import("@chevre/factory/lib/chevre/task/returnReserveTransaction").ITask | import("@chevre/factory/lib/chevre/task/sendEmailMessage").ITask | import("@chevre/factory/lib/chevre/task/sendOrder").ITask | import("@chevre/factory/lib/chevre/task/triggerWebhook").ITask | import("@chevre/factory/lib/chevre/task/useReservation").ITask | import("@chevre/factory/lib/chevre/task/voidPayTransaction").ITask, "id"> & {
|
|
32
40
|
expires?: never;
|
|
33
41
|
} & {
|
|
@@ -175,6 +175,22 @@ class AdminTaskRepo {
|
|
|
175
175
|
.exec();
|
|
176
176
|
return { count };
|
|
177
177
|
}
|
|
178
|
+
/**
|
|
179
|
+
* 不要なタスクを削除する
|
|
180
|
+
*/
|
|
181
|
+
async deleteRunsAtPassedCertainPeriod(params) {
|
|
182
|
+
return this.taskModel.deleteMany({
|
|
183
|
+
runsAt: { $lt: params.runsAt.$lt },
|
|
184
|
+
status: {
|
|
185
|
+
$in: [
|
|
186
|
+
factory_1.factory.taskStatus.Aborted,
|
|
187
|
+
factory_1.factory.taskStatus.Executed,
|
|
188
|
+
// factory.taskStatus.Expired // discontinue(2026-08-06~)
|
|
189
|
+
]
|
|
190
|
+
}
|
|
191
|
+
})
|
|
192
|
+
.exec();
|
|
193
|
+
}
|
|
178
194
|
getCursor(conditions, projection) {
|
|
179
195
|
return this.taskModel.find(conditions, projection)
|
|
180
196
|
.sort({ runsAt: factory_1.factory.sortType.Ascending })
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import type { Connection
|
|
1
|
+
import type { Connection } from 'mongoose';
|
|
2
2
|
import { factory } from '../factory';
|
|
3
3
|
import { IDocType } from './mongoose/schemas/task';
|
|
4
|
-
import type { IExecutableTask } from '../taskSettings';
|
|
5
4
|
/**
|
|
6
5
|
* リトライ可能なタスク作成属性
|
|
7
6
|
*/
|
|
@@ -57,39 +56,6 @@ export declare class TaskRepo {
|
|
|
57
56
|
identifier: string;
|
|
58
57
|
expires?: never;
|
|
59
58
|
}): Promise<void>;
|
|
60
|
-
/**
|
|
61
|
-
* Ready -> remainingNumberOfTriesが1減る
|
|
62
|
-
* Running -> findOneするだけ
|
|
63
|
-
*/
|
|
64
|
-
executeOneById(params: {
|
|
65
|
-
id: string;
|
|
66
|
-
status: factory.taskStatus.Ready | factory.taskStatus.Running;
|
|
67
|
-
executor: {
|
|
68
|
-
name: string;
|
|
69
|
-
};
|
|
70
|
-
expires?: never;
|
|
71
|
-
}): Promise<IExecutableTask<factory.taskName> | null>;
|
|
72
|
-
/**
|
|
73
|
-
* Runningのまま一定期間超過し、かつ、remainingNumberOfTries>0のタスクをReadyに変更する
|
|
74
|
-
*/
|
|
75
|
-
retryTasks(params: {
|
|
76
|
-
intervalInMinutes: number;
|
|
77
|
-
}): Promise<UpdateWriteOpResult>;
|
|
78
|
-
/**
|
|
79
|
-
* $lte:0をReadyにする(特定のタスクを除いて) -> Readyにすれば自動的にAbortedになる
|
|
80
|
-
*/
|
|
81
|
-
retryAbortingTasksByName(params: {
|
|
82
|
-
intervalInMinutes: number;
|
|
83
|
-
name: {
|
|
84
|
-
$in?: factory.taskName[];
|
|
85
|
-
};
|
|
86
|
-
}): Promise<UpdateWriteOpResult>;
|
|
87
|
-
/**
|
|
88
|
-
* $lte:0をReadyにする(特定のタスクを除いて) -> Readyにすれば自動的にAbortedになる
|
|
89
|
-
*/
|
|
90
|
-
retryAbortingTasks(params: {
|
|
91
|
-
intervalInMinutes: number;
|
|
92
|
-
}): Promise<UpdateWriteOpResult>;
|
|
93
59
|
/**
|
|
94
60
|
* 実行中止済タスクを強制的にリトライ
|
|
95
61
|
* 中止済タスクでなければ何もしない
|
|
@@ -97,27 +63,6 @@ export declare class TaskRepo {
|
|
|
97
63
|
retryForciblyIfAborted(params: {
|
|
98
64
|
id: string;
|
|
99
65
|
remainingNumberOfTries: number;
|
|
100
|
-
}): Promise<UpdateWriteOpResult>;
|
|
101
|
-
/**
|
|
102
|
-
* タスクIDから実行結果とステータスを保管する
|
|
103
|
-
* Abortedの場合、dateAbortedもセットする
|
|
104
|
-
*/
|
|
105
|
-
setExecutionResultAndStatus(params: {
|
|
106
|
-
/**
|
|
107
|
-
* タスクID
|
|
108
|
-
*/
|
|
109
|
-
id: string;
|
|
110
|
-
}, update: {
|
|
111
|
-
status: factory.taskStatus.Executed | factory.taskStatus.Running | factory.taskStatus.Aborted;
|
|
112
|
-
executionResult: factory.task.IExecutionResult;
|
|
113
|
-
}): Promise<void>;
|
|
114
|
-
/**
|
|
115
|
-
* 不要なタスクを削除する
|
|
116
|
-
*/
|
|
117
|
-
deleteRunsAtPassedCertainPeriod(params: {
|
|
118
|
-
runsAt: {
|
|
119
|
-
$lt: Date;
|
|
120
|
-
};
|
|
121
|
-
}): Promise<import("mongodb").DeleteResult>;
|
|
66
|
+
}): Promise<import("mongoose").UpdateWriteOpResult>;
|
|
122
67
|
}
|
|
123
68
|
export {};
|
package/lib/chevre/repo/task.js
CHANGED
|
@@ -1,28 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
3
|
exports.TaskRepo = void 0;
|
|
7
|
-
const moment_1 = __importDefault(require("moment"));
|
|
8
4
|
const errorHandler_1 = require("../errorHandler");
|
|
9
5
|
const task_1 = require("../eventEmitter/task");
|
|
10
6
|
const factory_1 = require("../factory");
|
|
11
|
-
const settings_1 = require("../settings");
|
|
12
7
|
const task_2 = require("./mongoose/schemas/task");
|
|
13
|
-
const executableTaskProjection = {
|
|
14
|
-
_id: 0,
|
|
15
|
-
id: { $toString: '$_id' },
|
|
16
|
-
// 必要最低限にprojection(2024-04-23~)
|
|
17
|
-
data: 1,
|
|
18
|
-
name: 1,
|
|
19
|
-
status: 1,
|
|
20
|
-
numberOfTried: 1,
|
|
21
|
-
project: 1,
|
|
22
|
-
remainingNumberOfTries: 1,
|
|
23
|
-
runsAt: 1,
|
|
24
|
-
// expires: 1 // 非同期アクションは移行につきexpires廃止(2026-08-05~)
|
|
25
|
-
};
|
|
26
8
|
/**
|
|
27
9
|
* タスクリポジトリ
|
|
28
10
|
*/
|
|
@@ -146,123 +128,6 @@ class TaskRepo {
|
|
|
146
128
|
throw new factory_1.factory.errors.Internal(`falied in creating a task unexpectedly. ${params.identifier}`);
|
|
147
129
|
}
|
|
148
130
|
}
|
|
149
|
-
/**
|
|
150
|
-
* Ready -> remainingNumberOfTriesが1減る
|
|
151
|
-
* Running -> findOneするだけ
|
|
152
|
-
*/
|
|
153
|
-
async executeOneById(params) {
|
|
154
|
-
const now = new Date();
|
|
155
|
-
let doc;
|
|
156
|
-
if (params.status === factory_1.factory.taskStatus.Running) {
|
|
157
|
-
doc = await this.taskModel.findOne({
|
|
158
|
-
_id: { $eq: params.id },
|
|
159
|
-
status: { $eq: params.status },
|
|
160
|
-
runsAt: { $lt: now },
|
|
161
|
-
// ...(params.expires instanceof Date) ? { expires: { $gt: now } } : undefined // 非同期アクションは移行につきexpires廃止(2026-08-05~)
|
|
162
|
-
}, executableTaskProjection)
|
|
163
|
-
.setOptions({ maxTimeMS: settings_1.MONGO_MAX_TIME_MS })
|
|
164
|
-
.lean()
|
|
165
|
-
.exec();
|
|
166
|
-
}
|
|
167
|
-
else {
|
|
168
|
-
doc = await this.taskModel.findOneAndUpdate({
|
|
169
|
-
_id: { $eq: params.id },
|
|
170
|
-
status: { $eq: params.status },
|
|
171
|
-
runsAt: { $lt: now },
|
|
172
|
-
// ...(params.expires instanceof Date) ? { expires: { $gt: now } } : undefined // 非同期アクションは移行につきexpires廃止(2026-08-05~)
|
|
173
|
-
}, {
|
|
174
|
-
$set: {
|
|
175
|
-
status: factory_1.factory.taskStatus.Running, // 実行中に変更
|
|
176
|
-
lastTriedAt: now,
|
|
177
|
-
executor: params.executor
|
|
178
|
-
},
|
|
179
|
-
$inc: {
|
|
180
|
-
remainingNumberOfTries: -1, // 残りトライ可能回数減らす
|
|
181
|
-
numberOfTried: 1 // トライ回数増やす
|
|
182
|
-
}
|
|
183
|
-
}, { new: true, projection: executableTaskProjection })
|
|
184
|
-
.setOptions({ maxTimeMS: settings_1.MONGO_MAX_TIME_MS })
|
|
185
|
-
.lean() // lean(2024-09-26~)
|
|
186
|
-
.exec();
|
|
187
|
-
}
|
|
188
|
-
if (doc === null) {
|
|
189
|
-
return null;
|
|
190
|
-
}
|
|
191
|
-
return doc;
|
|
192
|
-
}
|
|
193
|
-
/**
|
|
194
|
-
* Runningのまま一定期間超過し、かつ、remainingNumberOfTries>0のタスクをReadyに変更する
|
|
195
|
-
*/
|
|
196
|
-
async retryTasks(params) {
|
|
197
|
-
const lastTriedAtShoudBeLessThan = (0, moment_1.default)()
|
|
198
|
-
.add(-params.intervalInMinutes, 'minutes')
|
|
199
|
-
.toDate();
|
|
200
|
-
return this.taskModel.updateMany(
|
|
201
|
-
// name: 'retry'のindexと連動しているので、条件の順序などには注意すること
|
|
202
|
-
// @see schemas/task
|
|
203
|
-
{
|
|
204
|
-
status: { $eq: factory_1.factory.taskStatus.Running },
|
|
205
|
-
lastTriedAt: {
|
|
206
|
-
$type: 'date',
|
|
207
|
-
$lt: lastTriedAtShoudBeLessThan
|
|
208
|
-
},
|
|
209
|
-
remainingNumberOfTries: { $gte: 1 }
|
|
210
|
-
}, {
|
|
211
|
-
$set: {
|
|
212
|
-
status: factory_1.factory.taskStatus.Ready // 実行前に変更
|
|
213
|
-
}
|
|
214
|
-
})
|
|
215
|
-
.exec();
|
|
216
|
-
}
|
|
217
|
-
/**
|
|
218
|
-
* $lte:0をReadyにする(特定のタスクを除いて) -> Readyにすれば自動的にAbortedになる
|
|
219
|
-
*/
|
|
220
|
-
async retryAbortingTasksByName(params) {
|
|
221
|
-
const lastTriedAtShoudBeLessThan = (0, moment_1.default)()
|
|
222
|
-
.add(-params.intervalInMinutes, 'minutes')
|
|
223
|
-
.toDate();
|
|
224
|
-
return this.taskModel.updateMany(
|
|
225
|
-
// name: 'retry'のindexと連動しているので、条件の順序などには注意すること
|
|
226
|
-
// @see schemas/task
|
|
227
|
-
{
|
|
228
|
-
status: { $eq: factory_1.factory.taskStatus.Running },
|
|
229
|
-
lastTriedAt: {
|
|
230
|
-
$type: 'date',
|
|
231
|
-
$lt: lastTriedAtShoudBeLessThan
|
|
232
|
-
},
|
|
233
|
-
remainingNumberOfTries: { $lte: 0 },
|
|
234
|
-
...(Array.isArray(params.name.$in)) ? { name: { $in: params.name.$in } } : undefined
|
|
235
|
-
}, {
|
|
236
|
-
$set: {
|
|
237
|
-
status: factory_1.factory.taskStatus.Ready // 実行前に変更
|
|
238
|
-
}
|
|
239
|
-
})
|
|
240
|
-
.exec();
|
|
241
|
-
}
|
|
242
|
-
/**
|
|
243
|
-
* $lte:0をReadyにする(特定のタスクを除いて) -> Readyにすれば自動的にAbortedになる
|
|
244
|
-
*/
|
|
245
|
-
async retryAbortingTasks(params) {
|
|
246
|
-
const lastTriedAtShoudBeLessThan = (0, moment_1.default)()
|
|
247
|
-
.add(-params.intervalInMinutes, 'minutes')
|
|
248
|
-
.toDate();
|
|
249
|
-
return this.taskModel.updateMany(
|
|
250
|
-
// name: 'retry'のindexと連動しているので、条件の順序などには注意すること
|
|
251
|
-
// @see schemas/task
|
|
252
|
-
{
|
|
253
|
-
status: { $eq: factory_1.factory.taskStatus.Running },
|
|
254
|
-
lastTriedAt: {
|
|
255
|
-
$type: 'date',
|
|
256
|
-
$lt: lastTriedAtShoudBeLessThan
|
|
257
|
-
},
|
|
258
|
-
remainingNumberOfTries: { $lte: 0 }
|
|
259
|
-
}, {
|
|
260
|
-
$set: {
|
|
261
|
-
status: factory_1.factory.taskStatus.Ready // 実行前に変更
|
|
262
|
-
}
|
|
263
|
-
})
|
|
264
|
-
.exec();
|
|
265
|
-
}
|
|
266
131
|
/**
|
|
267
132
|
* 実行中止済タスクを強制的にリトライ
|
|
268
133
|
* 中止済タスクでなければ何もしない
|
|
@@ -281,37 +146,5 @@ class TaskRepo {
|
|
|
281
146
|
})
|
|
282
147
|
.exec();
|
|
283
148
|
}
|
|
284
|
-
/**
|
|
285
|
-
* タスクIDから実行結果とステータスを保管する
|
|
286
|
-
* Abortedの場合、dateAbortedもセットする
|
|
287
|
-
*/
|
|
288
|
-
async setExecutionResultAndStatus(params, update) {
|
|
289
|
-
const { id } = params;
|
|
290
|
-
const { status, executionResult } = update;
|
|
291
|
-
await this.taskModel.updateOne({ _id: { $eq: id } }, {
|
|
292
|
-
$set: {
|
|
293
|
-
status,
|
|
294
|
-
...(status === factory_1.factory.taskStatus.Aborted) ? { dateAborted: executionResult.endDate } : undefined // 2025-08-04~
|
|
295
|
-
},
|
|
296
|
-
$push: { executionResults: executionResult }
|
|
297
|
-
})
|
|
298
|
-
.exec();
|
|
299
|
-
}
|
|
300
|
-
/**
|
|
301
|
-
* 不要なタスクを削除する
|
|
302
|
-
*/
|
|
303
|
-
async deleteRunsAtPassedCertainPeriod(params) {
|
|
304
|
-
return this.taskModel.deleteMany({
|
|
305
|
-
runsAt: { $lt: params.runsAt.$lt },
|
|
306
|
-
status: {
|
|
307
|
-
$in: [
|
|
308
|
-
factory_1.factory.taskStatus.Aborted,
|
|
309
|
-
factory_1.factory.taskStatus.Executed,
|
|
310
|
-
factory_1.factory.taskStatus.Expired
|
|
311
|
-
]
|
|
312
|
-
}
|
|
313
|
-
})
|
|
314
|
-
.exec();
|
|
315
|
-
}
|
|
316
149
|
}
|
|
317
150
|
exports.TaskRepo = TaskRepo;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Connection } from 'mongoose';
|
|
1
|
+
import type { Connection, UpdateWriteOpResult } from 'mongoose';
|
|
2
2
|
import { factory } from '../factory';
|
|
3
3
|
/**
|
|
4
4
|
* 遅延タスクリポジトリ
|
|
@@ -64,4 +64,25 @@ export declare class TaskDelayedRepo {
|
|
|
64
64
|
name: string;
|
|
65
65
|
};
|
|
66
66
|
}): Promise<Pick<factory.task.ITask<factory.taskName>, 'id' | 'name'> | null>;
|
|
67
|
+
/**
|
|
68
|
+
* Runningのまま一定期間超過し、かつ、remainingNumberOfTries>0のタスクをReadyに変更する
|
|
69
|
+
*/
|
|
70
|
+
retryTasks(params: {
|
|
71
|
+
intervalInMinutes: number;
|
|
72
|
+
}): Promise<UpdateWriteOpResult>;
|
|
73
|
+
/**
|
|
74
|
+
* $lte:0をReadyにする(特定のタスクを除いて) -> Readyにすれば自動的にAbortedになる
|
|
75
|
+
*/
|
|
76
|
+
retryAbortingTasksByName(params: {
|
|
77
|
+
intervalInMinutes: number;
|
|
78
|
+
name: {
|
|
79
|
+
$in?: factory.taskName[];
|
|
80
|
+
};
|
|
81
|
+
}): Promise<UpdateWriteOpResult>;
|
|
82
|
+
/**
|
|
83
|
+
* $lte:0をReadyにする(特定のタスクを除いて) -> Readyにすれば自動的にAbortedになる
|
|
84
|
+
*/
|
|
85
|
+
retryAbortingTasks(params: {
|
|
86
|
+
intervalInMinutes: number;
|
|
87
|
+
}): Promise<UpdateWriteOpResult>;
|
|
67
88
|
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.TaskDelayedRepo = void 0;
|
|
7
|
+
const moment_1 = __importDefault(require("moment"));
|
|
4
8
|
const task_1 = require("../eventEmitter/task");
|
|
5
9
|
const factory_1 = require("../factory");
|
|
6
10
|
const settings_1 = require("../settings");
|
|
@@ -144,5 +148,78 @@ class TaskDelayedRepo {
|
|
|
144
148
|
task_1.taskEventEmitter.emitTaskStatusChanged(changedTask);
|
|
145
149
|
return doc;
|
|
146
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* Runningのまま一定期間超過し、かつ、remainingNumberOfTries>0のタスクをReadyに変更する
|
|
153
|
+
*/
|
|
154
|
+
async retryTasks(params) {
|
|
155
|
+
const lastTriedAtShoudBeLessThan = (0, moment_1.default)()
|
|
156
|
+
.add(-params.intervalInMinutes, 'minutes')
|
|
157
|
+
.toDate();
|
|
158
|
+
return this.taskModel.updateMany(
|
|
159
|
+
// name: 'retry'のindexと連動しているので、条件の順序などには注意すること
|
|
160
|
+
// @see schemas/task
|
|
161
|
+
{
|
|
162
|
+
status: { $eq: factory_1.factory.taskStatus.Running },
|
|
163
|
+
lastTriedAt: {
|
|
164
|
+
$type: 'date',
|
|
165
|
+
$lt: lastTriedAtShoudBeLessThan
|
|
166
|
+
},
|
|
167
|
+
remainingNumberOfTries: { $gte: 1 }
|
|
168
|
+
}, {
|
|
169
|
+
$set: {
|
|
170
|
+
status: factory_1.factory.taskStatus.Ready // 実行前に変更
|
|
171
|
+
}
|
|
172
|
+
})
|
|
173
|
+
.exec();
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* $lte:0をReadyにする(特定のタスクを除いて) -> Readyにすれば自動的にAbortedになる
|
|
177
|
+
*/
|
|
178
|
+
async retryAbortingTasksByName(params) {
|
|
179
|
+
const lastTriedAtShoudBeLessThan = (0, moment_1.default)()
|
|
180
|
+
.add(-params.intervalInMinutes, 'minutes')
|
|
181
|
+
.toDate();
|
|
182
|
+
return this.taskModel.updateMany(
|
|
183
|
+
// name: 'retry'のindexと連動しているので、条件の順序などには注意すること
|
|
184
|
+
// @see schemas/task
|
|
185
|
+
{
|
|
186
|
+
status: { $eq: factory_1.factory.taskStatus.Running },
|
|
187
|
+
lastTriedAt: {
|
|
188
|
+
$type: 'date',
|
|
189
|
+
$lt: lastTriedAtShoudBeLessThan
|
|
190
|
+
},
|
|
191
|
+
remainingNumberOfTries: { $lte: 0 },
|
|
192
|
+
...(Array.isArray(params.name.$in)) ? { name: { $in: params.name.$in } } : undefined
|
|
193
|
+
}, {
|
|
194
|
+
$set: {
|
|
195
|
+
status: factory_1.factory.taskStatus.Ready // 実行前に変更
|
|
196
|
+
}
|
|
197
|
+
})
|
|
198
|
+
.exec();
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* $lte:0をReadyにする(特定のタスクを除いて) -> Readyにすれば自動的にAbortedになる
|
|
202
|
+
*/
|
|
203
|
+
async retryAbortingTasks(params) {
|
|
204
|
+
const lastTriedAtShoudBeLessThan = (0, moment_1.default)()
|
|
205
|
+
.add(-params.intervalInMinutes, 'minutes')
|
|
206
|
+
.toDate();
|
|
207
|
+
return this.taskModel.updateMany(
|
|
208
|
+
// name: 'retry'のindexと連動しているので、条件の順序などには注意すること
|
|
209
|
+
// @see schemas/task
|
|
210
|
+
{
|
|
211
|
+
status: { $eq: factory_1.factory.taskStatus.Running },
|
|
212
|
+
lastTriedAt: {
|
|
213
|
+
$type: 'date',
|
|
214
|
+
$lt: lastTriedAtShoudBeLessThan
|
|
215
|
+
},
|
|
216
|
+
remainingNumberOfTries: { $lte: 0 }
|
|
217
|
+
}, {
|
|
218
|
+
$set: {
|
|
219
|
+
status: factory_1.factory.taskStatus.Ready // 実行前に変更
|
|
220
|
+
}
|
|
221
|
+
})
|
|
222
|
+
.exec();
|
|
223
|
+
}
|
|
147
224
|
}
|
|
148
225
|
exports.TaskDelayedRepo = TaskDelayedRepo;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Connection } from 'mongoose';
|
|
2
|
+
import { factory } from '../factory';
|
|
3
|
+
import type { IExecutableTask } from '../taskSettings';
|
|
4
|
+
/**
|
|
5
|
+
* 実行中タスクリポジトリ
|
|
6
|
+
*/
|
|
7
|
+
export declare class TaskRunningRepo {
|
|
8
|
+
private readonly taskModel;
|
|
9
|
+
constructor(connection: Connection);
|
|
10
|
+
/**
|
|
11
|
+
* Ready -> remainingNumberOfTriesが1減る
|
|
12
|
+
* Running -> findOneするだけ
|
|
13
|
+
*/
|
|
14
|
+
executeOneById(params: {
|
|
15
|
+
id: string;
|
|
16
|
+
status: factory.taskStatus.Ready | factory.taskStatus.Running;
|
|
17
|
+
executor: {
|
|
18
|
+
name: string;
|
|
19
|
+
};
|
|
20
|
+
expires?: never;
|
|
21
|
+
}): Promise<IExecutableTask<factory.taskName> | null>;
|
|
22
|
+
/**
|
|
23
|
+
* タスクIDから実行結果とステータスを保管する
|
|
24
|
+
* Abortedの場合、dateAbortedもセットする
|
|
25
|
+
*/
|
|
26
|
+
setExecutionResultAndStatus(params: {
|
|
27
|
+
/**
|
|
28
|
+
* タスクID
|
|
29
|
+
*/
|
|
30
|
+
id: string;
|
|
31
|
+
}, update: {
|
|
32
|
+
status: factory.taskStatus.Executed | factory.taskStatus.Running | factory.taskStatus.Aborted;
|
|
33
|
+
executionResult: factory.task.IExecutionResult;
|
|
34
|
+
}): Promise<void>;
|
|
35
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TaskRunningRepo = void 0;
|
|
4
|
+
const factory_1 = require("../factory");
|
|
5
|
+
const settings_1 = require("../settings");
|
|
6
|
+
const task_1 = require("./mongoose/schemas/task");
|
|
7
|
+
const executableTaskProjection = {
|
|
8
|
+
_id: 0,
|
|
9
|
+
id: { $toString: '$_id' },
|
|
10
|
+
// 必要最低限にprojection(2024-04-23~)
|
|
11
|
+
data: 1,
|
|
12
|
+
name: 1,
|
|
13
|
+
status: 1,
|
|
14
|
+
numberOfTried: 1,
|
|
15
|
+
project: 1,
|
|
16
|
+
remainingNumberOfTries: 1,
|
|
17
|
+
runsAt: 1,
|
|
18
|
+
// expires: 1 // 非同期アクションは移行につきexpires廃止(2026-08-05~)
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* 実行中タスクリポジトリ
|
|
22
|
+
*/
|
|
23
|
+
class TaskRunningRepo {
|
|
24
|
+
taskModel;
|
|
25
|
+
constructor(connection) {
|
|
26
|
+
this.taskModel = connection.model(task_1.modelName, (0, task_1.createSchema)());
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Ready -> remainingNumberOfTriesが1減る
|
|
30
|
+
* Running -> findOneするだけ
|
|
31
|
+
*/
|
|
32
|
+
async executeOneById(params) {
|
|
33
|
+
const now = new Date();
|
|
34
|
+
let doc;
|
|
35
|
+
if (params.status === factory_1.factory.taskStatus.Running) {
|
|
36
|
+
doc = await this.taskModel.findOne({
|
|
37
|
+
_id: { $eq: params.id },
|
|
38
|
+
status: { $eq: params.status },
|
|
39
|
+
runsAt: { $lt: now },
|
|
40
|
+
// ...(params.expires instanceof Date) ? { expires: { $gt: now } } : undefined // 非同期アクションは移行につきexpires廃止(2026-08-05~)
|
|
41
|
+
}, executableTaskProjection)
|
|
42
|
+
.setOptions({ maxTimeMS: settings_1.MONGO_MAX_TIME_MS })
|
|
43
|
+
.lean()
|
|
44
|
+
.exec();
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
doc = await this.taskModel.findOneAndUpdate({
|
|
48
|
+
_id: { $eq: params.id },
|
|
49
|
+
status: { $eq: params.status },
|
|
50
|
+
runsAt: { $lt: now },
|
|
51
|
+
// ...(params.expires instanceof Date) ? { expires: { $gt: now } } : undefined // 非同期アクションは移行につきexpires廃止(2026-08-05~)
|
|
52
|
+
}, {
|
|
53
|
+
$set: {
|
|
54
|
+
status: factory_1.factory.taskStatus.Running, // 実行中に変更
|
|
55
|
+
lastTriedAt: now,
|
|
56
|
+
executor: params.executor
|
|
57
|
+
},
|
|
58
|
+
$inc: {
|
|
59
|
+
remainingNumberOfTries: -1, // 残りトライ可能回数減らす
|
|
60
|
+
numberOfTried: 1 // トライ回数増やす
|
|
61
|
+
}
|
|
62
|
+
}, { new: true, projection: executableTaskProjection })
|
|
63
|
+
.setOptions({ maxTimeMS: settings_1.MONGO_MAX_TIME_MS })
|
|
64
|
+
.lean() // lean(2024-09-26~)
|
|
65
|
+
.exec();
|
|
66
|
+
}
|
|
67
|
+
if (doc === null) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
return doc;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* タスクIDから実行結果とステータスを保管する
|
|
74
|
+
* Abortedの場合、dateAbortedもセットする
|
|
75
|
+
*/
|
|
76
|
+
async setExecutionResultAndStatus(params, update) {
|
|
77
|
+
const { id } = params;
|
|
78
|
+
const { status, executionResult } = update;
|
|
79
|
+
await this.taskModel.updateOne({ _id: { $eq: id } }, {
|
|
80
|
+
$set: {
|
|
81
|
+
status,
|
|
82
|
+
...(status === factory_1.factory.taskStatus.Aborted) ? { dateAborted: executionResult.endDate } : undefined // 2025-08-04~
|
|
83
|
+
},
|
|
84
|
+
$push: { executionResults: executionResult }
|
|
85
|
+
})
|
|
86
|
+
.exec();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
exports.TaskRunningRepo = TaskRunningRepo;
|
|
@@ -15,12 +15,12 @@ const debug = (0, debug_1.default)('chevre-domain:service:task');
|
|
|
15
15
|
*/
|
|
16
16
|
function executeTaskById(params) {
|
|
17
17
|
return async (settings) => {
|
|
18
|
-
const
|
|
18
|
+
const taskRunningRepo = new (await import('../repo/taskRunning.js')).TaskRunningRepo(settings.connection);
|
|
19
19
|
const { id, status, executor } = params;
|
|
20
20
|
let task = null;
|
|
21
21
|
try {
|
|
22
22
|
// support status: Running(2025-03-05~)
|
|
23
|
-
task = await
|
|
23
|
+
task = await taskRunningRepo.executeOneById({
|
|
24
24
|
id,
|
|
25
25
|
status,
|
|
26
26
|
executor: { name: executor.name },
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { factory } from '../../factory';
|
|
2
2
|
import type { SettingRepo } from '../../repo/setting';
|
|
3
3
|
import type { TaskRepo } from '../../repo/task';
|
|
4
|
+
import type { TaskRunningRepo } from '../../repo/taskRunning';
|
|
4
5
|
import type { IExecutableTask } from '../../taskSettings';
|
|
5
6
|
/**
|
|
6
7
|
* タスク実行失敗時処理
|
|
@@ -13,5 +14,6 @@ declare function onOperationFailed(params: {
|
|
|
13
14
|
}): (repos: {
|
|
14
15
|
setting: SettingRepo;
|
|
15
16
|
task: TaskRepo;
|
|
17
|
+
taskRunning: TaskRunningRepo;
|
|
16
18
|
}) => Promise<void>;
|
|
17
19
|
export { onOperationFailed };
|
|
@@ -19,9 +19,6 @@ function onOperationFailed(params) {
|
|
|
19
19
|
const isRetryable = task.remainingNumberOfTries > 0;
|
|
20
20
|
if (isRetryable) {
|
|
21
21
|
// 実験的に実行中タスク連携をしてみたが、ひとまず廃止(2026-07-01~)
|
|
22
|
-
// if (USE_INFORM_TASK_RUNNING) {
|
|
23
|
-
// await informTaskIfNeeded({ task, executionEndDate: endDate })(repos);
|
|
24
|
-
// }
|
|
25
22
|
const result = {
|
|
26
23
|
executedAt: now,
|
|
27
24
|
endDate,
|
|
@@ -34,11 +31,7 @@ function onOperationFailed(params) {
|
|
|
34
31
|
}
|
|
35
32
|
};
|
|
36
33
|
// 失敗してもここではステータスを戻さない(Runningのまま待機)
|
|
37
|
-
await repos.
|
|
38
|
-
id: task.id,
|
|
39
|
-
// remainingNumberOfTries: task.remainingNumberOfTries,
|
|
40
|
-
// name: task.name
|
|
41
|
-
}, {
|
|
34
|
+
await repos.taskRunning.setExecutionResultAndStatus({ id: task.id }, {
|
|
42
35
|
status: task.status,
|
|
43
36
|
executionResult: result
|
|
44
37
|
});
|
|
@@ -60,11 +53,7 @@ function onOperationFailed(params) {
|
|
|
60
53
|
stack: error.stack
|
|
61
54
|
}
|
|
62
55
|
};
|
|
63
|
-
await repos.
|
|
64
|
-
id: task.id,
|
|
65
|
-
// remainingNumberOfTries: task.remainingNumberOfTries,
|
|
66
|
-
// name: task.name
|
|
67
|
-
}, {
|
|
56
|
+
await repos.taskRunning.setExecutionResultAndStatus({ id: task.id }, {
|
|
68
57
|
status: factory_1.factory.taskStatus.Aborted,
|
|
69
58
|
executionResult: result
|
|
70
59
|
});
|
|
@@ -7,7 +7,6 @@ exports.taskLoader = void 0;
|
|
|
7
7
|
exports.executeTask = executeTask;
|
|
8
8
|
const debug_1 = __importDefault(require("debug"));
|
|
9
9
|
const moment_1 = __importDefault(require("moment"));
|
|
10
|
-
// import type { INextFunction } from '../eventEmitter/task';
|
|
11
10
|
const factory_1 = require("../factory");
|
|
12
11
|
const onOperationFailed_1 = require("./taskHandler/onOperationFailed");
|
|
13
12
|
const debug = (0, debug_1.default)('chevre-domain:service:taskHandler');
|
|
@@ -25,6 +24,7 @@ function executeTask(task) {
|
|
|
25
24
|
return async (settings, options) => {
|
|
26
25
|
const settingRepo = new (await import('../repo/setting.js')).SettingRepo(settings.connection);
|
|
27
26
|
const taskRepo = new (await import('../repo/task.js')).TaskRepo(settings.connection);
|
|
27
|
+
const taskRunningRepo = new (await import('../repo/taskRunning.js')).TaskRunningRepo(settings.connection);
|
|
28
28
|
try {
|
|
29
29
|
// 期限検証(2024-04-23~)
|
|
30
30
|
if (task.expires instanceof Date) {
|
|
@@ -56,11 +56,7 @@ function executeTask(task) {
|
|
|
56
56
|
}
|
|
57
57
|
: ''
|
|
58
58
|
};
|
|
59
|
-
await
|
|
60
|
-
id: task.id,
|
|
61
|
-
// remainingNumberOfTries,
|
|
62
|
-
// name: task.name
|
|
63
|
-
}, {
|
|
59
|
+
await taskRunningRepo.setExecutionResultAndStatus({ id: task.id }, {
|
|
64
60
|
status: factory_1.factory.taskStatus.Executed,
|
|
65
61
|
executionResult: result
|
|
66
62
|
});
|
|
@@ -69,7 +65,7 @@ function executeTask(task) {
|
|
|
69
65
|
await (0, onOperationFailed_1.onOperationFailed)({
|
|
70
66
|
task, now, error,
|
|
71
67
|
// ...(typeof next === 'function') ? { next } : undefined // discontinue next(2026-08-05~)
|
|
72
|
-
})({ setting: settingRepo, task: taskRepo });
|
|
68
|
+
})({ setting: settingRepo, task: taskRepo, taskRunning: taskRunningRepo });
|
|
73
69
|
}
|
|
74
70
|
};
|
|
75
71
|
}
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@aws-sdk/client-cognito-identity-provider": "3.1090.0",
|
|
13
13
|
"@aws-sdk/credential-providers": "3.1090.0",
|
|
14
|
-
"@chevre/factory": "10.1.0
|
|
14
|
+
"@chevre/factory": "10.1.0",
|
|
15
15
|
"@motionpicture/coa-service": "10.0.0",
|
|
16
16
|
"@motionpicture/gmo-service": "6.1.0-alpha.0",
|
|
17
17
|
"@sendgrid/client": "8.1.4",
|
|
@@ -88,5 +88,5 @@
|
|
|
88
88
|
"postversion": "git push origin --tags",
|
|
89
89
|
"prepublishOnly": "npm run clean && npm run build"
|
|
90
90
|
},
|
|
91
|
-
"version": "26.0.0-alpha.
|
|
91
|
+
"version": "26.0.0-alpha.17"
|
|
92
92
|
}
|