@chevre/domain 25.2.0-alpha.54 → 25.2.0-alpha.56
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 +37 -0
- package/lib/chevre/repo/adminTask.js +163 -0
- package/lib/chevre/repo/aggregateTask.d.ts +38 -0
- package/lib/chevre/repo/aggregateTask.js +136 -0
- package/lib/chevre/repo/scheduledTask.d.ts +52 -0
- package/lib/chevre/repo/scheduledTask.js +113 -0
- package/lib/chevre/repo/task.d.ts +2 -64
- package/lib/chevre/repo/task.js +2 -318
- package/lib/chevre/repository.d.ts +15 -0
- package/lib/chevre/repository.js +35 -2
- package/lib/chevre/service/aggregation/system.d.ts +2 -2
- package/lib/chevre/service/aggregation/system.js +1 -1
- package/lib/chevre/service/notification/notifyAbortedTasksByEmail.d.ts +2 -2
- package/lib/chevre/service/notification/notifyAbortedTasksByEmail.js +1 -1
- package/lib/chevre/service/order/onOrderStatusChanged/onOrderPaymentDue.d.ts +0 -3
- package/lib/chevre/service/order/onOrderStatusChanged/onOrderPaymentDue.js +72 -43
- package/package.json +1 -1
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { AnyKeys, Connection, FilterQuery, ProjectionType } from 'mongoose';
|
|
2
|
+
import { factory } from '../factory';
|
|
3
|
+
import { IModel, IDocType } from './mongoose/schemas/task';
|
|
4
|
+
type IKeyOfProjection = keyof factory.task.ITask<factory.taskName> | 'expires';
|
|
5
|
+
/**
|
|
6
|
+
* タスク管理リポジトリ
|
|
7
|
+
*/
|
|
8
|
+
export declare class AdminTaskRepo {
|
|
9
|
+
readonly taskModel: IModel;
|
|
10
|
+
constructor(connection: Connection);
|
|
11
|
+
static CREATE_MONGO_CONDITIONS(params: factory.task.ISearchConditions): 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>[];
|
|
12
|
+
countTasks(params: factory.task.ISearchConditions): Promise<{
|
|
13
|
+
count: number;
|
|
14
|
+
}>;
|
|
15
|
+
/**
|
|
16
|
+
* 検索する
|
|
17
|
+
*/
|
|
18
|
+
findTasks(params: factory.task.ISearchConditions, inclusion: IKeyOfProjection[]): Promise<factory.task.ITask<factory.taskName>[]>;
|
|
19
|
+
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"> & {
|
|
20
|
+
expires?: Date;
|
|
21
|
+
} & {
|
|
22
|
+
_id: import("mongoose").Types.ObjectId;
|
|
23
|
+
} & {
|
|
24
|
+
__v: number;
|
|
25
|
+
}, import("mongoose").QueryOptions<IDocType>, (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"> & {
|
|
26
|
+
expires?: Date;
|
|
27
|
+
} & {
|
|
28
|
+
_id: import("mongoose").Types.ObjectId;
|
|
29
|
+
} & {
|
|
30
|
+
__v: number;
|
|
31
|
+
}) | null>;
|
|
32
|
+
unsetUnnecessaryFields(params: {
|
|
33
|
+
filter: FilterQuery<factory.task.ITask<factory.taskName>>;
|
|
34
|
+
$unset: AnyKeys<factory.task.ITask<factory.taskName>>;
|
|
35
|
+
}): Promise<import("mongoose").UpdateWriteOpResult>;
|
|
36
|
+
}
|
|
37
|
+
export {};
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AdminTaskRepo = void 0;
|
|
4
|
+
const factory_1 = require("../factory");
|
|
5
|
+
const settings_1 = require("../settings");
|
|
6
|
+
const task_1 = require("./mongoose/schemas/task");
|
|
7
|
+
const AVAILABLE_PROJECT_FIELDS = [
|
|
8
|
+
'alternateName',
|
|
9
|
+
'identifier',
|
|
10
|
+
'description',
|
|
11
|
+
'project',
|
|
12
|
+
'name',
|
|
13
|
+
'status',
|
|
14
|
+
'runsAt',
|
|
15
|
+
'remainingNumberOfTries',
|
|
16
|
+
'lastTriedAt',
|
|
17
|
+
'numberOfTried',
|
|
18
|
+
'executionResults',
|
|
19
|
+
'executor',
|
|
20
|
+
'data',
|
|
21
|
+
'dateAborted',
|
|
22
|
+
'expires'
|
|
23
|
+
];
|
|
24
|
+
/**
|
|
25
|
+
* タスク管理リポジトリ
|
|
26
|
+
*/
|
|
27
|
+
class AdminTaskRepo {
|
|
28
|
+
taskModel;
|
|
29
|
+
constructor(connection) {
|
|
30
|
+
this.taskModel = connection.model(task_1.modelName, (0, task_1.createSchema)());
|
|
31
|
+
}
|
|
32
|
+
static CREATE_MONGO_CONDITIONS(params) {
|
|
33
|
+
const andConditions = [];
|
|
34
|
+
const idEq = params.id?.$eq;
|
|
35
|
+
if (typeof idEq === 'string') {
|
|
36
|
+
andConditions.push({ _id: { $eq: idEq } });
|
|
37
|
+
}
|
|
38
|
+
const projectIdEq = params.project?.id?.$eq;
|
|
39
|
+
if (typeof projectIdEq === 'string') {
|
|
40
|
+
andConditions.push({ 'project.id': { $eq: projectIdEq } });
|
|
41
|
+
}
|
|
42
|
+
if (typeof params.name === 'string') {
|
|
43
|
+
andConditions.push({ name: { $eq: params.name } });
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
const nameIn = params.name?.$in;
|
|
47
|
+
if (Array.isArray(nameIn)) {
|
|
48
|
+
andConditions.push({ name: { $in: nameIn } });
|
|
49
|
+
}
|
|
50
|
+
const nameNin = params.name?.$nin;
|
|
51
|
+
if (Array.isArray(nameNin)) {
|
|
52
|
+
andConditions.push({ name: { $nin: nameNin } });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const statusEq = params.status?.$eq;
|
|
56
|
+
if (typeof statusEq === 'string') {
|
|
57
|
+
andConditions.push({ status: { $eq: statusEq } });
|
|
58
|
+
}
|
|
59
|
+
if (Array.isArray(params.statuses)) {
|
|
60
|
+
andConditions.push({ status: { $in: params.statuses } });
|
|
61
|
+
}
|
|
62
|
+
if (params.runsFrom instanceof Date) {
|
|
63
|
+
andConditions.push({ runsAt: { $gte: params.runsFrom } });
|
|
64
|
+
}
|
|
65
|
+
if (params.runsThrough instanceof Date) {
|
|
66
|
+
andConditions.push({ runsAt: { $lte: params.runsThrough } });
|
|
67
|
+
}
|
|
68
|
+
if (params.lastTriedFrom instanceof Date) {
|
|
69
|
+
andConditions.push({ lastTriedAt: { $type: 'date', $gte: params.lastTriedFrom } });
|
|
70
|
+
}
|
|
71
|
+
if (params.lastTriedThrough instanceof Date) {
|
|
72
|
+
andConditions.push({ lastTriedAt: { $type: 'date', $lte: params.lastTriedThrough } });
|
|
73
|
+
}
|
|
74
|
+
const dateAbortedGte = params.dateAborted?.$gte;
|
|
75
|
+
if (dateAbortedGte instanceof Date) {
|
|
76
|
+
andConditions.push({ dateAborted: { $type: 'date', $gte: dateAbortedGte } });
|
|
77
|
+
}
|
|
78
|
+
const dateAbortedLte = params.dateAborted?.$lte;
|
|
79
|
+
if (dateAbortedLte instanceof Date) {
|
|
80
|
+
andConditions.push({ dateAborted: { $type: 'date', $lte: dateAbortedLte } });
|
|
81
|
+
}
|
|
82
|
+
const objectIdEq = params.data?.object?.id?.$eq;
|
|
83
|
+
if (typeof objectIdEq === 'string') {
|
|
84
|
+
andConditions.push({ 'data.object.id': { $exists: true, $eq: objectIdEq } });
|
|
85
|
+
}
|
|
86
|
+
const objectOrderNumberEq = params.data?.object?.orderNumber?.$eq;
|
|
87
|
+
if (typeof objectOrderNumberEq === 'string') {
|
|
88
|
+
andConditions.push({ 'data.object.orderNumber': { $exists: true, $eq: objectOrderNumberEq } });
|
|
89
|
+
}
|
|
90
|
+
const objectTransactionNumberEq = params.data?.object?.transactionNumber?.$eq;
|
|
91
|
+
if (typeof objectTransactionNumberEq === 'string') {
|
|
92
|
+
andConditions.push({ 'data.object.transactionNumber': { $exists: true, $eq: objectTransactionNumberEq } });
|
|
93
|
+
}
|
|
94
|
+
const objectPurposeIdEq = params.data?.purpose?.id?.$eq;
|
|
95
|
+
if (typeof objectPurposeIdEq === 'string') {
|
|
96
|
+
andConditions.push({ 'data.purpose.id': { $exists: true, $eq: objectPurposeIdEq } });
|
|
97
|
+
}
|
|
98
|
+
const objectPurposeOrderNumberEq = params.data?.purpose?.orderNumber?.$eq;
|
|
99
|
+
if (typeof objectPurposeOrderNumberEq === 'string') {
|
|
100
|
+
andConditions.push({ 'data.purpose.orderNumber': { $exists: true, $eq: objectPurposeOrderNumberEq } });
|
|
101
|
+
}
|
|
102
|
+
const alternateNameRegex = params.alternateName?.$regex;
|
|
103
|
+
if (typeof alternateNameRegex === 'string' && alternateNameRegex.length > 0) {
|
|
104
|
+
andConditions.push({ alternateName: { $exists: true, $regex: new RegExp(alternateNameRegex) } });
|
|
105
|
+
}
|
|
106
|
+
const identifierRegex = params.identifier?.$regex;
|
|
107
|
+
if (typeof identifierRegex === 'string' && identifierRegex.length > 0) {
|
|
108
|
+
andConditions.push({ identifier: { $exists: true, $regex: new RegExp(identifierRegex) } });
|
|
109
|
+
}
|
|
110
|
+
return andConditions;
|
|
111
|
+
}
|
|
112
|
+
async countTasks(params) {
|
|
113
|
+
const { limit } = params;
|
|
114
|
+
const conditions = AdminTaskRepo.CREATE_MONGO_CONDITIONS(params);
|
|
115
|
+
const query = this.taskModel.countDocuments((conditions.length > 0) ? { $and: conditions } : {});
|
|
116
|
+
if (typeof limit === 'number' && limit >= 0) {
|
|
117
|
+
query.limit(limit);
|
|
118
|
+
}
|
|
119
|
+
const count = await query.setOptions({ maxTimeMS: settings_1.MONGO_MAX_TIME_MS })
|
|
120
|
+
.exec();
|
|
121
|
+
return { count };
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* 検索する
|
|
125
|
+
*/
|
|
126
|
+
async findTasks(params, inclusion) {
|
|
127
|
+
const conditions = AdminTaskRepo.CREATE_MONGO_CONDITIONS(params);
|
|
128
|
+
let positiveProjectionFields = AVAILABLE_PROJECT_FIELDS;
|
|
129
|
+
if (Array.isArray(inclusion) && inclusion.length > 0) {
|
|
130
|
+
positiveProjectionFields = inclusion.filter((key) => AVAILABLE_PROJECT_FIELDS.includes(key));
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
// no op
|
|
134
|
+
}
|
|
135
|
+
const projection = {
|
|
136
|
+
_id: 0,
|
|
137
|
+
id: { $toString: '$_id' },
|
|
138
|
+
...Object.fromEntries(positiveProjectionFields.map((key) => ([key, 1])))
|
|
139
|
+
};
|
|
140
|
+
const query = this.taskModel.find((conditions.length > 0) ? { $and: conditions } : {}, projection);
|
|
141
|
+
if (typeof params.limit === 'number' && params.limit > 0) {
|
|
142
|
+
const page = (typeof params.page === 'number' && params.page > 0) ? params.page : 1;
|
|
143
|
+
query.limit(params.limit)
|
|
144
|
+
.skip(params.limit * (page - 1));
|
|
145
|
+
}
|
|
146
|
+
if (params.sort?.runsAt !== undefined) {
|
|
147
|
+
query.sort({ runsAt: params.sort.runsAt });
|
|
148
|
+
}
|
|
149
|
+
return query.setOptions({ maxTimeMS: settings_1.MONGO_MAX_TIME_MS })
|
|
150
|
+
.lean() // lean(2024-09-26~)
|
|
151
|
+
.exec();
|
|
152
|
+
}
|
|
153
|
+
getCursor(conditions, projection) {
|
|
154
|
+
return this.taskModel.find(conditions, projection)
|
|
155
|
+
.sort({ runsAt: factory_1.factory.sortType.Ascending })
|
|
156
|
+
.cursor();
|
|
157
|
+
}
|
|
158
|
+
async unsetUnnecessaryFields(params) {
|
|
159
|
+
return this.taskModel.updateMany(params.filter, { $unset: params.$unset }, { timestamps: false })
|
|
160
|
+
.exec();
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
exports.AdminTaskRepo = AdminTaskRepo;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Connection } from 'mongoose';
|
|
2
|
+
import { factory } from '../factory';
|
|
3
|
+
import { IModel } from './mongoose/schemas/task';
|
|
4
|
+
interface IAggregationByStatus {
|
|
5
|
+
taskCount: number;
|
|
6
|
+
avgLatency: number;
|
|
7
|
+
maxLatency: number;
|
|
8
|
+
minLatency: number;
|
|
9
|
+
percentilesLatency: {
|
|
10
|
+
name: string;
|
|
11
|
+
value: number;
|
|
12
|
+
}[];
|
|
13
|
+
}
|
|
14
|
+
interface IStatus {
|
|
15
|
+
status: factory.taskStatus;
|
|
16
|
+
aggregation: IAggregationByStatus;
|
|
17
|
+
}
|
|
18
|
+
interface IAggregateTask {
|
|
19
|
+
statuses: IStatus[];
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* タスク集計リポジトリ
|
|
23
|
+
*/
|
|
24
|
+
export declare class AggregateTaskRepo {
|
|
25
|
+
readonly taskModel: IModel;
|
|
26
|
+
constructor(connection: Connection);
|
|
27
|
+
aggregateTask(params: {
|
|
28
|
+
project?: {
|
|
29
|
+
id?: {
|
|
30
|
+
$ne?: string;
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
runsFrom: Date;
|
|
34
|
+
runsThrough: Date;
|
|
35
|
+
}): Promise<IAggregateTask>;
|
|
36
|
+
private agggregateByStatus;
|
|
37
|
+
}
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AggregateTaskRepo = void 0;
|
|
4
|
+
const factory_1 = require("../factory");
|
|
5
|
+
const task_1 = require("./mongoose/schemas/task");
|
|
6
|
+
/**
|
|
7
|
+
* タスク集計リポジトリ
|
|
8
|
+
*/
|
|
9
|
+
class AggregateTaskRepo {
|
|
10
|
+
taskModel;
|
|
11
|
+
constructor(connection) {
|
|
12
|
+
this.taskModel = connection.model(task_1.modelName, (0, task_1.createSchema)());
|
|
13
|
+
}
|
|
14
|
+
async aggregateTask(params) {
|
|
15
|
+
const statuses = await Promise.all([
|
|
16
|
+
factory_1.factory.taskStatus.Executed,
|
|
17
|
+
factory_1.factory.taskStatus.Aborted
|
|
18
|
+
].map(async (taskStatus) => {
|
|
19
|
+
const matchConditions = {
|
|
20
|
+
runsAt: {
|
|
21
|
+
$gte: params.runsFrom,
|
|
22
|
+
$lte: params.runsThrough
|
|
23
|
+
},
|
|
24
|
+
status: { $eq: taskStatus },
|
|
25
|
+
...(typeof params.project?.id?.$ne === 'string')
|
|
26
|
+
? { 'project.id': { $ne: params.project.id.$ne } }
|
|
27
|
+
: undefined
|
|
28
|
+
};
|
|
29
|
+
return this.agggregateByStatus({ matchConditions, status: taskStatus });
|
|
30
|
+
}));
|
|
31
|
+
return { statuses };
|
|
32
|
+
}
|
|
33
|
+
async agggregateByStatus(params) {
|
|
34
|
+
const matchConditions = params.matchConditions;
|
|
35
|
+
const taskStatus = params.status;
|
|
36
|
+
const aggregate1 = this.taskModel.aggregate([
|
|
37
|
+
{
|
|
38
|
+
$match: matchConditions
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
$project: {
|
|
42
|
+
latency: { $subtract: ['$lastTriedAt', '$runsAt'] },
|
|
43
|
+
status: '$status',
|
|
44
|
+
runsAt: '$runsAt',
|
|
45
|
+
lastTriedAt: '$lastTriedAt'
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
$group: {
|
|
50
|
+
_id: '$status',
|
|
51
|
+
taskCount: { $sum: 1 },
|
|
52
|
+
maxLatency: { $max: '$latency' },
|
|
53
|
+
minLatency: { $min: '$latency' },
|
|
54
|
+
avgLatency: { $avg: '$latency' }
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
$project: {
|
|
59
|
+
_id: 0,
|
|
60
|
+
taskCount: '$taskCount',
|
|
61
|
+
avgLatency: '$avgLatency',
|
|
62
|
+
maxLatency: '$maxLatency',
|
|
63
|
+
minLatency: '$minLatency'
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
]);
|
|
67
|
+
// const explainResult = await aggregate1.explain();
|
|
68
|
+
// console.dir(explainResult, { depth: null });
|
|
69
|
+
// return;
|
|
70
|
+
const aggregations = await aggregate1.exec();
|
|
71
|
+
const percents = [50, 95, 99];
|
|
72
|
+
if (aggregations.length === 0) {
|
|
73
|
+
return {
|
|
74
|
+
status: taskStatus,
|
|
75
|
+
aggregation: {
|
|
76
|
+
taskCount: 0,
|
|
77
|
+
avgLatency: 0,
|
|
78
|
+
maxLatency: 0,
|
|
79
|
+
minLatency: 0,
|
|
80
|
+
percentilesLatency: percents.map((percent) => {
|
|
81
|
+
return {
|
|
82
|
+
name: String(percent),
|
|
83
|
+
value: 0
|
|
84
|
+
};
|
|
85
|
+
})
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
const ranks4percentile = percents.map((percentile) => {
|
|
90
|
+
return {
|
|
91
|
+
percentile,
|
|
92
|
+
rank: Math.floor(aggregations[0].taskCount * percentile / 100)
|
|
93
|
+
};
|
|
94
|
+
});
|
|
95
|
+
const aggregate2 = this.taskModel.aggregate([
|
|
96
|
+
{
|
|
97
|
+
$match: matchConditions
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
$project: {
|
|
101
|
+
latency: { $subtract: ['$lastTriedAt', '$runsAt'] },
|
|
102
|
+
status: '$status',
|
|
103
|
+
runsAt: '$runsAt',
|
|
104
|
+
lastTriedAt: '$lastTriedAt'
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
{ $sort: { latency: 1 } },
|
|
108
|
+
{
|
|
109
|
+
$group: {
|
|
110
|
+
_id: '$status',
|
|
111
|
+
latencies: { $push: '$latency' }
|
|
112
|
+
}
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
$project: {
|
|
116
|
+
_id: 0,
|
|
117
|
+
percentilesLatency: ranks4percentile.map((rank) => {
|
|
118
|
+
return {
|
|
119
|
+
name: String(rank.percentile),
|
|
120
|
+
value: { $arrayElemAt: ['$latencies', rank.rank] }
|
|
121
|
+
};
|
|
122
|
+
})
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
]);
|
|
126
|
+
const aggregations2 = await aggregate2.exec();
|
|
127
|
+
return {
|
|
128
|
+
status: taskStatus,
|
|
129
|
+
aggregation: {
|
|
130
|
+
...aggregations[0],
|
|
131
|
+
...aggregations2[0]
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
exports.AggregateTaskRepo = AggregateTaskRepo;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Connection } from 'mongoose';
|
|
2
|
+
import { factory } from '../factory';
|
|
3
|
+
import { IModel } from './mongoose/schemas/task';
|
|
4
|
+
type ICreatingTaskKeys = 'data' | 'executionResults' | 'name' | 'numberOfTried' | 'project' | 'remainingNumberOfTries' | 'runsAt' | 'status' | 'identifier' | 'description';
|
|
5
|
+
/**
|
|
6
|
+
* リトライ可能なタスク作成属性
|
|
7
|
+
*/
|
|
8
|
+
type ICreatingTask = Pick<factory.task.importEventCapacitiesFromCOA.IAttributes, ICreatingTaskKeys> | Pick<factory.task.importEventsFromCOA.IAttributes, ICreatingTaskKeys>;
|
|
9
|
+
/**
|
|
10
|
+
* 予定タスクリポジトリ
|
|
11
|
+
*/
|
|
12
|
+
export declare class ScheduledTaskRepo {
|
|
13
|
+
readonly taskModel: IModel;
|
|
14
|
+
constructor(connection: Connection);
|
|
15
|
+
addScheduledTasks(taskAttributes: ICreatingTask[]): Promise<{
|
|
16
|
+
id: string;
|
|
17
|
+
}[]>;
|
|
18
|
+
countPotentiallyRunningScheduledTasks(params: {
|
|
19
|
+
name: {
|
|
20
|
+
$eq: factory.taskName;
|
|
21
|
+
};
|
|
22
|
+
runsAt: {
|
|
23
|
+
$lt: Date;
|
|
24
|
+
};
|
|
25
|
+
limit?: number;
|
|
26
|
+
}): Promise<{
|
|
27
|
+
count: number;
|
|
28
|
+
}>;
|
|
29
|
+
/**
|
|
30
|
+
* 実行日時を一定期間過ぎたReadyタスクについて、Runningスタータスに変更した上で、Runningイベントを発生させる
|
|
31
|
+
*/
|
|
32
|
+
emitRunningScheduledTaskIfExists(params: {
|
|
33
|
+
/**
|
|
34
|
+
* 必ずタスク名指定で実行する
|
|
35
|
+
*/
|
|
36
|
+
name: {
|
|
37
|
+
$eq: factory.taskName;
|
|
38
|
+
};
|
|
39
|
+
runsAt: {
|
|
40
|
+
$lt: Date;
|
|
41
|
+
};
|
|
42
|
+
sort: {
|
|
43
|
+
numberOfTried?: factory.sortType;
|
|
44
|
+
runsAt?: factory.sortType;
|
|
45
|
+
};
|
|
46
|
+
executor: {
|
|
47
|
+
name: string;
|
|
48
|
+
};
|
|
49
|
+
nameFilterBeforeRunsAt: boolean;
|
|
50
|
+
}): Promise<Pick<factory.task.ITask<factory.taskName>, 'id' | 'name'> | null>;
|
|
51
|
+
}
|
|
52
|
+
export {};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ScheduledTaskRepo = 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 ScheduledTaskRepo {
|
|
12
|
+
taskModel;
|
|
13
|
+
constructor(connection) {
|
|
14
|
+
this.taskModel = connection.model(task_2.modelName, (0, task_2.createSchema)());
|
|
15
|
+
}
|
|
16
|
+
async addScheduledTasks(taskAttributes) {
|
|
17
|
+
if (taskAttributes.length > 0) {
|
|
18
|
+
// resolve uniqueness of identifier(2025-03-27~)
|
|
19
|
+
const creatingTasks = taskAttributes.map(({ identifier, ...creatingTask }) => creatingTask); // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
20
|
+
const result = await this.taskModel.insertMany(creatingTasks, { ordered: false, rawResult: true });
|
|
21
|
+
if (result.insertedCount !== taskAttributes.length) {
|
|
22
|
+
throw new factory_1.factory.errors.Internal('all tasks not saved');
|
|
23
|
+
}
|
|
24
|
+
const savedTasks = Object.values(result.insertedIds)
|
|
25
|
+
.map((objectId) => {
|
|
26
|
+
return { id: objectId.toHexString() };
|
|
27
|
+
});
|
|
28
|
+
// イベントは発火しない
|
|
29
|
+
// if (emitImmediately) {
|
|
30
|
+
// savedTasks.forEach((savedTask) => {
|
|
31
|
+
// taskEventEmitter.emitTaskStatusChanged({
|
|
32
|
+
// id: savedTask.id,
|
|
33
|
+
// status: factory.taskStatus.Ready
|
|
34
|
+
// });
|
|
35
|
+
// });
|
|
36
|
+
// }
|
|
37
|
+
return savedTasks;
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async countPotentiallyRunningScheduledTasks(params) {
|
|
44
|
+
const { runsAt, limit, name } = params;
|
|
45
|
+
const nameEq = name.$eq;
|
|
46
|
+
if (!(runsAt.$lt instanceof Date)) {
|
|
47
|
+
throw new factory_1.factory.errors.Argument('runsAt.$lt', 'must be Date');
|
|
48
|
+
}
|
|
49
|
+
const query = this.taskModel.countDocuments({
|
|
50
|
+
status: { $eq: factory_1.factory.taskStatus.Ready },
|
|
51
|
+
runsAt: { $lt: params.runsAt.$lt },
|
|
52
|
+
name: { $eq: nameEq }
|
|
53
|
+
});
|
|
54
|
+
if (typeof limit === 'number' && limit >= 0) {
|
|
55
|
+
query.limit(limit);
|
|
56
|
+
}
|
|
57
|
+
const count = await query.setOptions({ maxTimeMS: settings_1.MONGO_MAX_TIME_MS })
|
|
58
|
+
.exec();
|
|
59
|
+
return { count };
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* 実行日時を一定期間過ぎたReadyタスクについて、Runningスタータスに変更した上で、Runningイベントを発生させる
|
|
63
|
+
*/
|
|
64
|
+
async emitRunningScheduledTaskIfExists(params) {
|
|
65
|
+
if (!(params.runsAt.$lt instanceof Date)) {
|
|
66
|
+
throw new factory_1.factory.errors.Argument('runsAt.$lt', 'must be Date');
|
|
67
|
+
}
|
|
68
|
+
const projection = {
|
|
69
|
+
_id: 0,
|
|
70
|
+
id: { $toString: '$_id' },
|
|
71
|
+
name: 1
|
|
72
|
+
};
|
|
73
|
+
const nameEq = params.name.$eq;
|
|
74
|
+
const { nameFilterBeforeRunsAt } = params;
|
|
75
|
+
const filter = {
|
|
76
|
+
status: { $eq: factory_1.factory.taskStatus.Ready },
|
|
77
|
+
...(nameFilterBeforeRunsAt) ? { name: params.name } : undefined,
|
|
78
|
+
runsAt: { $lt: params.runsAt.$lt },
|
|
79
|
+
...(!nameFilterBeforeRunsAt) ? { name: params.name } : undefined
|
|
80
|
+
};
|
|
81
|
+
const doc = await this.taskModel.findOneAndUpdate(filter, {
|
|
82
|
+
$set: {
|
|
83
|
+
status: factory_1.factory.taskStatus.Running, // 実行中に変更
|
|
84
|
+
lastTriedAt: new Date(),
|
|
85
|
+
executor: params.executor
|
|
86
|
+
},
|
|
87
|
+
$inc: {
|
|
88
|
+
remainingNumberOfTries: -1, // 残りトライ可能回数減らす
|
|
89
|
+
numberOfTried: 1 // トライ回数増やす
|
|
90
|
+
}
|
|
91
|
+
}, {
|
|
92
|
+
new: true,
|
|
93
|
+
projection,
|
|
94
|
+
...(typeof params.sort.numberOfTried === 'number' || typeof params.sort.runsAt === 'number')
|
|
95
|
+
? { sort: params.sort }
|
|
96
|
+
: undefined
|
|
97
|
+
})
|
|
98
|
+
.setOptions({ maxTimeMS: settings_1.MONGO_MAX_TIME_MS })
|
|
99
|
+
.lean()
|
|
100
|
+
.exec();
|
|
101
|
+
if (doc === null) {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
const changedTask = {
|
|
105
|
+
id: doc.id,
|
|
106
|
+
status: factory_1.factory.taskStatus.Running,
|
|
107
|
+
name: nameEq
|
|
108
|
+
};
|
|
109
|
+
task_1.taskEventEmitter.emitTaskStatusChanged(changedTask);
|
|
110
|
+
return doc;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
exports.ScheduledTaskRepo = ScheduledTaskRepo;
|
|
@@ -1,25 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Connection, UpdateWriteOpResult } from 'mongoose';
|
|
2
2
|
import { INextFunction } from '../eventEmitter/task';
|
|
3
3
|
import { factory } from '../factory';
|
|
4
4
|
import { IModel, IDocType } from './mongoose/schemas/task';
|
|
5
5
|
import type { IExecutableTask } from '../taskSettings';
|
|
6
|
-
interface IAggregationByStatus {
|
|
7
|
-
taskCount: number;
|
|
8
|
-
avgLatency: number;
|
|
9
|
-
maxLatency: number;
|
|
10
|
-
minLatency: number;
|
|
11
|
-
percentilesLatency: {
|
|
12
|
-
name: string;
|
|
13
|
-
value: number;
|
|
14
|
-
}[];
|
|
15
|
-
}
|
|
16
|
-
interface IStatus {
|
|
17
|
-
status: factory.taskStatus;
|
|
18
|
-
aggregation: IAggregationByStatus;
|
|
19
|
-
}
|
|
20
|
-
export interface IAggregateTask {
|
|
21
|
-
statuses: IStatus[];
|
|
22
|
-
}
|
|
23
6
|
interface IOptionOnCreate {
|
|
24
7
|
emitImmediately: boolean;
|
|
25
8
|
}
|
|
@@ -36,7 +19,6 @@ type ICreatingTask = Pick<factory.task.IAttributes<factory.taskName>, 'data' | '
|
|
|
36
19
|
export declare class TaskRepo {
|
|
37
20
|
readonly taskModel: IModel;
|
|
38
21
|
constructor(connection: Connection);
|
|
39
|
-
static CREATE_MONGO_CONDITIONS(params: factory.task.ISearchConditions): 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>[];
|
|
40
22
|
runImmediately(params: Pick<factory.task.IAttributes<factory.taskName>, 'data' | 'name' | 'project' | 'remainingNumberOfTries' | 'runsAt'> & {
|
|
41
23
|
alternateName?: never;
|
|
42
24
|
identifier?: never;
|
|
@@ -140,7 +122,7 @@ export declare class TaskRepo {
|
|
|
140
122
|
name: string;
|
|
141
123
|
};
|
|
142
124
|
nameFilterBeforeRunsAt: boolean;
|
|
143
|
-
}
|
|
125
|
+
}): Promise<Pick<factory.task.ITask<factory.taskName>, 'id' | 'name'> | null>;
|
|
144
126
|
/**
|
|
145
127
|
* Readyのままで期限切れのタスクをExpiredに変更する
|
|
146
128
|
*/
|
|
@@ -193,13 +175,6 @@ export declare class TaskRepo {
|
|
|
193
175
|
status: factory.taskStatus.Executed | factory.taskStatus.Running | factory.taskStatus.Aborted;
|
|
194
176
|
executionResult: factory.task.IExecutionResult;
|
|
195
177
|
}, next?: INextFunction): Promise<void>;
|
|
196
|
-
count(params: factory.task.ISearchConditions): Promise<{
|
|
197
|
-
count: number;
|
|
198
|
-
}>;
|
|
199
|
-
/**
|
|
200
|
-
* 検索する
|
|
201
|
-
*/
|
|
202
|
-
projectFields(params: factory.task.ISearchConditions, inclusion: IKeyOfProjection[]): Promise<factory.task.ITask<factory.taskName>[]>;
|
|
203
178
|
/**
|
|
204
179
|
* タスクの状態を参照する
|
|
205
180
|
* 非同期アクション移行が完了したら廃止する(2026-07-29~)
|
|
@@ -222,16 +197,6 @@ export declare class TaskRepo {
|
|
|
222
197
|
id: string;
|
|
223
198
|
};
|
|
224
199
|
}): Promise<void>;
|
|
225
|
-
deleteByName(params: {
|
|
226
|
-
name: factory.taskName;
|
|
227
|
-
status?: {
|
|
228
|
-
$eq?: factory.taskStatus;
|
|
229
|
-
};
|
|
230
|
-
runsAt?: {
|
|
231
|
-
$gte: Date;
|
|
232
|
-
$lte: Date;
|
|
233
|
-
};
|
|
234
|
-
}): Promise<import("mongodb").DeleteResult>;
|
|
235
200
|
/**
|
|
236
201
|
* 不要なタスクを削除する
|
|
237
202
|
*/
|
|
@@ -249,32 +214,5 @@ export declare class TaskRepo {
|
|
|
249
214
|
}): Promise<{
|
|
250
215
|
count: number;
|
|
251
216
|
}>;
|
|
252
|
-
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"> & {
|
|
253
|
-
expires?: Date;
|
|
254
|
-
} & {
|
|
255
|
-
_id: import("mongoose").Types.ObjectId;
|
|
256
|
-
} & {
|
|
257
|
-
__v: number;
|
|
258
|
-
}, import("mongoose").QueryOptions<IDocType>, (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"> & {
|
|
259
|
-
expires?: Date;
|
|
260
|
-
} & {
|
|
261
|
-
_id: import("mongoose").Types.ObjectId;
|
|
262
|
-
} & {
|
|
263
|
-
__v: number;
|
|
264
|
-
}) | null>;
|
|
265
|
-
unsetUnnecessaryFields(params: {
|
|
266
|
-
filter: FilterQuery<factory.task.ITask<factory.taskName>>;
|
|
267
|
-
$unset: AnyKeys<factory.task.ITask<factory.taskName>>;
|
|
268
|
-
}): Promise<UpdateWriteOpResult>;
|
|
269
|
-
aggregateTask(params: {
|
|
270
|
-
project?: {
|
|
271
|
-
id?: {
|
|
272
|
-
$ne?: string;
|
|
273
|
-
};
|
|
274
|
-
};
|
|
275
|
-
runsFrom: Date;
|
|
276
|
-
runsThrough: Date;
|
|
277
|
-
}): Promise<IAggregateTask>;
|
|
278
|
-
private agggregateByStatus;
|
|
279
217
|
}
|
|
280
218
|
export {};
|