@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.
@@ -24,7 +24,9 @@ async function main() {
24
24
  url: INFORM_TASK_AGG_URL
25
25
  }
26
26
  }],
27
- informTaskNames: []
27
+ informTaskNames: [
28
+ chevre.factory.taskName.Pay
29
+ ]
28
30
  }
29
31
  }
30
32
  );
@@ -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
- * support no name(2025-03-04~)
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: INextFunction): Promise<Pick<factory.task.ITask<factory.taskName>, 'id' | 'name'> | null>;
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
- * make tasks expired
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
- retry(params: {
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
- pushExecutionResultById(params: {
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
- }, executionResult: factory.task.IExecutionResult, next?: INextFunction): Promise<void>;
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
  }>;
@@ -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
- * support no name(2025-03-04~)
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
- * make tasks expired
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
- retry(params) {
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
- return this.taskModel.updateMany({
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: 0 }
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
- pushExecutionResultById(params, executionResult,
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, status, remainingNumberOfTries, name } = params;
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.pushExecutionResultById({
125
+ yield taskRepo.setExecutionResultAndStatus({
74
126
  id: task.id,
75
- status: factory.taskStatus.Executed,
76
- remainingNumberOfTries: task.remainingNumberOfTries,
127
+ remainingNumberOfTries,
77
128
  name: task.name
78
- }, result, (typeof next === 'function') ? next : undefined);
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
- if (typeof error !== 'object') {
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
@@ -115,5 +115,5 @@
115
115
  "postversion": "git push origin --tags",
116
116
  "prepublishOnly": "npm run clean && npm run build && npm test && npm run doc"
117
117
  },
118
- "version": "22.11.0-alpha.19"
118
+ "version": "22.11.0-alpha.20"
119
119
  }