UNPKG

@nocobase/plugin-workflow

Version:

A powerful BPM tool that provides foundational support for business automation, with the capability to extend unlimited triggers and nodes.

192 lines (190 loc) • 7.54 kB
/** * This file is part of the NocoBase (R) project. * Copyright (c) 2020-2024 NocoBase Co., Ltd. * Authors: NocoBase Team. * * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License. * For more information, please refer to: https://www.nocobase.com/agreement. */ var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var utils_exports = {}; __export(utils_exports, { abortExecution: () => abortExecution, getExecutionLockKey: () => getExecutionLockKey, getExecutionStatusName: () => getExecutionStatusName, getWorkflowExecutionLogMeta: () => getWorkflowExecutionLogMeta, isLockAcquireError: () => isLockAcquireError, toJSON: () => toJSON, validateCollectionField: () => validateCollectionField }); module.exports = __toCommonJS(utils_exports); var import_database = require("@nocobase/database"); var import_data_source_manager = require("@nocobase/data-source-manager"); var import_constants = require("./constants"); function getExecutionLockKey(executionId) { return `workflow:execution:${executionId}`; } function isLockAcquireError(error) { return error instanceof Error && error.constructor.name === "LockAcquireError"; } function afterTransactionCommit(transaction, callback) { if (typeof transaction.afterCommit === "function") { transaction.afterCommit(callback); return; } callback(); } function validateCollectionField(collection, dataSourceManager) { const [dataSourceName, collectionName] = (0, import_data_source_manager.parseCollectionName)(collection); if (!dataSourceName || !collectionName) { return { collection: `"collection" must be in the format "dataSourceName:collectionName"` }; } const dataSource = dataSourceManager.dataSources.get(dataSourceName); if (!dataSource) { return { collection: `Data source "${dataSourceName}" does not exist` }; } if (!dataSource.collectionManager.getCollection(collectionName)) { return { collection: `Collection "${collectionName}" does not exist in data source "${dataSourceName}"` }; } return null; } const EXECUTION_STATUS_NAMES = new Map(Object.entries(import_constants.EXECUTION_STATUS).map(([name, value]) => [value, name])); function getExecutionStatusName(status) { if (typeof status === "undefined") { return "UNKNOWN"; } return EXECUTION_STATUS_NAMES.get(status) ?? `${status}`; } function getWorkflowExecutionLogMeta(workflow, processor) { var _a, _b, _c, _d; const lastSavedJob = processor == null ? void 0 : processor.lastSavedJob; const lastNode = (_a = processor == null ? void 0 : processor.nodesMap) == null ? void 0 : _a.get(lastSavedJob == null ? void 0 : lastSavedJob.nodeId); return { workflowId: workflow.id, workflowKey: workflow.key, workflowTitle: workflow.title, executionId: ((_b = processor == null ? void 0 : processor.execution) == null ? void 0 : _b.id) ?? null, executionStatus: ((_c = processor == null ? void 0 : processor.execution) == null ? void 0 : _c.status) ?? null, executionStatusName: getExecutionStatusName((_d = processor == null ? void 0 : processor.execution) == null ? void 0 : _d.status), lastNodeId: (lastNode == null ? void 0 : lastNode.id) ?? (lastSavedJob == null ? void 0 : lastSavedJob.nodeId) ?? null, lastNodeType: (lastNode == null ? void 0 : lastNode.type) ?? null, lastJobId: (lastSavedJob == null ? void 0 : lastSavedJob.id) ?? null, lastJobStatus: (lastSavedJob == null ? void 0 : lastSavedJob.status) ?? null }; } async function abortExecution(plugin, execution, options = {}) { const logger = plugin.getLogger(execution.workflowId); const transaction = options.transaction ?? void 0; const ExecutionRepo = plugin.db.getRepository("executions"); const JobRepo = plugin.db.getRepository("jobs"); try { if (!transaction) { return plugin.db.sequelize.transaction( (transaction2) => abortExecution(plugin, execution, { ...options, transaction: transaction2 }) ); } const abortValues = { status: import_constants.EXECUTION_STATUS.ABORTED, ...options.reason ? { reason: options.reason } : {} }; const expectedStatus = typeof execution.status === "undefined" ? import_constants.EXECUTION_STATUS.STARTED : execution.status; if (![import_constants.EXECUTION_STATUS.QUEUEING, import_constants.EXECUTION_STATUS.STARTED].includes(expectedStatus)) { return false; } const [affected] = await ExecutionRepo.model.update(abortValues, { where: { id: execution.id, status: expectedStatus }, individualHooks: true, transaction }); if (!affected) { return false; } const updated = await JobRepo.update({ values: { status: import_constants.JOB_STATUS.ABORTED }, filter: { executionId: execution.id, status: import_constants.JOB_STATUS.PENDING }, individualHooks: false, transaction }); const childExecutions = await plugin.db.getRepository("executions").find({ filter: { parentExecutionId: execution.id, status: [import_constants.EXECUTION_STATUS.QUEUEING, import_constants.EXECUTION_STATUS.STARTED] }, transaction }); for (const child of childExecutions) { if (![import_constants.EXECUTION_STATUS.QUEUEING, import_constants.EXECUTION_STATUS.STARTED].includes(child.status)) { continue; } await abortExecution(plugin, child, { transaction, reason: import_constants.EXECUTION_REASON.PARENT_ABORTED }); } const updateLocalState = () => { execution.set("status", import_constants.EXECUTION_STATUS.ABORTED); execution.set("reason", options.reason ?? null); plugin.timeoutManager.clear(execution.id); plugin.abortRunningExecution(execution.id, options.reason); }; afterTransactionCommit(transaction, updateLocalState); logger.info(`execution (${execution.id}) aborted`, { workflowId: execution.workflowId, pendingJobs: Array.isArray(updated) ? updated.length : updated }); return true; } catch (error) { throw error; } } function toJSON(data) { if (Array.isArray(data)) { return data.map(toJSON); } if (!(data instanceof import_database.Model) || !data) { return data; } const result = data.get(); Object.keys(data.constructor.associations).forEach((key) => { if (result[key] != null && typeof result[key] === "object") { result[key] = toJSON(result[key]); } }); return result; } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { abortExecution, getExecutionLockKey, getExecutionStatusName, getWorkflowExecutionLogMeta, isLockAcquireError, toJSON, validateCollectionField });