@chevre/domain
Version:
Chevre Domain Library for Node.js
183 lines (182 loc) • 8.72 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.executeById = executeById;
exports.executeOneIfExists = executeOneIfExists;
exports.execute = execute;
exports.notifyAbortedTasksByEmail = notifyAbortedTasksByEmail;
/**
* タスクサービス
*/
const createDebug = require("debug");
const moment = require("moment");
const factory = require("../factory");
const factory_1 = require("./notification/factory");
const debug = createDebug('chevre-domain:service:task');
/**
* タスク変更イベントを受けて実行する
*/
function executeById(params, next) {
return (settings) => __awaiter(this, void 0, void 0, function* () {
const taskRepo = new (yield Promise.resolve().then(() => require('../repo/task'))).TaskRepo(settings.connection);
const { id, status, executor, expires } = params;
// tslint:disable-next-line:no-null-keyword
let task = null;
try {
// support status: Running(2025-03-05~)
task = yield taskRepo.executeOneById(Object.assign({ id,
status, executor: { name: executor.name } }, (expires instanceof Date) ? { expires } : undefined));
}
catch (error) {
// tslint:disable-next-line:no-single-line-block-comment
/* istanbul ignore next */
debug('service.task.executeById error:', error);
}
// タスクがなければ終了
if (task !== null) {
yield execute(task, (typeof next === 'function') ? next : undefined)(settings, {
executeById: true,
executeByName: false
});
}
});
}
/**
* support no name(2025-03-04~)
*/
function executeOneIfExists(params) {
return (settings) => __awaiter(this, void 0, void 0, function* () {
var _a;
const taskRepo = new (yield Promise.resolve().then(() => require('../repo/task'))).TaskRepo(settings.connection);
// 未実行のタスクを取得
// tslint:disable-next-line:no-null-keyword
let task = null;
try {
task = yield taskRepo.executeOneIfExists(Object.assign({ executor: { name: params.executor.name }, runsAt: { $lt: params.runsAt.$lt } }, (params.name !== undefined) ? { name: params.name } : undefined));
debug('executable task found.', task, params.runsAt.$lt);
}
catch (error) {
// tslint:disable-next-line:no-single-line-block-comment
/* istanbul ignore next */
debug('executeOne error:', error);
}
// タスクがなければ終了
if (task !== null) {
yield execute(task)(settings, {
executeById: false,
executeByName: (typeof ((_a = params.name) === null || _a === void 0 ? void 0 : _a.$eq) === 'string')
});
}
});
}
/**
* タスクを実行する
*/
function execute(task, next) {
const now = new Date();
debug('executing an executableTask...', task, now);
return (settings, options) => __awaiter(this, void 0, void 0, function* () {
const taskRepo = new (yield Promise.resolve().then(() => require('../repo/task'))).TaskRepo(settings.connection);
try {
// 期限検証(2024-04-23~)
if (task.expires instanceof Date) {
const taskExpired = moment(now)
.isAfter(task.expires);
if (taskExpired) {
throw new factory.errors.Internal(`task expired [expires:${task.expires}]`);
}
}
// タスク名の関数が定義されていなければ、TypeErrorとなる
let callResult;
const { call } = yield Promise.resolve(`${`./task/${task.name}`}`).then(s => require(s));
switch (task.name) {
case factory.taskName.AcceptCOAOffer:
case factory.taskName.AggregateOnSystem:
case factory.taskName.AuthorizePayment:
case factory.taskName.CancelPendingReservation:
case factory.taskName.CheckMovieTicket:
case factory.taskName.DeletePerson:
case factory.taskName.HandleNotification:
case factory.taskName.ImportEventCapacitiesFromCOA:
case factory.taskName.ImportEventsFromCOA:
case factory.taskName.ImportOffersFromCOA:
case factory.taskName.InvalidatePaymentUrl:
case factory.taskName.OnAuthorizationCreated:
case factory.taskName.Pay:
case factory.taskName.PublishPaymentUrl:
case factory.taskName.Refund:
case factory.taskName.VoidPayTransaction:
case factory.taskName.VoidReserveTransaction:
case factory.taskName.ConfirmReserveTransaction:
case factory.taskName.ReturnPayTransaction:
case factory.taskName.ReturnReserveTransaction:
case factory.taskName.SendEmailMessage:
case factory.taskName.TriggerWebhook:
callResult = yield call(task)(settings, options);
break;
default:
yield call(task.data)(settings);
}
const result = {
executedAt: now,
endDate: new Date(),
// enable overwriting task.executionResults.error on Executed(2024-05-29~)
error: ((callResult === null || callResult === void 0 ? void 0 : callResult.error) instanceof Error)
? Object.assign(Object.assign({}, callResult.error), { message: callResult.error.message }) : ''
};
yield taskRepo.pushExecutionResultById({
id: task.id,
status: factory.taskStatus.Executed
}, result, (typeof next === 'function') ? next : undefined);
}
catch (error) {
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);
if (typeof error !== 'object') {
error = { message: String(error) };
}
// 実行結果追加
const result = {
executedAt: now,
endDate: new Date(),
error: Object.assign(Object.assign({}, error), { code: error.code, message: error.message, name: error.name, stack: error.stack })
};
// 失敗してもここではステータスを戻さない(Runningのまま待機)
yield taskRepo.pushExecutionResultById({
id: task.id,
status: task.status
}, result, (typeof next === 'function') ? next : undefined);
}
});
}
let notification;
/**
* add(2025-03-13~)
*/
function notifyAbortedTasksByEmail(params) {
return (repos, settings, credentials) => __awaiter(this, void 0, void 0, function* () {
const { abortedTasksWithoutReport } = settings;
const abortedTasks = yield repos.task.projectFields(Object.assign({ status: { $eq: factory.taskStatus.Aborted }, dateAborted: { $gte: params.dateAbortedGte } }, (abortedTasksWithoutReport.length > 0)
? { name: { $nin: abortedTasksWithoutReport } }
: undefined), []);
if (abortedTasks.length > 0) {
if (notification === undefined) {
notification = yield Promise.resolve().then(() => require('./notification'));
}
// 開発者へ報告
const message = (0, factory_1.tasks2lineNotify)({ tasks: abortedTasks });
const notifyResult = yield notification.notifyByEmail({
subject: message.subject, content: message.content,
logLevel: 'error'
})({}, credentials);
debug('notifyResult:', notifyResult);
}
});
}
;