UNPKG

@chevre/domain

Version:

Chevre Domain Library for Node.js

183 lines (182 loc) 8.72 kB
"use strict"; 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); } }); }