@chevre/domain 26.0.0-alpha.8 → 26.0.0-alpha.9
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/adminAsyncAction.d.ts +2 -2
- package/lib/chevre/repo/asyncAction.d.ts +2 -2
- package/lib/chevre/repo/scheduledTaskLegacy.d.ts +22 -2
- package/lib/chevre/repo/scheduledTaskLegacy.js +56 -2
- package/lib/chevre/repo/task.d.ts +27 -22
- package/lib/chevre/repo/task.js +172 -63
- package/lib/chevre/service/task.d.ts +1 -20
- package/lib/chevre/service/task.js +0 -28
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Connection, FilterQuery } from 'mongoose';
|
|
2
2
|
import { factory } from '../factory';
|
|
3
|
-
import {
|
|
3
|
+
import { IDocType } from './mongoose/schemas/asyncAction';
|
|
4
4
|
import type { IExecutableTask } from '../taskSettings';
|
|
5
5
|
export type IExecutableAsyncAction = Pick<IExecutableTask<factory.taskName>, 'data' | 'expires' | 'id' | 'name' | 'project' | 'runsAt' | 'status'>;
|
|
6
6
|
type IKeyOfProjection = keyof factory.task.ITask<factory.taskName> | 'expires';
|
|
@@ -9,7 +9,7 @@ type IFindParams = Pick<factory.task.ISearchConditions, 'id' | 'name' | 'project
|
|
|
9
9
|
* 非同期アクション管理リポジトリ
|
|
10
10
|
*/
|
|
11
11
|
export declare class AdminAsyncActionRepo {
|
|
12
|
-
readonly asyncActionModel
|
|
12
|
+
private readonly asyncActionModel;
|
|
13
13
|
constructor(connection: Connection);
|
|
14
14
|
static CREATE_MONGO_CONDITIONS(params: Pick<IFindParams, 'id' | 'name' | 'project' | 'runsFrom' | 'runsThrough' | 'status'>): FilterQuery<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>[];
|
|
15
15
|
findAsyncActions(params: IFindParams, inclusion: IKeyOfProjection[]): Promise<(IDocType & {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Connection } from 'mongoose';
|
|
2
2
|
import { factory } from '../factory';
|
|
3
|
-
import {
|
|
3
|
+
import { IDocType } from './mongoose/schemas/asyncAction';
|
|
4
4
|
import type { IExecutableTask } from '../taskSettings';
|
|
5
5
|
type ISavingTask = Pick<factory.task.IAttributes<factory.taskName>, 'data' | 'executionResults' | 'name' | 'project' | 'runsAt' | 'status'> & {
|
|
6
6
|
expires: Date;
|
|
@@ -11,7 +11,7 @@ type IKeyOfProjection = keyof factory.task.ITask<factory.taskName> | 'expires';
|
|
|
11
11
|
* 非同期アクションリポジトリ
|
|
12
12
|
*/
|
|
13
13
|
export declare class AsyncActionRepo {
|
|
14
|
-
readonly asyncActionModel
|
|
14
|
+
private readonly asyncActionModel;
|
|
15
15
|
constructor(connection: Connection);
|
|
16
16
|
/**
|
|
17
17
|
* Readyタスクをひとつ追加する
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import type { Connection, UpdateWriteOpResult } from 'mongoose';
|
|
2
2
|
import { factory } from '../factory';
|
|
3
|
-
import { IModel } from './mongoose/schemas/task';
|
|
4
3
|
/**
|
|
5
4
|
* 旧予定タスクリポジトリ
|
|
6
5
|
*/
|
|
7
6
|
export declare class ScheduledTaskLegacyRepo {
|
|
8
|
-
readonly taskModel
|
|
7
|
+
private readonly taskModel;
|
|
9
8
|
constructor(connection: Connection);
|
|
10
9
|
/**
|
|
11
10
|
* $eq:0をAbortedにする(特定のタスクのみ)(これらは中止されてもhubへ通知しない)
|
|
@@ -16,4 +15,25 @@ export declare class ScheduledTaskLegacyRepo {
|
|
|
16
15
|
$in: factory.taskName[];
|
|
17
16
|
};
|
|
18
17
|
}): Promise<UpdateWriteOpResult>;
|
|
18
|
+
/**
|
|
19
|
+
* 実行日時を一定期間過ぎたReadyタスクについて、Runningステータスに変更した上で、Runningイベントを発生させる
|
|
20
|
+
*/
|
|
21
|
+
emitRunningIfExistsLegacy(params: {
|
|
22
|
+
/**
|
|
23
|
+
* 必ずタスク名指定で実行する
|
|
24
|
+
*/
|
|
25
|
+
name: {
|
|
26
|
+
$eq: factory.taskName;
|
|
27
|
+
};
|
|
28
|
+
runsAt: {
|
|
29
|
+
$lt: Date;
|
|
30
|
+
};
|
|
31
|
+
sort: {
|
|
32
|
+
numberOfTried?: factory.sortType;
|
|
33
|
+
runsAt?: factory.sortType;
|
|
34
|
+
};
|
|
35
|
+
executor: {
|
|
36
|
+
name: string;
|
|
37
|
+
};
|
|
38
|
+
}): Promise<Pick<factory.task.ITask<factory.taskName>, 'id' | 'name'> | null>;
|
|
19
39
|
}
|
|
@@ -5,15 +5,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.ScheduledTaskLegacyRepo = void 0;
|
|
7
7
|
const moment_1 = __importDefault(require("moment"));
|
|
8
|
+
const task_1 = require("../eventEmitter/task");
|
|
8
9
|
const factory_1 = require("../factory");
|
|
9
|
-
const
|
|
10
|
+
const settings_1 = require("../settings");
|
|
11
|
+
const task_2 = require("./mongoose/schemas/task");
|
|
10
12
|
/**
|
|
11
13
|
* 旧予定タスクリポジトリ
|
|
12
14
|
*/
|
|
13
15
|
class ScheduledTaskLegacyRepo {
|
|
14
16
|
taskModel;
|
|
15
17
|
constructor(connection) {
|
|
16
|
-
this.taskModel = connection.model(
|
|
18
|
+
this.taskModel = connection.model(task_2.modelName, (0, task_2.createSchema)());
|
|
17
19
|
}
|
|
18
20
|
/**
|
|
19
21
|
* $eq:0をAbortedにする(特定のタスクのみ)(これらは中止されてもhubへ通知しない)
|
|
@@ -38,5 +40,57 @@ class ScheduledTaskLegacyRepo {
|
|
|
38
40
|
})
|
|
39
41
|
.exec();
|
|
40
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
* 実行日時を一定期間過ぎたReadyタスクについて、Runningステータスに変更した上で、Runningイベントを発生させる
|
|
45
|
+
*/
|
|
46
|
+
async emitRunningIfExistsLegacy(params
|
|
47
|
+
// next?: INextFunction // 現時点でタスク遅延実行ではnext指定なし(2026-07-30)
|
|
48
|
+
) {
|
|
49
|
+
if (!(params.runsAt.$lt instanceof Date)) {
|
|
50
|
+
throw new factory_1.factory.errors.Argument('runsAt.$lt', 'must be Date');
|
|
51
|
+
}
|
|
52
|
+
const projection = {
|
|
53
|
+
_id: 0,
|
|
54
|
+
id: { $toString: '$_id' },
|
|
55
|
+
name: 1
|
|
56
|
+
};
|
|
57
|
+
const nameEq = params.name?.$eq;
|
|
58
|
+
// インデックス'executeOneByNameIfExists'を想定したfilter
|
|
59
|
+
const filter = {
|
|
60
|
+
status: { $eq: factory_1.factory.taskStatus.Ready },
|
|
61
|
+
runsAt: { $lt: params.runsAt.$lt },
|
|
62
|
+
name: params.name
|
|
63
|
+
};
|
|
64
|
+
const doc = await this.taskModel.findOneAndUpdate(filter, {
|
|
65
|
+
$set: {
|
|
66
|
+
status: factory_1.factory.taskStatus.Running, // 実行中に変更
|
|
67
|
+
lastTriedAt: new Date(),
|
|
68
|
+
executor: params.executor
|
|
69
|
+
},
|
|
70
|
+
$inc: {
|
|
71
|
+
remainingNumberOfTries: -1, // 残りトライ可能回数減らす
|
|
72
|
+
numberOfTried: 1 // トライ回数増やす
|
|
73
|
+
}
|
|
74
|
+
}, {
|
|
75
|
+
new: true,
|
|
76
|
+
projection,
|
|
77
|
+
...(typeof params.sort.numberOfTried === 'number' || typeof params.sort.runsAt === 'number')
|
|
78
|
+
? { sort: params.sort }
|
|
79
|
+
: undefined
|
|
80
|
+
})
|
|
81
|
+
.setOptions({ maxTimeMS: settings_1.MONGO_MAX_TIME_MS })
|
|
82
|
+
.lean()
|
|
83
|
+
.exec();
|
|
84
|
+
if (doc === null) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
const changedTask = {
|
|
88
|
+
id: doc.id,
|
|
89
|
+
status: factory_1.factory.taskStatus.Running,
|
|
90
|
+
name: nameEq
|
|
91
|
+
};
|
|
92
|
+
task_1.taskEventEmitter.emitTaskStatusChanged(changedTask);
|
|
93
|
+
return doc;
|
|
94
|
+
}
|
|
41
95
|
}
|
|
42
96
|
exports.ScheduledTaskLegacyRepo = ScheduledTaskLegacyRepo;
|
|
@@ -56,24 +56,7 @@ export declare class TaskRepo {
|
|
|
56
56
|
expires?: Date;
|
|
57
57
|
}): Promise<IExecutableTask<factory.taskName> | null>;
|
|
58
58
|
/**
|
|
59
|
-
*
|
|
60
|
-
*/
|
|
61
|
-
executeOneIfExists(params: {
|
|
62
|
-
name: {
|
|
63
|
-
$eq: factory.taskName;
|
|
64
|
-
};
|
|
65
|
-
executor: {
|
|
66
|
-
name: string;
|
|
67
|
-
};
|
|
68
|
-
runsAt: {
|
|
69
|
-
$lt: Date;
|
|
70
|
-
};
|
|
71
|
-
sort: {
|
|
72
|
-
numberOfTried?: factory.sortType;
|
|
73
|
-
runsAt?: factory.sortType;
|
|
74
|
-
};
|
|
75
|
-
}): Promise<IExecutableTask<factory.taskName> | null>;
|
|
76
|
-
/**
|
|
59
|
+
* 潜在的に実行されるべきタスクをカウントする
|
|
77
60
|
* add(2025-03-16~)
|
|
78
61
|
*/
|
|
79
62
|
countPotentiallyRunning(params: {
|
|
@@ -84,14 +67,18 @@ export declare class TaskRepo {
|
|
|
84
67
|
runsAt: {
|
|
85
68
|
$lt: Date;
|
|
86
69
|
};
|
|
87
|
-
limit
|
|
70
|
+
limit: number;
|
|
88
71
|
}): Promise<{
|
|
89
72
|
count: number;
|
|
90
73
|
}>;
|
|
91
74
|
/**
|
|
92
|
-
* 実行日時を一定期間過ぎたReadyタスクについて、Running
|
|
75
|
+
* 実行日時を一定期間過ぎたReadyタスクについて、Runningステータスに変更する
|
|
93
76
|
*/
|
|
94
|
-
|
|
77
|
+
private runDelayedTask;
|
|
78
|
+
/**
|
|
79
|
+
* 実行日時を一定期間過ぎたReadyタスクについて、Runningステータスに変更した上で、Runningイベントを発生させる
|
|
80
|
+
*/
|
|
81
|
+
emitRunningIfExistsByName(params: {
|
|
95
82
|
/**
|
|
96
83
|
* 必ずタスク名指定で実行する
|
|
97
84
|
*/
|
|
@@ -112,7 +99,19 @@ export declare class TaskRepo {
|
|
|
112
99
|
executor: {
|
|
113
100
|
name: string;
|
|
114
101
|
};
|
|
115
|
-
|
|
102
|
+
}): Promise<Pick<factory.task.ITask<factory.taskName>, 'id' | 'name'> | null>;
|
|
103
|
+
/**
|
|
104
|
+
* 実行日時を一定期間過ぎたReadyタスクについて、Runningステータスに変更した上で、Runningイベントを発生させる
|
|
105
|
+
* taskNameで絞らない
|
|
106
|
+
* 2026-08-04~
|
|
107
|
+
*/
|
|
108
|
+
emitRunningIfExistsNoName(params: {
|
|
109
|
+
runsAt: {
|
|
110
|
+
$lt: Date;
|
|
111
|
+
};
|
|
112
|
+
executor: {
|
|
113
|
+
name: string;
|
|
114
|
+
};
|
|
116
115
|
}): Promise<Pick<factory.task.ITask<factory.taskName>, 'id' | 'name'> | null>;
|
|
117
116
|
/**
|
|
118
117
|
* Runningのまま一定期間超過し、かつ、remainingNumberOfTries>0のタスクをReadyに変更する
|
|
@@ -129,6 +128,12 @@ export declare class TaskRepo {
|
|
|
129
128
|
$in?: factory.taskName[];
|
|
130
129
|
};
|
|
131
130
|
}): Promise<UpdateWriteOpResult>;
|
|
131
|
+
/**
|
|
132
|
+
* $lte:0をReadyにする(特定のタスクを除いて) -> Readyにすれば自動的にAbortedになる
|
|
133
|
+
*/
|
|
134
|
+
retryAbortingTasks(params: {
|
|
135
|
+
intervalInMinutes: number;
|
|
136
|
+
}): Promise<UpdateWriteOpResult>;
|
|
132
137
|
/**
|
|
133
138
|
* 実行中止済タスクを強制的にリトライ
|
|
134
139
|
* 中止済タスクでなければ何もしない
|
package/lib/chevre/repo/task.js
CHANGED
|
@@ -266,58 +266,76 @@ class TaskRepo {
|
|
|
266
266
|
}
|
|
267
267
|
return doc;
|
|
268
268
|
}
|
|
269
|
+
// 不要なので廃止(2026-08-04~)
|
|
270
|
+
// /**
|
|
271
|
+
// * Readyのタスクをname指定でひとつRunningに変更する
|
|
272
|
+
// */
|
|
273
|
+
// public async executeOneIfExists(params: {
|
|
274
|
+
// name: {
|
|
275
|
+
// $eq: factory.taskName;
|
|
276
|
+
// // $nin?: factory.taskName[]; // discontinue(2025-08-07~)
|
|
277
|
+
// };
|
|
278
|
+
// executor: { name: string };
|
|
279
|
+
// runsAt: {
|
|
280
|
+
// $lt: Date;
|
|
281
|
+
// };
|
|
282
|
+
// sort: {
|
|
283
|
+
// numberOfTried?: factory.sortType; // トライ回数の少なさ優先
|
|
284
|
+
// runsAt?: factory.sortType; // 実行予定日時の早さ優先
|
|
285
|
+
// };
|
|
286
|
+
// }): Promise<IExecutableTask<factory.taskName> | null> {
|
|
287
|
+
// if (!(params.runsAt.$lt instanceof Date)) {
|
|
288
|
+
// throw new factory.errors.Argument('runsAt.$lt', 'must be Date');
|
|
289
|
+
// }
|
|
290
|
+
// const nameEq = params.name?.$eq;
|
|
291
|
+
// // const nameNin = params.name?.$nin;
|
|
292
|
+
// const doc = await this.taskModel.findOneAndUpdate(
|
|
293
|
+
// {
|
|
294
|
+
// status: { $eq: factory.taskStatus.Ready },
|
|
295
|
+
// runsAt: { $lt: params.runsAt.$lt },
|
|
296
|
+
// ...(typeof nameEq === 'string')
|
|
297
|
+
// ? {
|
|
298
|
+
// name: {
|
|
299
|
+
// ...(typeof nameEq === 'string') ? { $eq: nameEq } : undefined
|
|
300
|
+
// // ...(Array.isArray(nameNin)) ? { $nin: nameNin } : undefined
|
|
301
|
+
// }
|
|
302
|
+
// }
|
|
303
|
+
// : undefined
|
|
304
|
+
// },
|
|
305
|
+
// {
|
|
306
|
+
// $set: {
|
|
307
|
+
// status: factory.taskStatus.Running, // 実行中に変更
|
|
308
|
+
// lastTriedAt: new Date(),
|
|
309
|
+
// executor: params.executor
|
|
310
|
+
// },
|
|
311
|
+
// $inc: {
|
|
312
|
+
// remainingNumberOfTries: -1, // 残りトライ可能回数減らす
|
|
313
|
+
// numberOfTried: 1 // トライ回数増やす
|
|
314
|
+
// }
|
|
315
|
+
// },
|
|
316
|
+
// {
|
|
317
|
+
// new: true,
|
|
318
|
+
// projection: executableTaskProjection,
|
|
319
|
+
// ...(typeof params.sort.numberOfTried === 'number' || typeof params.sort.runsAt === 'number')
|
|
320
|
+
// ? { sort: params.sort }
|
|
321
|
+
// : undefined
|
|
322
|
+
// }
|
|
323
|
+
// )
|
|
324
|
+
// .setOptions({ maxTimeMS: MONGO_MAX_TIME_MS })
|
|
325
|
+
// .lean<IExecutableTask<factory.taskName>>() // lean(2024-09-26~)
|
|
326
|
+
// .exec();
|
|
327
|
+
// if (doc === null) {
|
|
328
|
+
// return null;
|
|
329
|
+
// }
|
|
330
|
+
// return doc;
|
|
331
|
+
// }
|
|
269
332
|
/**
|
|
270
|
-
*
|
|
271
|
-
*/
|
|
272
|
-
async executeOneIfExists(params) {
|
|
273
|
-
if (!(params.runsAt.$lt instanceof Date)) {
|
|
274
|
-
throw new factory_1.factory.errors.Argument('runsAt.$lt', 'must be Date');
|
|
275
|
-
}
|
|
276
|
-
const nameEq = params.name?.$eq;
|
|
277
|
-
// const nameNin = params.name?.$nin;
|
|
278
|
-
const doc = await this.taskModel.findOneAndUpdate({
|
|
279
|
-
status: { $eq: factory_1.factory.taskStatus.Ready },
|
|
280
|
-
runsAt: { $lt: params.runsAt.$lt },
|
|
281
|
-
...(typeof nameEq === 'string')
|
|
282
|
-
? {
|
|
283
|
-
name: {
|
|
284
|
-
...(typeof nameEq === 'string') ? { $eq: nameEq } : undefined
|
|
285
|
-
// ...(Array.isArray(nameNin)) ? { $nin: nameNin } : undefined
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
: undefined
|
|
289
|
-
}, {
|
|
290
|
-
$set: {
|
|
291
|
-
status: factory_1.factory.taskStatus.Running, // 実行中に変更
|
|
292
|
-
lastTriedAt: new Date(),
|
|
293
|
-
executor: params.executor
|
|
294
|
-
},
|
|
295
|
-
$inc: {
|
|
296
|
-
remainingNumberOfTries: -1, // 残りトライ可能回数減らす
|
|
297
|
-
numberOfTried: 1 // トライ回数増やす
|
|
298
|
-
}
|
|
299
|
-
}, {
|
|
300
|
-
new: true,
|
|
301
|
-
projection: executableTaskProjection,
|
|
302
|
-
...(typeof params.sort.numberOfTried === 'number' || typeof params.sort.runsAt === 'number')
|
|
303
|
-
? { sort: params.sort }
|
|
304
|
-
: undefined
|
|
305
|
-
})
|
|
306
|
-
.setOptions({ maxTimeMS: settings_1.MONGO_MAX_TIME_MS })
|
|
307
|
-
.lean() // lean(2024-09-26~)
|
|
308
|
-
.exec();
|
|
309
|
-
if (doc === null) {
|
|
310
|
-
return null;
|
|
311
|
-
}
|
|
312
|
-
return doc;
|
|
313
|
-
}
|
|
314
|
-
/**
|
|
333
|
+
* 潜在的に実行されるべきタスクをカウントする
|
|
315
334
|
* add(2025-03-16~)
|
|
316
335
|
*/
|
|
317
336
|
async countPotentiallyRunning(params) {
|
|
318
337
|
const { runsAt, limit, name } = params;
|
|
319
338
|
const nameEq = name?.$eq;
|
|
320
|
-
// const nameNin = name?.$nin;
|
|
321
339
|
const nameIn = name?.$in;
|
|
322
340
|
if (!(runsAt.$lt instanceof Date)) {
|
|
323
341
|
throw new factory_1.factory.errors.Argument('runsAt.$lt', 'must be Date');
|
|
@@ -329,7 +347,6 @@ class TaskRepo {
|
|
|
329
347
|
? {
|
|
330
348
|
name: {
|
|
331
349
|
...(typeof nameEq === 'string') ? { $eq: nameEq } : undefined,
|
|
332
|
-
// ...(Array.isArray(nameNin)) ? { $nin: nameNin } : undefined,
|
|
333
350
|
...(Array.isArray(nameIn)) ? { $in: nameIn } : undefined
|
|
334
351
|
}
|
|
335
352
|
}
|
|
@@ -343,28 +360,16 @@ class TaskRepo {
|
|
|
343
360
|
return { count };
|
|
344
361
|
}
|
|
345
362
|
/**
|
|
346
|
-
* 実行日時を一定期間過ぎたReadyタスクについて、Running
|
|
363
|
+
* 実行日時を一定期間過ぎたReadyタスクについて、Runningステータスに変更する
|
|
347
364
|
*/
|
|
348
|
-
async
|
|
349
|
-
|
|
350
|
-
throw new factory_1.factory.errors.Argument('runsAt.$lt', 'must be Date');
|
|
351
|
-
}
|
|
365
|
+
async runDelayedTask(params) {
|
|
366
|
+
const { filter } = params;
|
|
352
367
|
const projection = {
|
|
353
368
|
_id: 0,
|
|
354
369
|
id: { $toString: '$_id' },
|
|
355
370
|
name: 1
|
|
356
371
|
};
|
|
357
|
-
|
|
358
|
-
// const nameNin = params.name?.$nin;
|
|
359
|
-
// const nameIn = params.name?.$in;
|
|
360
|
-
const { nameFilterBeforeRunsAt } = params;
|
|
361
|
-
const filter = {
|
|
362
|
-
status: { $eq: factory_1.factory.taskStatus.Ready },
|
|
363
|
-
...(nameFilterBeforeRunsAt) ? { name: params.name } : undefined,
|
|
364
|
-
runsAt: { $lt: params.runsAt.$lt },
|
|
365
|
-
...(!nameFilterBeforeRunsAt) ? { name: params.name } : undefined
|
|
366
|
-
};
|
|
367
|
-
const doc = await this.taskModel.findOneAndUpdate(filter, {
|
|
372
|
+
return this.taskModel.findOneAndUpdate(filter, {
|
|
368
373
|
$set: {
|
|
369
374
|
status: factory_1.factory.taskStatus.Running, // 実行中に変更
|
|
370
375
|
lastTriedAt: new Date(),
|
|
@@ -384,9 +389,58 @@ class TaskRepo {
|
|
|
384
389
|
.setOptions({ maxTimeMS: settings_1.MONGO_MAX_TIME_MS })
|
|
385
390
|
.lean()
|
|
386
391
|
.exec();
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* 実行日時を一定期間過ぎたReadyタスクについて、Runningステータスに変更した上で、Runningイベントを発生させる
|
|
395
|
+
*/
|
|
396
|
+
async emitRunningIfExistsByName(params) {
|
|
397
|
+
if (!(params.runsAt.$lt instanceof Date)) {
|
|
398
|
+
throw new factory_1.factory.errors.Argument('runsAt.$lt', 'must be Date');
|
|
399
|
+
}
|
|
400
|
+
// const projection: ProjectionType<IDocType> = {
|
|
401
|
+
// _id: 0,
|
|
402
|
+
// id: { $toString: '$_id' },
|
|
403
|
+
// name: 1
|
|
404
|
+
// };
|
|
405
|
+
// インデックス'executeOneByNameIfExists'を想定したfilter
|
|
406
|
+
const filter = {
|
|
407
|
+
status: { $eq: factory_1.factory.taskStatus.Ready },
|
|
408
|
+
runsAt: { $lt: params.runsAt.$lt },
|
|
409
|
+
name: params.name
|
|
410
|
+
};
|
|
411
|
+
const doc = await this.runDelayedTask({
|
|
412
|
+
filter,
|
|
413
|
+
sort: params.sort,
|
|
414
|
+
executor: params.executor
|
|
415
|
+
});
|
|
416
|
+
// const doc = await this.taskModel.findOneAndUpdate(
|
|
417
|
+
// filter,
|
|
418
|
+
// {
|
|
419
|
+
// $set: {
|
|
420
|
+
// status: factory.taskStatus.Running, // 実行中に変更
|
|
421
|
+
// lastTriedAt: new Date(),
|
|
422
|
+
// executor: params.executor
|
|
423
|
+
// },
|
|
424
|
+
// $inc: {
|
|
425
|
+
// remainingNumberOfTries: -1, // 残りトライ可能回数減らす
|
|
426
|
+
// numberOfTried: 1 // トライ回数増やす
|
|
427
|
+
// }
|
|
428
|
+
// },
|
|
429
|
+
// {
|
|
430
|
+
// new: true,
|
|
431
|
+
// projection,
|
|
432
|
+
// ...(typeof params.sort.numberOfTried === 'number' || typeof params.sort.runsAt === 'number')
|
|
433
|
+
// ? { sort: params.sort }
|
|
434
|
+
// : undefined
|
|
435
|
+
// }
|
|
436
|
+
// )
|
|
437
|
+
// .setOptions({ maxTimeMS: MONGO_MAX_TIME_MS })
|
|
438
|
+
// .lean<Pick<factory.task.ITask<factory.taskName>, 'id' | 'name'>>()
|
|
439
|
+
// .exec();
|
|
387
440
|
if (doc === null) {
|
|
388
441
|
return null;
|
|
389
442
|
}
|
|
443
|
+
const nameEq = params.name?.$eq;
|
|
390
444
|
let changedTask;
|
|
391
445
|
if (typeof nameEq === 'string') {
|
|
392
446
|
changedTask = {
|
|
@@ -404,6 +458,37 @@ class TaskRepo {
|
|
|
404
458
|
task_1.taskEventEmitter.emitTaskStatusChanged(changedTask);
|
|
405
459
|
return doc;
|
|
406
460
|
}
|
|
461
|
+
/**
|
|
462
|
+
* 実行日時を一定期間過ぎたReadyタスクについて、Runningステータスに変更した上で、Runningイベントを発生させる
|
|
463
|
+
* taskNameで絞らない
|
|
464
|
+
* 2026-08-04~
|
|
465
|
+
*/
|
|
466
|
+
async emitRunningIfExistsNoName(params) {
|
|
467
|
+
if (!(params.runsAt.$lt instanceof Date)) {
|
|
468
|
+
throw new factory_1.factory.errors.Argument('runsAt.$lt', 'must be Date');
|
|
469
|
+
}
|
|
470
|
+
// インデックス'executeOneByNameIfExists'を想定したfilter
|
|
471
|
+
const filter = {
|
|
472
|
+
status: { $eq: factory_1.factory.taskStatus.Ready },
|
|
473
|
+
runsAt: { $lt: params.runsAt.$lt }
|
|
474
|
+
};
|
|
475
|
+
const doc = await this.runDelayedTask({
|
|
476
|
+
filter,
|
|
477
|
+
sort: {
|
|
478
|
+
runsAt: factory_1.factory.sortType.Ascending // ソートはrunsAtのみにしてみる(2026-08-04~)
|
|
479
|
+
},
|
|
480
|
+
executor: params.executor
|
|
481
|
+
});
|
|
482
|
+
if (doc === null) {
|
|
483
|
+
return null;
|
|
484
|
+
}
|
|
485
|
+
const changedTask = {
|
|
486
|
+
id: doc.id,
|
|
487
|
+
status: factory_1.factory.taskStatus.Running
|
|
488
|
+
};
|
|
489
|
+
task_1.taskEventEmitter.emitTaskStatusChanged(changedTask);
|
|
490
|
+
return doc;
|
|
491
|
+
}
|
|
407
492
|
/**
|
|
408
493
|
* Runningのまま一定期間超過し、かつ、remainingNumberOfTries>0のタスクをReadyに変更する
|
|
409
494
|
*/
|
|
@@ -470,6 +555,30 @@ class TaskRepo {
|
|
|
470
555
|
})
|
|
471
556
|
.exec();
|
|
472
557
|
}
|
|
558
|
+
/**
|
|
559
|
+
* $lte:0をReadyにする(特定のタスクを除いて) -> Readyにすれば自動的にAbortedになる
|
|
560
|
+
*/
|
|
561
|
+
async retryAbortingTasks(params) {
|
|
562
|
+
const lastTriedAtShoudBeLessThan = (0, moment_1.default)()
|
|
563
|
+
.add(-params.intervalInMinutes, 'minutes')
|
|
564
|
+
.toDate();
|
|
565
|
+
return this.taskModel.updateMany(
|
|
566
|
+
// name: 'retry'のindexと連動しているので、条件の順序などには注意すること
|
|
567
|
+
// @see schemas/task
|
|
568
|
+
{
|
|
569
|
+
status: { $eq: factory_1.factory.taskStatus.Running },
|
|
570
|
+
lastTriedAt: {
|
|
571
|
+
$type: 'date',
|
|
572
|
+
$lt: lastTriedAtShoudBeLessThan
|
|
573
|
+
},
|
|
574
|
+
remainingNumberOfTries: { $lte: 0 }
|
|
575
|
+
}, {
|
|
576
|
+
$set: {
|
|
577
|
+
status: factory_1.factory.taskStatus.Ready // 実行前に変更
|
|
578
|
+
}
|
|
579
|
+
})
|
|
580
|
+
.exec();
|
|
581
|
+
}
|
|
473
582
|
/**
|
|
474
583
|
* 実行中止済タスクを強制的にリトライ
|
|
475
584
|
* 中止済タスクでなければ何もしない
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { IExecuteSettings as IMinimumExecuteSettings, INextFunction, IReadyTask, IRunningTask } from '../eventEmitter/task';
|
|
2
|
-
import { factory } from '../factory';
|
|
3
2
|
import type { AggregationSettings } from '../taskSettings';
|
|
4
3
|
interface IExecuteSettings extends IMinimumExecuteSettings {
|
|
5
4
|
aggregationSettings?: AggregationSettings;
|
|
@@ -16,22 +15,4 @@ declare function executeById(params: (IReadyTask | IRunningTask) & {
|
|
|
16
15
|
name: string;
|
|
17
16
|
};
|
|
18
17
|
}, next?: INextFunction): IOperation<void>;
|
|
19
|
-
|
|
20
|
-
name: {
|
|
21
|
-
$eq: factory.taskName;
|
|
22
|
-
};
|
|
23
|
-
executor: {
|
|
24
|
-
/**
|
|
25
|
-
* タスク実行者名称
|
|
26
|
-
*/
|
|
27
|
-
name: string;
|
|
28
|
-
};
|
|
29
|
-
runsAt: {
|
|
30
|
-
$lt: Date;
|
|
31
|
-
};
|
|
32
|
-
sort: {
|
|
33
|
-
numberOfTried?: factory.sortType;
|
|
34
|
-
runsAt?: factory.sortType;
|
|
35
|
-
};
|
|
36
|
-
}): IOperation<void>;
|
|
37
|
-
export { executeById, executeOneIfExists };
|
|
18
|
+
export { executeById, };
|
|
@@ -4,7 +4,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.executeById = executeById;
|
|
7
|
-
exports.executeOneIfExists = executeOneIfExists;
|
|
8
7
|
/**
|
|
9
8
|
* タスクサービス
|
|
10
9
|
*/
|
|
@@ -41,30 +40,3 @@ function executeById(params, next) {
|
|
|
41
40
|
}
|
|
42
41
|
};
|
|
43
42
|
}
|
|
44
|
-
function executeOneIfExists(params) {
|
|
45
|
-
return async (settings) => {
|
|
46
|
-
const taskRepo = new (await import('../repo/task.js')).TaskRepo(settings.connection);
|
|
47
|
-
// 未実行のタスクを取得
|
|
48
|
-
let task = null;
|
|
49
|
-
try {
|
|
50
|
-
task = await taskRepo.executeOneIfExists({
|
|
51
|
-
executor: { name: params.executor.name },
|
|
52
|
-
runsAt: { $lt: params.runsAt.$lt },
|
|
53
|
-
name: params.name,
|
|
54
|
-
sort: params.sort
|
|
55
|
-
});
|
|
56
|
-
debug('executable task found.', task, params.runsAt.$lt);
|
|
57
|
-
}
|
|
58
|
-
catch (error) {
|
|
59
|
-
/* istanbul ignore next */
|
|
60
|
-
debug('executeOne error:', error);
|
|
61
|
-
}
|
|
62
|
-
// タスクがなければ終了
|
|
63
|
-
if (task !== null) {
|
|
64
|
-
await (0, taskHandler_1.executeTask)(task)(settings, {
|
|
65
|
-
executeById: false,
|
|
66
|
-
executeByName: (typeof params.name?.$eq === 'string')
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
}
|
package/package.json
CHANGED