@chevre/domain 25.2.0-alpha.45 → 25.2.0-alpha.46
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/service/asyncAction.d.ts +12 -0
- package/lib/chevre/service/asyncAction.js +38 -0
- package/lib/chevre/service/asyncActionHandler/onOperationFailed.d.ts +20 -0
- package/lib/chevre/service/asyncActionHandler/onOperationFailed.js +84 -0
- package/lib/chevre/service/asyncActionHandler.d.ts +13 -0
- package/lib/chevre/service/asyncActionHandler.js +96 -0
- package/lib/chevre/service.d.ts +4 -0
- package/lib/chevre/service.js +12 -1
- package/package.json +1 -1
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { IExecuteSettings as IMinimumExecuteSettings, INextFunction, IReadyTask } from '../eventEmitter/task';
|
|
2
|
+
type IExecuteSettings = IMinimumExecuteSettings;
|
|
3
|
+
type IOperation<T> = (settings: IExecuteSettings) => Promise<T>;
|
|
4
|
+
declare function executeAsyncActionById(params: IReadyTask & {
|
|
5
|
+
executor: {
|
|
6
|
+
/**
|
|
7
|
+
* タスク実行者名称
|
|
8
|
+
*/
|
|
9
|
+
name: string;
|
|
10
|
+
};
|
|
11
|
+
}, next?: INextFunction): IOperation<void>;
|
|
12
|
+
export { executeAsyncActionById };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.executeAsyncActionById = executeAsyncActionById;
|
|
7
|
+
/**
|
|
8
|
+
* 非同期アクションサービス
|
|
9
|
+
*/
|
|
10
|
+
const debug_1 = __importDefault(require("debug"));
|
|
11
|
+
const asyncActionHandler_1 = require("./asyncActionHandler");
|
|
12
|
+
const debug = (0, debug_1.default)('chevre-domain:service:task');
|
|
13
|
+
function executeAsyncActionById(params, next) {
|
|
14
|
+
return async (settings) => {
|
|
15
|
+
const taskRepo = new (await import('../repo/task.js')).TaskRepo(settings.connection);
|
|
16
|
+
const { id, status, executor, expires } = params;
|
|
17
|
+
let task = null;
|
|
18
|
+
try {
|
|
19
|
+
task = await taskRepo.executeOneById({
|
|
20
|
+
id,
|
|
21
|
+
status,
|
|
22
|
+
executor: { name: executor.name },
|
|
23
|
+
...(expires instanceof Date) ? { expires } : undefined
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
/* istanbul ignore next */
|
|
28
|
+
debug('service.asyncAction.executeAsyncActionById error:', error);
|
|
29
|
+
}
|
|
30
|
+
// タスクがなければ終了
|
|
31
|
+
if (task !== null) {
|
|
32
|
+
await (0, asyncActionHandler_1.executeAsyncAction)(task, (typeof next === 'function') ? next : undefined)(settings, {
|
|
33
|
+
executeById: true,
|
|
34
|
+
executeByName: false
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { IExecutedTask, INextFunction } from '../../eventEmitter/task';
|
|
2
|
+
import { factory } from '../../factory';
|
|
3
|
+
import type { SettingRepo } from '../../repo/setting';
|
|
4
|
+
import type { TaskRepo } from '../../repo/task';
|
|
5
|
+
import type { IExecutableTask } from '../../taskSettings';
|
|
6
|
+
/**
|
|
7
|
+
* タスク実行失敗時処理
|
|
8
|
+
*/
|
|
9
|
+
declare function onOperationFailed(params: {
|
|
10
|
+
task: IExecutableTask<factory.taskName>;
|
|
11
|
+
now: Date;
|
|
12
|
+
error: any;
|
|
13
|
+
next?: INextFunction;
|
|
14
|
+
}): (repos: {
|
|
15
|
+
setting: SettingRepo;
|
|
16
|
+
task: TaskRepo;
|
|
17
|
+
}) => Promise<{
|
|
18
|
+
executedTask: IExecutedTask;
|
|
19
|
+
}>;
|
|
20
|
+
export { onOperationFailed };
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.onOperationFailed = onOperationFailed;
|
|
4
|
+
const factory_1 = require("../../factory");
|
|
5
|
+
/**
|
|
6
|
+
* タスク実行失敗時処理
|
|
7
|
+
*/
|
|
8
|
+
function onOperationFailed(params) {
|
|
9
|
+
return async (repos) => {
|
|
10
|
+
let error = params.error;
|
|
11
|
+
const { task, now, next } = params;
|
|
12
|
+
if (typeof error !== 'object') {
|
|
13
|
+
error = { message: String(error) };
|
|
14
|
+
}
|
|
15
|
+
const endDate = new Date();
|
|
16
|
+
let executedTask;
|
|
17
|
+
// remainingNumberOfTries<=0ならAborted(2025-08-04~)
|
|
18
|
+
const isRetryable = task.remainingNumberOfTries > 0;
|
|
19
|
+
if (isRetryable) {
|
|
20
|
+
// 実験的に実行中タスク連携をしてみたが、ひとまず廃止(2026-07-01~)
|
|
21
|
+
// if (USE_INFORM_TASK_RUNNING) {
|
|
22
|
+
// await informTaskIfNeeded({ task, executionEndDate: endDate })(repos);
|
|
23
|
+
// }
|
|
24
|
+
const result = {
|
|
25
|
+
executedAt: now,
|
|
26
|
+
endDate,
|
|
27
|
+
error: {
|
|
28
|
+
...error,
|
|
29
|
+
code: error.code,
|
|
30
|
+
message: error.message,
|
|
31
|
+
name: error.name,
|
|
32
|
+
stack: error.stack
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
// 失敗してもここではステータスを戻さない(Runningのまま待機)
|
|
36
|
+
await 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
|
+
executedTask = {
|
|
45
|
+
id: task.id,
|
|
46
|
+
remainingNumberOfTries: task.remainingNumberOfTries,
|
|
47
|
+
name: task.name,
|
|
48
|
+
status: task.status,
|
|
49
|
+
executionResult: result
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
// one time taskは分析連携しない
|
|
54
|
+
// await informTaskIfNeeded({ task, executionEndDate: endDate })(repos);
|
|
55
|
+
const result = {
|
|
56
|
+
executedAt: now,
|
|
57
|
+
endDate,
|
|
58
|
+
error: {
|
|
59
|
+
...error,
|
|
60
|
+
code: error.code,
|
|
61
|
+
message: error.message,
|
|
62
|
+
name: error.name,
|
|
63
|
+
stack: error.stack
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
await repos.task.setExecutionResultAndStatus({
|
|
67
|
+
id: task.id,
|
|
68
|
+
remainingNumberOfTries: task.remainingNumberOfTries,
|
|
69
|
+
name: task.name
|
|
70
|
+
}, {
|
|
71
|
+
status: factory_1.factory.taskStatus.Aborted,
|
|
72
|
+
executionResult: result
|
|
73
|
+
}, (typeof next === 'function') ? next : undefined);
|
|
74
|
+
executedTask = {
|
|
75
|
+
id: task.id,
|
|
76
|
+
remainingNumberOfTries: task.remainingNumberOfTries,
|
|
77
|
+
name: task.name,
|
|
78
|
+
status: task.status,
|
|
79
|
+
executionResult: result
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
return { executedTask };
|
|
83
|
+
};
|
|
84
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { INextFunction } from '../eventEmitter/task';
|
|
2
|
+
import { factory } from '../factory';
|
|
3
|
+
import type { ICallResult, ICallableTaskOperation, IExecutableTask, IExecutableTaskKeys, IOperationExecute } from '../taskSettings';
|
|
4
|
+
export declare const taskLoader: {
|
|
5
|
+
load: (taskName: string) => Promise<{
|
|
6
|
+
call: ICallableTaskOperation;
|
|
7
|
+
}>;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* 非同期アクションを実行する
|
|
11
|
+
*/
|
|
12
|
+
declare function executeAsyncAction(task: IExecutableTask<factory.taskName>, next?: INextFunction): IOperationExecute<void>;
|
|
13
|
+
export { ICallableTaskOperation, ICallResult, IExecutableTaskKeys, IOperationExecute, executeAsyncAction };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.taskLoader = void 0;
|
|
7
|
+
exports.executeAsyncAction = executeAsyncAction;
|
|
8
|
+
const debug_1 = __importDefault(require("debug"));
|
|
9
|
+
const moment_1 = __importDefault(require("moment"));
|
|
10
|
+
const factory_1 = require("../factory");
|
|
11
|
+
const onOperationFailed_1 = require("./asyncActionHandler/onOperationFailed");
|
|
12
|
+
const debug = (0, debug_1.default)('chevre-domain:service:asyncActionHandler');
|
|
13
|
+
exports.taskLoader = {
|
|
14
|
+
load: (taskName) => {
|
|
15
|
+
return import(`./task/${taskName}.js`);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* 非同期アクションを実行する
|
|
20
|
+
*/
|
|
21
|
+
function executeAsyncAction(task, next) {
|
|
22
|
+
const now = new Date();
|
|
23
|
+
debug('executing an executableTask...', task, now);
|
|
24
|
+
return async (settings, options) => {
|
|
25
|
+
const settingRepo = new (await import('../repo/setting.js')).SettingRepo(settings.connection);
|
|
26
|
+
const taskRepo = new (await import('../repo/task.js')).TaskRepo(settings.connection);
|
|
27
|
+
let executedTask;
|
|
28
|
+
try {
|
|
29
|
+
// 期限検証(2024-04-23~)
|
|
30
|
+
if (task.expires instanceof Date) {
|
|
31
|
+
const taskExpired = (0, moment_1.default)(now)
|
|
32
|
+
.isAfter(task.expires);
|
|
33
|
+
if (taskExpired) {
|
|
34
|
+
throw new factory_1.factory.errors.Internal(`task expired [expires:${task.expires}]`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// remainingNumberOfTries<0ならcallを実行しない(2025-08-04~)
|
|
38
|
+
// リトライを繰り返した後、不明の原因でRunningのまま残ってしまったタスクがリトライされたケース
|
|
39
|
+
const { remainingNumberOfTries } = task;
|
|
40
|
+
const isCallable = remainingNumberOfTries >= 0;
|
|
41
|
+
if (!isCallable) {
|
|
42
|
+
throw new factory_1.factory.errors.Internal(`task remainingNumberOfTries < 0 [remainingNumberOfTries:${remainingNumberOfTries}]`);
|
|
43
|
+
}
|
|
44
|
+
// タスク名の関数が定義されていなければ、TypeErrorとなる
|
|
45
|
+
const { call } = await exports.taskLoader.load(task.name); // testが書きづらいのでtaskLoader経由で呼ぶ
|
|
46
|
+
const callResult = await call(task)(settings, options);
|
|
47
|
+
const result = {
|
|
48
|
+
executedAt: now,
|
|
49
|
+
endDate: new Date(),
|
|
50
|
+
// enable overwriting task.executionResults.error on Executed(2024-05-29~)
|
|
51
|
+
error: (callResult?.error instanceof Error)
|
|
52
|
+
? {
|
|
53
|
+
...callResult.error,
|
|
54
|
+
message: callResult.error.message
|
|
55
|
+
}
|
|
56
|
+
: ''
|
|
57
|
+
};
|
|
58
|
+
await taskRepo.setExecutionResultAndStatus({
|
|
59
|
+
id: task.id,
|
|
60
|
+
remainingNumberOfTries,
|
|
61
|
+
name: task.name
|
|
62
|
+
}, {
|
|
63
|
+
status: factory_1.factory.taskStatus.Executed,
|
|
64
|
+
executionResult: result
|
|
65
|
+
});
|
|
66
|
+
executedTask = {
|
|
67
|
+
id: task.id,
|
|
68
|
+
remainingNumberOfTries: 0, // one timeの前提なのでひとまず固定で0
|
|
69
|
+
name: task.name,
|
|
70
|
+
status: factory_1.factory.taskStatus.Executed,
|
|
71
|
+
executionResult: result
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
const onOperationFailedResult = await (0, onOperationFailed_1.onOperationFailed)({
|
|
76
|
+
task, now, error,
|
|
77
|
+
// ...(typeof next === 'function') ? { next } : undefined // タスクステータス変更イベントを発生させない
|
|
78
|
+
})({ setting: settingRepo, task: taskRepo });
|
|
79
|
+
executedTask = onOperationFailedResult.executedTask;
|
|
80
|
+
}
|
|
81
|
+
finally {
|
|
82
|
+
if (typeof next === 'function') {
|
|
83
|
+
if (executedTask === undefined) {
|
|
84
|
+
executedTask = {
|
|
85
|
+
id: task.id,
|
|
86
|
+
remainingNumberOfTries: 0, // one timeの前提なのでひとまず固定で0
|
|
87
|
+
name: task.name,
|
|
88
|
+
status: factory_1.factory.taskStatus.Aborted,
|
|
89
|
+
executionResult: {} // eslint-disable-line @typescript-eslint/no-explicit-any
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
await next(executedTask)(settings);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
}
|
package/lib/chevre/service.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ import type * as AnyPaymentService from './service/payment/any';
|
|
|
17
17
|
import type * as ProjectService from './service/project';
|
|
18
18
|
import type * as ReserveService from './service/reserve';
|
|
19
19
|
import type * as TaskService from './service/task';
|
|
20
|
+
import type * as AsyncActionService from './service/asyncAction';
|
|
20
21
|
import type * as TransactionService from './service/transaction';
|
|
21
22
|
export declare namespace aggregation {
|
|
22
23
|
function createService(): Promise<typeof AggregationService>;
|
|
@@ -53,6 +54,9 @@ export declare namespace reserve {
|
|
|
53
54
|
export declare namespace task {
|
|
54
55
|
function createService(): Promise<typeof TaskService>;
|
|
55
56
|
}
|
|
57
|
+
export declare namespace asyncAction {
|
|
58
|
+
function createService(): Promise<typeof AsyncActionService>;
|
|
59
|
+
}
|
|
56
60
|
export declare namespace transaction {
|
|
57
61
|
function createService(): Promise<typeof TransactionService>;
|
|
58
62
|
}
|
package/lib/chevre/service.js
CHANGED
|
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.factory = exports.transaction = exports.task = exports.reserve = exports.project = exports.payment = exports.order = exports.offer = exports.notification = exports.iam = exports.event = exports.assetTransaction = exports.aggregation = void 0;
|
|
36
|
+
exports.factory = exports.transaction = exports.asyncAction = exports.task = exports.reserve = exports.project = exports.payment = exports.order = exports.offer = exports.notification = exports.iam = exports.event = exports.assetTransaction = exports.aggregation = void 0;
|
|
37
37
|
/* eslint-disable @typescript-eslint/no-namespace */
|
|
38
38
|
/**
|
|
39
39
|
* service module
|
|
@@ -167,6 +167,17 @@ var task;
|
|
|
167
167
|
}
|
|
168
168
|
task.createService = createService;
|
|
169
169
|
})(task || (exports.task = task = {}));
|
|
170
|
+
var asyncAction;
|
|
171
|
+
(function (asyncAction) {
|
|
172
|
+
let service;
|
|
173
|
+
async function createService() {
|
|
174
|
+
if (service === undefined) {
|
|
175
|
+
service = await import('./service/asyncAction.js');
|
|
176
|
+
}
|
|
177
|
+
return service;
|
|
178
|
+
}
|
|
179
|
+
asyncAction.createService = createService;
|
|
180
|
+
})(asyncAction || (exports.asyncAction = asyncAction = {}));
|
|
170
181
|
var transaction;
|
|
171
182
|
(function (transaction) {
|
|
172
183
|
let service;
|
package/package.json
CHANGED