@chevre/domain 26.0.0-alpha.13 → 26.0.0-alpha.15

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.
Files changed (48) hide show
  1. package/lib/chevre/eventEmitter/task.d.ts +5 -4
  2. package/lib/chevre/eventEmitter/task.js +2 -2
  3. package/lib/chevre/repo/adminTask.d.ts +12 -0
  4. package/lib/chevre/repo/adminTask.js +24 -0
  5. package/lib/chevre/repo/assetTransaction.d.ts +1 -1
  6. package/lib/chevre/repo/mongoose/schemas/task.js +4 -0
  7. package/lib/chevre/repo/scheduledTask.js +0 -21
  8. package/lib/chevre/repo/task.d.ts +1 -77
  9. package/lib/chevre/repo/task.js +3 -384
  10. package/lib/chevre/repo/taskDelayed.d.ts +67 -0
  11. package/lib/chevre/repo/taskDelayed.js +148 -0
  12. package/lib/chevre/repo/transaction.d.ts +9 -9
  13. package/lib/chevre/repository.d.ts +5 -10
  14. package/lib/chevre/repository.js +11 -22
  15. package/lib/chevre/service/asyncAction.d.ts +2 -2
  16. package/lib/chevre/service/asyncAction.js +2 -2
  17. package/lib/chevre/service/asyncActionHandler.d.ts +4 -4
  18. package/lib/chevre/service/asyncActionHandler.js +11 -13
  19. package/lib/chevre/service/order/confirmPayTransaction.js +4 -1
  20. package/lib/chevre/service/order/onOrderStatusChanged/onOrderInTransit.js +2 -2
  21. package/lib/chevre/service/order/onOrderStatusChanged/onOrderPaymentDue.js +1 -1
  22. package/lib/chevre/service/order/onOrderStatusChanged/onOrderProcessing/createSendEmailMessageTaskIfNotExist.js +1 -1
  23. package/lib/chevre/service/order/onOrderStatusChanged/onOrderProcessing/factory.d.ts +1 -1
  24. package/lib/chevre/service/order/onOrderStatusChanged/onOrderProcessing/factory.js +1 -1
  25. package/lib/chevre/service/order/onOrderStatusChanged/onOrderProcessing/processOrder.js +1 -1
  26. package/lib/chevre/service/project.d.ts +0 -3
  27. package/lib/chevre/service/project.js +0 -1
  28. package/lib/chevre/service/reserve/potentialActions/onReservationConfirmed.js +1 -1
  29. package/lib/chevre/service/scheduledTask.js +1 -1
  30. package/lib/chevre/service/task/acceptCOAOffer.js +1 -14
  31. package/lib/chevre/service/task/authorizePayment.js +1 -7
  32. package/lib/chevre/service/task/checkMovieTicket.js +1 -7
  33. package/lib/chevre/service/task/confirmReserveTransaction.js +3 -1
  34. package/lib/chevre/service/task/publishPaymentUrl.js +1 -10
  35. package/lib/chevre/service/task/syncResourcesFromCOA.js +1 -5
  36. package/lib/chevre/service/task/voidReserveTransaction.js +5 -8
  37. package/lib/chevre/service/task.d.ts +3 -3
  38. package/lib/chevre/service/task.js +3 -3
  39. package/lib/chevre/service/taskHandler/onOperationFailed.d.ts +1 -2
  40. package/lib/chevre/service/taskHandler/onOperationFailed.js +8 -7
  41. package/lib/chevre/service/taskHandler.d.ts +1 -2
  42. package/lib/chevre/service/taskHandler.js +6 -5
  43. package/lib/chevre/taskSettings.d.ts +4 -2
  44. package/package.json +1 -1
  45. package/lib/chevre/repo/asyncActionLegacy.d.ts +0 -23
  46. package/lib/chevre/repo/asyncActionLegacy.js +0 -59
  47. package/lib/chevre/repo/scheduledTaskLegacy.d.ts +0 -39
  48. package/lib/chevre/repo/scheduledTaskLegacy.js +0 -96
@@ -33,7 +33,6 @@ class TaskRepo {
33
33
  }
34
34
  async saveMany(taskAttributes) {
35
35
  const emitImmediately = true; // always true(2026-07-30~)
36
- // const emitImmediately = options?.emitImmediately === true;
37
36
  if (taskAttributes.length > 0) {
38
37
  const creatingTasks = taskAttributes.map(({ identifier, ...creatingTask }) => creatingTask); // eslint-disable-line @typescript-eslint/no-unused-vars
39
38
  const result = await this.taskModel.insertMany(creatingTasks, { ordered: false, rawResult: true });
@@ -51,14 +50,7 @@ class TaskRepo {
51
50
  status: factory_1.factory.taskStatus.Ready
52
51
  });
53
52
  });
54
- // taskAttributes.forEach((savedTask) => {
55
- // taskEventEmitter.emitTaskStatusChanged({
56
- // name: savedTask.name,
57
- // status: factory.taskStatus.Ready
58
- // });
59
- // });
60
53
  }
61
- // return result.ops;
62
54
  return savedTasks;
63
55
  }
64
56
  else {
@@ -109,12 +101,6 @@ class TaskRepo {
109
101
  if (typeof params.identifier !== 'string' || params.identifier.length === 0) {
110
102
  throw new factory_1.factory.errors.ArgumentNull('identifier');
111
103
  }
112
- if (typeof params.alternateName !== 'string' || params.alternateName.length === 0) {
113
- throw new factory_1.factory.errors.ArgumentNull('alternateName');
114
- }
115
- if (params.identifier !== params.alternateName) {
116
- throw new factory_1.factory.errors.Argument('identifier,alternateName not matched');
117
- }
118
104
  let createdTask;
119
105
  const filterQuery = {
120
106
  'project.id': { $eq: params.project.id },
@@ -160,63 +146,6 @@ class TaskRepo {
160
146
  throw new factory_1.factory.errors.Internal(`falied in creating a task unexpectedly. ${params.identifier}`);
161
147
  }
162
148
  }
163
- // /**
164
- // * 取引削除タスク冪等作成
165
- // */
166
- // public async createDeleteTransactionTaskIfNotExist(
167
- // // resolve uniqueness of identifier(2025-03-27~)
168
- // params: Pick<
169
- // factory.task.IAttributes<factory.taskName.DeleteTransaction>,
170
- // 'data' | 'executionResults' | 'name' | 'numberOfTried' | 'project' | 'remainingNumberOfTries' | 'runsAt' | 'status'
171
- // >,
172
- // options: IOptionOnCreate
173
- // ): Promise<void> {
174
- // if (params.data.object.specifyingMethod !== factory.action.update.deleteAction.ObjectAsTransactionSpecifyingMethod.Id) {
175
- // throw new factory.errors.NotImplemented(`only ${factory.action.update.deleteAction.ObjectAsTransactionSpecifyingMethod.Id} implemented`);
176
- // }
177
- // const createdTask = await this.taskModel.findOneAndUpdate(
178
- // {
179
- // 'project.id': { $eq: params.project.id },
180
- // name: { $eq: params.name },
181
- // 'data.object.id': { $exists: true, $eq: params.data.object.id }
182
- // },
183
- // { $setOnInsert: params },
184
- // { new: true, upsert: true }
185
- // )
186
- // .select({ _id: 1 })
187
- // .exec();
188
- // if (options.emitImmediately) {
189
- // taskEventEmitter.emitTaskStatusChanged({
190
- // id: createdTask.id,
191
- // name: params.name,
192
- // status: factory.taskStatus.Ready
193
- // });
194
- // }
195
- // }
196
- async createOnAssetTransactionStatusChangedTaskIfNotExist(params) {
197
- const emitImmediately = true; // always true(2026-07-30~)
198
- const createdTask = await this.taskModel.findOneAndUpdate({
199
- 'project.id': { $eq: params.project.id },
200
- name: { $eq: params.name },
201
- 'data.object.transactionNumber': {
202
- $exists: true,
203
- $eq: String(params.data.object.transactionNumber)
204
- },
205
- 'data.purpose.orderNumber': {
206
- $exists: true,
207
- $eq: String(params.data.purpose.orderNumber)
208
- }
209
- }, { $setOnInsert: params }, { new: true, upsert: true })
210
- .select({ _id: 1 })
211
- .exec();
212
- if (emitImmediately) {
213
- task_1.taskEventEmitter.emitTaskStatusChanged({
214
- id: createdTask.id,
215
- name: params.name,
216
- status: factory_1.factory.taskStatus.Ready
217
- });
218
- }
219
- }
220
149
  /**
221
150
  * Ready -> remainingNumberOfTriesが1減る
222
151
  * Running -> findOneするだけ
@@ -261,229 +190,6 @@ class TaskRepo {
261
190
  }
262
191
  return doc;
263
192
  }
264
- // 不要なので廃止(2026-08-04~)
265
- // /**
266
- // * Readyのタスクをname指定でひとつRunningに変更する
267
- // */
268
- // public async executeOneIfExists(params: {
269
- // name: {
270
- // $eq: factory.taskName;
271
- // // $nin?: factory.taskName[]; // discontinue(2025-08-07~)
272
- // };
273
- // executor: { name: string };
274
- // runsAt: {
275
- // $lt: Date;
276
- // };
277
- // sort: {
278
- // numberOfTried?: factory.sortType; // トライ回数の少なさ優先
279
- // runsAt?: factory.sortType; // 実行予定日時の早さ優先
280
- // };
281
- // }): Promise<IExecutableTask<factory.taskName> | null> {
282
- // if (!(params.runsAt.$lt instanceof Date)) {
283
- // throw new factory.errors.Argument('runsAt.$lt', 'must be Date');
284
- // }
285
- // const nameEq = params.name?.$eq;
286
- // // const nameNin = params.name?.$nin;
287
- // const doc = await this.taskModel.findOneAndUpdate(
288
- // {
289
- // status: { $eq: factory.taskStatus.Ready },
290
- // runsAt: { $lt: params.runsAt.$lt },
291
- // ...(typeof nameEq === 'string')
292
- // ? {
293
- // name: {
294
- // ...(typeof nameEq === 'string') ? { $eq: nameEq } : undefined
295
- // // ...(Array.isArray(nameNin)) ? { $nin: nameNin } : undefined
296
- // }
297
- // }
298
- // : undefined
299
- // },
300
- // {
301
- // $set: {
302
- // status: factory.taskStatus.Running, // 実行中に変更
303
- // lastTriedAt: new Date(),
304
- // executor: params.executor
305
- // },
306
- // $inc: {
307
- // remainingNumberOfTries: -1, // 残りトライ可能回数減らす
308
- // numberOfTried: 1 // トライ回数増やす
309
- // }
310
- // },
311
- // {
312
- // new: true,
313
- // projection: executableTaskProjection,
314
- // ...(typeof params.sort.numberOfTried === 'number' || typeof params.sort.runsAt === 'number')
315
- // ? { sort: params.sort }
316
- // : undefined
317
- // }
318
- // )
319
- // .setOptions({ maxTimeMS: MONGO_MAX_TIME_MS })
320
- // .lean<IExecutableTask<factory.taskName>>() // lean(2024-09-26~)
321
- // .exec();
322
- // if (doc === null) {
323
- // return null;
324
- // }
325
- // return doc;
326
- // }
327
- /**
328
- * 潜在的に実行されるべきタスクをカウントする
329
- * add(2025-03-16~)
330
- */
331
- async countPotentiallyRunning(params) {
332
- const { runsAt, limit, name } = params;
333
- const nameEq = name?.$eq;
334
- const nameIn = name?.$in;
335
- if (!(runsAt.$lt instanceof Date)) {
336
- throw new factory_1.factory.errors.Argument('runsAt.$lt', 'must be Date');
337
- }
338
- const query = this.taskModel.countDocuments({
339
- status: { $eq: factory_1.factory.taskStatus.Ready },
340
- runsAt: { $lt: params.runsAt.$lt },
341
- ...(typeof nameEq === 'string' || Array.isArray(nameIn))
342
- ? {
343
- name: {
344
- ...(typeof nameEq === 'string') ? { $eq: nameEq } : undefined,
345
- ...(Array.isArray(nameIn)) ? { $in: nameIn } : undefined
346
- }
347
- }
348
- : undefined
349
- });
350
- if (typeof limit === 'number' && limit >= 0) {
351
- query.limit(limit);
352
- }
353
- const count = await query.setOptions({ maxTimeMS: settings_1.MONGO_MAX_TIME_MS })
354
- .exec();
355
- return { count };
356
- }
357
- /**
358
- * 実行日時を一定期間過ぎたReadyタスクについて、Runningステータスに変更する
359
- */
360
- async runDelayedTask(params) {
361
- const { filter } = params;
362
- const projection = {
363
- _id: 0,
364
- id: { $toString: '$_id' },
365
- name: 1
366
- };
367
- return this.taskModel.findOneAndUpdate(filter, {
368
- $set: {
369
- status: factory_1.factory.taskStatus.Running, // 実行中に変更
370
- lastTriedAt: new Date(),
371
- executor: params.executor
372
- },
373
- $inc: {
374
- remainingNumberOfTries: -1, // 残りトライ可能回数減らす
375
- numberOfTried: 1 // トライ回数増やす
376
- }
377
- }, {
378
- new: true,
379
- projection,
380
- ...(typeof params.sort.numberOfTried === 'number' || typeof params.sort.runsAt === 'number')
381
- ? { sort: params.sort }
382
- : undefined
383
- })
384
- .setOptions({ maxTimeMS: settings_1.MONGO_MAX_TIME_MS })
385
- .lean()
386
- .exec();
387
- }
388
- /**
389
- * 実行日時を一定期間過ぎたReadyタスクについて、Runningステータスに変更した上で、Runningイベントを発生させる
390
- */
391
- async emitRunningIfExistsByName(params) {
392
- if (!(params.runsAt.$lt instanceof Date)) {
393
- throw new factory_1.factory.errors.Argument('runsAt.$lt', 'must be Date');
394
- }
395
- // const projection: ProjectionType<IDocType> = {
396
- // _id: 0,
397
- // id: { $toString: '$_id' },
398
- // name: 1
399
- // };
400
- // インデックス'executeOneByNameIfExists'を想定したfilter
401
- const filter = {
402
- status: { $eq: factory_1.factory.taskStatus.Ready },
403
- runsAt: { $lt: params.runsAt.$lt },
404
- name: params.name
405
- };
406
- const doc = await this.runDelayedTask({
407
- filter,
408
- sort: params.sort,
409
- executor: params.executor
410
- });
411
- // const doc = await this.taskModel.findOneAndUpdate(
412
- // filter,
413
- // {
414
- // $set: {
415
- // status: factory.taskStatus.Running, // 実行中に変更
416
- // lastTriedAt: new Date(),
417
- // executor: params.executor
418
- // },
419
- // $inc: {
420
- // remainingNumberOfTries: -1, // 残りトライ可能回数減らす
421
- // numberOfTried: 1 // トライ回数増やす
422
- // }
423
- // },
424
- // {
425
- // new: true,
426
- // projection,
427
- // ...(typeof params.sort.numberOfTried === 'number' || typeof params.sort.runsAt === 'number')
428
- // ? { sort: params.sort }
429
- // : undefined
430
- // }
431
- // )
432
- // .setOptions({ maxTimeMS: MONGO_MAX_TIME_MS })
433
- // .lean<Pick<factory.task.ITask<factory.taskName>, 'id' | 'name'>>()
434
- // .exec();
435
- if (doc === null) {
436
- return null;
437
- }
438
- const nameEq = params.name?.$eq;
439
- let changedTask;
440
- if (typeof nameEq === 'string') {
441
- changedTask = {
442
- id: doc.id,
443
- status: factory_1.factory.taskStatus.Running,
444
- name: nameEq
445
- };
446
- }
447
- else {
448
- changedTask = {
449
- id: doc.id,
450
- status: factory_1.factory.taskStatus.Running
451
- };
452
- }
453
- task_1.taskEventEmitter.emitTaskStatusChanged(changedTask);
454
- return doc;
455
- }
456
- /**
457
- * 実行日時を一定期間過ぎたReadyタスクについて、Runningステータスに変更した上で、Runningイベントを発生させる
458
- * taskNameで絞らない
459
- * 2026-08-04~
460
- */
461
- async emitRunningIfExistsNoName(params) {
462
- if (!(params.runsAt.$lt instanceof Date)) {
463
- throw new factory_1.factory.errors.Argument('runsAt.$lt', 'must be Date');
464
- }
465
- // インデックス'executeOneByNameIfExists'を想定したfilter
466
- const filter = {
467
- status: { $eq: factory_1.factory.taskStatus.Ready },
468
- runsAt: { $lt: params.runsAt.$lt }
469
- };
470
- const doc = await this.runDelayedTask({
471
- filter,
472
- sort: {
473
- runsAt: factory_1.factory.sortType.Ascending // ソートはrunsAtのみにしてみる(2026-08-04~)
474
- },
475
- executor: params.executor
476
- });
477
- if (doc === null) {
478
- return null;
479
- }
480
- const changedTask = {
481
- id: doc.id,
482
- status: factory_1.factory.taskStatus.Running
483
- };
484
- task_1.taskEventEmitter.emitTaskStatusChanged(changedTask);
485
- return doc;
486
- }
487
193
  /**
488
194
  * Runningのまま一定期間超過し、かつ、remainingNumberOfTries>0のタスクをReadyに変更する
489
195
  */
@@ -491,8 +197,6 @@ class TaskRepo {
491
197
  const lastTriedAtShoudBeLessThan = (0, moment_1.default)()
492
198
  .add(-params.intervalInMinutes, 'minutes')
493
199
  .toDate();
494
- // const remainingNumberOfTriesGte = params.remainingNumberOfTries.$gte;
495
- // const remainingNumberOfTriesLte = params.remainingNumberOfTries.$lte;
496
200
  return this.taskModel.updateMany(
497
201
  // name: 'retry'のindexと連動しているので、条件の順序などには注意すること
498
202
  // @see schemas/task
@@ -502,14 +206,7 @@ class TaskRepo {
502
206
  $type: 'date',
503
207
  $lt: lastTriedAtShoudBeLessThan
504
208
  },
505
- remainingNumberOfTries: { $gte: 1 },
506
- // ...(typeof remainingNumberOfTriesGte === 'number')
507
- // ? { remainingNumberOfTries: { $gte: remainingNumberOfTriesGte } }
508
- // : undefined,
509
- // ...(typeof remainingNumberOfTriesLte === 'number')
510
- // ? { remainingNumberOfTries: { $lte: remainingNumberOfTriesLte } }
511
- // : undefined,
512
- // ...(Array.isArray(params.name.$in)) ? { name: { $in: params.name.$in } } : undefined
209
+ remainingNumberOfTries: { $gte: 1 }
513
210
  }, {
514
211
  $set: {
515
212
  status: factory_1.factory.taskStatus.Ready // 実行前に変更
@@ -524,8 +221,6 @@ class TaskRepo {
524
221
  const lastTriedAtShoudBeLessThan = (0, moment_1.default)()
525
222
  .add(-params.intervalInMinutes, 'minutes')
526
223
  .toDate();
527
- // const remainingNumberOfTriesGte = params.remainingNumberOfTries.$gte;
528
- // const remainingNumberOfTriesLte = params.remainingNumberOfTries.$lte;
529
224
  return this.taskModel.updateMany(
530
225
  // name: 'retry'のindexと連動しているので、条件の順序などには注意すること
531
226
  // @see schemas/task
@@ -536,12 +231,6 @@ class TaskRepo {
536
231
  $lt: lastTriedAtShoudBeLessThan
537
232
  },
538
233
  remainingNumberOfTries: { $lte: 0 },
539
- // ...(typeof remainingNumberOfTriesGte === 'number')
540
- // ? { remainingNumberOfTries: { $gte: remainingNumberOfTriesGte } }
541
- // : undefined,
542
- // ...(typeof remainingNumberOfTriesLte === 'number')
543
- // ? { remainingNumberOfTries: { $lte: remainingNumberOfTriesLte } }
544
- // : undefined,
545
234
  ...(Array.isArray(params.name.$in)) ? { name: { $in: params.name.$in } } : undefined
546
235
  }, {
547
236
  $set: {
@@ -596,10 +285,8 @@ class TaskRepo {
596
285
  * タスクIDから実行結果とステータスを保管する
597
286
  * Abortedの場合、dateAbortedもセットする
598
287
  */
599
- async setExecutionResultAndStatus(params, update,
600
- // support customr function(2025-05-25~)
601
- next) {
602
- const { id, remainingNumberOfTries, name } = params;
288
+ async setExecutionResultAndStatus(params, update) {
289
+ const { id } = params;
603
290
  const { status, executionResult } = update;
604
291
  await this.taskModel.updateOne({ _id: { $eq: id } }, {
605
292
  $set: {
@@ -609,57 +296,6 @@ class TaskRepo {
609
296
  $push: { executionResults: executionResult }
610
297
  })
611
298
  .exec();
612
- // emit event(2025-05-26~)
613
- if (typeof next === 'function') {
614
- const changedTask = { id, name, status, remainingNumberOfTries, executionResult };
615
- task_1.taskEventEmitter.emitTaskStatusChanged(changedTask, next);
616
- }
617
- }
618
- // 非同期アクションへ移行したので不要(2026-08-04~)
619
- // /**
620
- // * タスクの状態を参照する
621
- // * 非同期アクション移行が完了したら廃止する(2026-07-29~)
622
- // */
623
- // public async findTaskById(
624
- // params: {
625
- // id: { $eq: string };
626
- // project: { id: { $eq: string } };
627
- // name: factory.taskName
628
- // },
629
- // inclusion: IKeyOfProjection[]
630
- // ): Promise<(IDocType & { id: string } | undefined)> {
631
- // let positiveProjectionFields: IKeyOfProjection[] = AVAILABLE_PROJECT_FIELDS;
632
- // if (Array.isArray(inclusion) && inclusion.length > 0) {
633
- // positiveProjectionFields = inclusion.filter((key) => AVAILABLE_PROJECT_FIELDS.includes(key));
634
- // } else {
635
- // // no op
636
- // }
637
- // const projection: ProjectionType<IDocType> = {
638
- // _id: 0,
639
- // id: { $toString: '$_id' },
640
- // ...Object.fromEntries<1>(positiveProjectionFields.map((key) => ([key, 1])))
641
- // };
642
- // const query = this.taskModel.findOne(
643
- // {
644
- // _id: { $eq: params.id.$eq },
645
- // 'project.id': { $eq: params.project.id.$eq },
646
- // name: { $eq: params.name }
647
- // },
648
- // projection
649
- // );
650
- // const doc = await query.setOptions({ maxTimeMS: MONGO_MAX_TIME_MS })
651
- // .lean<IDocType & { id: string }>()
652
- // .exec();
653
- // if (doc === null) {
654
- // return;
655
- // }
656
- // return doc;
657
- // }
658
- async deleteByProject(params) {
659
- await this.taskModel.deleteMany({
660
- 'project.id': { $eq: params.project.id }
661
- })
662
- .exec();
663
299
  }
664
300
  /**
665
301
  * 不要なタスクを削除する
@@ -677,22 +313,5 @@ class TaskRepo {
677
313
  })
678
314
  .exec();
679
315
  }
680
- async countDelayedTasks(params) {
681
- const { limit } = params;
682
- const runsAtLt = (0, moment_1.default)()
683
- .add(-params.delayInSeconds, 'seconds')
684
- .toDate();
685
- const query = this.taskModel.countDocuments({
686
- status: { $eq: factory_1.factory.taskStatus.Ready },
687
- runsAt: { $lt: runsAtLt },
688
- ...(Array.isArray(params.name.$nin)) ? { name: { $nin: params.name.$nin } } : undefined
689
- });
690
- if (typeof limit === 'number' && limit >= 0) {
691
- query.limit(limit);
692
- }
693
- const count = await query.setOptions({ maxTimeMS: settings_1.MONGO_MAX_TIME_MS })
694
- .exec();
695
- return { count };
696
- }
697
316
  }
698
317
  exports.TaskRepo = TaskRepo;
@@ -0,0 +1,67 @@
1
+ import type { Connection } from 'mongoose';
2
+ import { factory } from '../factory';
3
+ /**
4
+ * 遅延タスクリポジトリ
5
+ */
6
+ export declare class TaskDelayedRepo {
7
+ private readonly taskModel;
8
+ constructor(connection: Connection);
9
+ /**
10
+ * 潜在的に実行されるべきタスクをカウントする
11
+ * add(2025-03-16~)
12
+ */
13
+ countPotentiallyRunning(params: {
14
+ name?: {
15
+ $eq?: factory.taskName;
16
+ $in?: factory.taskName[];
17
+ };
18
+ runsAt: {
19
+ $lt: Date;
20
+ };
21
+ limit: number;
22
+ }): Promise<{
23
+ count: number;
24
+ }>;
25
+ /**
26
+ * 実行日時を一定期間過ぎたReadyタスクについて、Runningステータスに変更する
27
+ */
28
+ private runDelayedTask;
29
+ /**
30
+ * 実行日時を一定期間過ぎたReadyタスクについて、Runningステータスに変更した上で、Runningイベントを発生させる
31
+ */
32
+ emitRunningIfExistsByName(params: {
33
+ /**
34
+ * 必ずタスク名指定で実行する
35
+ */
36
+ name: {
37
+ $eq: factory.taskName;
38
+ $in?: never;
39
+ } | {
40
+ $eq?: never;
41
+ $in: factory.taskName[];
42
+ };
43
+ runsAt: {
44
+ $lt: Date;
45
+ };
46
+ sort: {
47
+ numberOfTried?: factory.sortType;
48
+ runsAt?: factory.sortType;
49
+ };
50
+ executor: {
51
+ name: string;
52
+ };
53
+ }): Promise<Pick<factory.task.ITask<factory.taskName>, 'id' | 'name'> | null>;
54
+ /**
55
+ * 実行日時を一定期間過ぎたReadyタスクについて、Runningステータスに変更した上で、Runningイベントを発生させる
56
+ * taskNameで絞らない
57
+ * 2026-08-04~
58
+ */
59
+ emitRunningIfExistsNoName(params: {
60
+ runsAt: {
61
+ $lt: Date;
62
+ };
63
+ executor: {
64
+ name: string;
65
+ };
66
+ }): Promise<Pick<factory.task.ITask<factory.taskName>, 'id' | 'name'> | null>;
67
+ }
@@ -0,0 +1,148 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TaskDelayedRepo = void 0;
4
+ const task_1 = require("../eventEmitter/task");
5
+ const factory_1 = require("../factory");
6
+ const settings_1 = require("../settings");
7
+ const task_2 = require("./mongoose/schemas/task");
8
+ /**
9
+ * 遅延タスクリポジトリ
10
+ */
11
+ class TaskDelayedRepo {
12
+ taskModel;
13
+ constructor(connection) {
14
+ this.taskModel = connection.model(task_2.modelName, (0, task_2.createSchema)());
15
+ }
16
+ /**
17
+ * 潜在的に実行されるべきタスクをカウントする
18
+ * add(2025-03-16~)
19
+ */
20
+ async countPotentiallyRunning(params) {
21
+ const { runsAt, limit, name } = params;
22
+ const nameEq = name?.$eq;
23
+ const nameIn = name?.$in;
24
+ if (!(runsAt.$lt instanceof Date)) {
25
+ throw new factory_1.factory.errors.Argument('runsAt.$lt', 'must be Date');
26
+ }
27
+ const query = this.taskModel.countDocuments({
28
+ status: { $eq: factory_1.factory.taskStatus.Ready },
29
+ ...(typeof nameEq === 'string' || Array.isArray(nameIn))
30
+ ? {
31
+ name: {
32
+ ...(typeof nameEq === 'string') ? { $eq: nameEq } : undefined,
33
+ ...(Array.isArray(nameIn)) ? { $in: nameIn } : undefined
34
+ }
35
+ }
36
+ : undefined,
37
+ runsAt: { $lt: params.runsAt.$lt }
38
+ });
39
+ if (typeof limit === 'number' && limit >= 0) {
40
+ query.limit(limit);
41
+ }
42
+ const count = await query.setOptions({ maxTimeMS: settings_1.MONGO_MAX_TIME_MS })
43
+ .exec();
44
+ return { count };
45
+ }
46
+ /**
47
+ * 実行日時を一定期間過ぎたReadyタスクについて、Runningステータスに変更する
48
+ */
49
+ async runDelayedTask(params) {
50
+ const { filter } = params;
51
+ const projection = {
52
+ _id: 0,
53
+ id: { $toString: '$_id' },
54
+ name: 1
55
+ };
56
+ return this.taskModel.findOneAndUpdate(filter, {
57
+ $set: {
58
+ status: factory_1.factory.taskStatus.Running, // 実行中に変更
59
+ lastTriedAt: new Date(),
60
+ executor: params.executor
61
+ },
62
+ $inc: {
63
+ remainingNumberOfTries: -1, // 残りトライ可能回数減らす
64
+ numberOfTried: 1 // トライ回数増やす
65
+ }
66
+ }, {
67
+ new: true,
68
+ projection,
69
+ ...(typeof params.sort.numberOfTried === 'number' || typeof params.sort.runsAt === 'number')
70
+ ? { sort: params.sort }
71
+ : undefined
72
+ })
73
+ .setOptions({ maxTimeMS: settings_1.MONGO_MAX_TIME_MS })
74
+ .lean()
75
+ .exec();
76
+ }
77
+ /**
78
+ * 実行日時を一定期間過ぎたReadyタスクについて、Runningステータスに変更した上で、Runningイベントを発生させる
79
+ */
80
+ async emitRunningIfExistsByName(params) {
81
+ if (!(params.runsAt.$lt instanceof Date)) {
82
+ throw new factory_1.factory.errors.Argument('runsAt.$lt', 'must be Date');
83
+ }
84
+ // インデックス'executeOneByNameIfExists'を想定したfilter
85
+ const filter = {
86
+ status: { $eq: factory_1.factory.taskStatus.Ready },
87
+ name: params.name,
88
+ runsAt: { $lt: params.runsAt.$lt }
89
+ };
90
+ const doc = await this.runDelayedTask({
91
+ filter,
92
+ sort: params.sort,
93
+ executor: params.executor
94
+ });
95
+ if (doc === null) {
96
+ return null;
97
+ }
98
+ const nameEq = params.name?.$eq;
99
+ let changedTask;
100
+ if (typeof nameEq === 'string') {
101
+ changedTask = {
102
+ id: doc.id,
103
+ status: factory_1.factory.taskStatus.Running,
104
+ name: nameEq
105
+ };
106
+ }
107
+ else {
108
+ changedTask = {
109
+ id: doc.id,
110
+ status: factory_1.factory.taskStatus.Running
111
+ };
112
+ }
113
+ task_1.taskEventEmitter.emitTaskStatusChanged(changedTask);
114
+ return doc;
115
+ }
116
+ /**
117
+ * 実行日時を一定期間過ぎたReadyタスクについて、Runningステータスに変更した上で、Runningイベントを発生させる
118
+ * taskNameで絞らない
119
+ * 2026-08-04~
120
+ */
121
+ async emitRunningIfExistsNoName(params) {
122
+ if (!(params.runsAt.$lt instanceof Date)) {
123
+ throw new factory_1.factory.errors.Argument('runsAt.$lt', 'must be Date');
124
+ }
125
+ // インデックス'executeOneByNameIfExists'を想定したfilter
126
+ const filter = {
127
+ status: { $eq: factory_1.factory.taskStatus.Ready },
128
+ runsAt: { $lt: params.runsAt.$lt }
129
+ };
130
+ const doc = await this.runDelayedTask({
131
+ filter,
132
+ sort: {
133
+ runsAt: factory_1.factory.sortType.Ascending // ソートはrunsAtのみにしてみる(2026-08-04~)
134
+ },
135
+ executor: params.executor
136
+ });
137
+ if (doc === null) {
138
+ return null;
139
+ }
140
+ const changedTask = {
141
+ id: doc.id,
142
+ status: factory_1.factory.taskStatus.Running
143
+ };
144
+ task_1.taskEventEmitter.emitTaskStatusChanged(changedTask);
145
+ return doc;
146
+ }
147
+ }
148
+ exports.TaskDelayedRepo = TaskDelayedRepo;