From 8ee8ab7d6d62c1eb12da6844ce6e0877aa9c10a1 Mon Sep 17 00:00:00 2001 From: Junyi Date: Wed, 27 Dec 2023 13:55:48 +0800 Subject: [PATCH] refactor(plugin-workflow): refactor apis (#3267) * refactor(plugin-workflow): refactor apis * fix(plugin-workflow-parallel): fix import in test cases * fix(plugin-workflow): fix some module import source * fix(plugin-workflow): move manual table acl to manual plugin * fix(plugin-workflow-manual): fix folder typo --- .../src/client/index.ts | 3 +- .../src/server/AggregateInstruction.ts | 2 +- .../src/server/Plugin.ts | 7 +-- .../plugin-workflow-delay/src/client/index.ts | 3 +- .../src/server/DelayInstruction.ts | 12 ++-- .../src/server/Plugin.ts | 7 +-- .../src/server/Plugin.ts | 7 +-- .../src/client/FormTrigger.tsx | 1 - .../src/client/index.ts | 3 +- .../src/server/FormTrigger.ts | 12 ++-- .../src/server/Plugin.ts | 5 +- .../plugin-workflow-loop/src/client/index.ts | 3 +- .../plugin-workflow-loop/src/server/Plugin.ts | 7 +-- .../src/server/__tests__/instruction.test.ts | 6 +- .../src/server/ManualInstruction.ts | 12 ++-- .../src/server/Plugin.ts | 15 +++-- .../src/server/actions.ts | 2 +- .../{collecions => collections}/jobs.ts | 0 .../{collecions => collections}/users.ts | 0 .../{collecions => collections}/users_jobs.ts | 0 .../src/server/forms/create.ts | 4 +- .../src/server/forms/update.ts | 4 +- .../src/client/index.ts | 3 +- .../src/server/ParallelInstruction.ts | 2 +- .../src/server/Plugin.ts | 7 +-- .../src/server/__tests__/instruction.test.ts | 6 +- .../src/client/RequestInstruction.tsx | 9 ++- .../src/client/index.ts | 3 +- .../src/server/Plugin.ts | 7 +-- .../src/server/RequestInstruction.ts | 2 +- .../src/client/SQLInstruction.tsx | 4 +- .../plugin-workflow-sql/src/client/index.ts | 3 +- .../plugin-workflow-sql/src/server/Plugin.ts | 7 +-- .../src/server/SQLInstruction.ts | 2 +- .../plugin-workflow/src/client/index.tsx | 36 +++++++++--- .../src/client/nodes/calculation.tsx | 4 +- .../src/client/nodes/index.tsx | 16 ++++-- .../src/client/schemas/workflows.ts | 8 --- .../src/client/triggers/collection.tsx | 1 - .../src/client/triggers/index.tsx | 6 +- .../src/client/triggers/schedule/index.tsx | 1 - .../plugin-workflow/src/client/variable.tsx | 41 +++++++------- .../plugin-workflow/src/server/Plugin.ts | 55 ++++++++++++------- .../plugin-workflow/src/server/Processor.ts | 48 +++------------- .../src/server/__tests__/Processor.test.ts | 14 ++--- .../__tests__/instructions/condition.test.ts | 3 +- .../src/server/actions/workflows.ts | 7 +-- .../src/server/collections/workflows.ts | 5 -- .../plugin-workflow/src/server/constants.ts | 10 +--- .../instructions/ConditionInstruction.ts | 6 ++ .../server/instructions/CreateInstruction.ts | 4 +- .../server/instructions/DestroyInstruction.ts | 2 +- .../server/instructions/QueryInstruction.ts | 2 +- .../server/instructions/UpdateInstruction.ts | 2 +- .../src/server/instructions/index.ts | 2 +- .../src/server/triggers/CollectionTrigger.ts | 6 +- .../src/server/triggers/ScheduleTrigger.ts | 28 +++++----- .../src/server/triggers/index.ts | 2 +- .../src/server/types/Execution.ts | 3 - .../src/server/types/Workflow.ts | 1 - 60 files changed, 222 insertions(+), 261 deletions(-) rename packages/plugins/@nocobase/plugin-workflow-manual/src/server/{collecions => collections}/jobs.ts (100%) rename packages/plugins/@nocobase/plugin-workflow-manual/src/server/{collecions => collections}/users.ts (100%) rename packages/plugins/@nocobase/plugin-workflow-manual/src/server/{collecions => collections}/users_jobs.ts (100%) diff --git a/packages/plugins/@nocobase/plugin-workflow-aggregate/src/client/index.ts b/packages/plugins/@nocobase/plugin-workflow-aggregate/src/client/index.ts index b39b536de..eae3ba742 100644 --- a/packages/plugins/@nocobase/plugin-workflow-aggregate/src/client/index.ts +++ b/packages/plugins/@nocobase/plugin-workflow-aggregate/src/client/index.ts @@ -13,7 +13,6 @@ export default class extends Plugin { // You can get and modify the app instance here async load() { const workflow = this.app.pm.get('workflow') as WorkflowPlugin; - const aggregateInstruction = new AggregateInstruction(); - workflow.instructions.register(aggregateInstruction.type, aggregateInstruction); + workflow.registerInstruction('aggregate', AggregateInstruction); } } diff --git a/packages/plugins/@nocobase/plugin-workflow-aggregate/src/server/AggregateInstruction.ts b/packages/plugins/@nocobase/plugin-workflow-aggregate/src/server/AggregateInstruction.ts index 4f3e7f486..50bf8e144 100644 --- a/packages/plugins/@nocobase/plugin-workflow-aggregate/src/server/AggregateInstruction.ts +++ b/packages/plugins/@nocobase/plugin-workflow-aggregate/src/server/AggregateInstruction.ts @@ -28,7 +28,7 @@ export default class extends Instruction { const result = await repo.aggregate({ ...options, method: aggregators[aggregator], - transaction: processor.transaction, + // transaction: processor.transaction, }); return { diff --git a/packages/plugins/@nocobase/plugin-workflow-aggregate/src/server/Plugin.ts b/packages/plugins/@nocobase/plugin-workflow-aggregate/src/server/Plugin.ts index 2cde92f57..e0caad378 100644 --- a/packages/plugins/@nocobase/plugin-workflow-aggregate/src/server/Plugin.ts +++ b/packages/plugins/@nocobase/plugin-workflow-aggregate/src/server/Plugin.ts @@ -4,11 +4,8 @@ import WorkflowPlugin from '@nocobase/plugin-workflow'; import AggregateInstruction from './AggregateInstruction'; export default class extends Plugin { - workflow: WorkflowPlugin; - async load() { - const workflowPlugin = this.app.getPlugin('workflow') as WorkflowPlugin; - this.workflow = workflowPlugin; - workflowPlugin.instructions.register('aggregate', new AggregateInstruction(workflowPlugin)); + const workflowPlugin = this.app.getPlugin(WorkflowPlugin); + workflowPlugin.registerInstruction('aggregate', AggregateInstruction); } } diff --git a/packages/plugins/@nocobase/plugin-workflow-delay/src/client/index.ts b/packages/plugins/@nocobase/plugin-workflow-delay/src/client/index.ts index 98afe99e2..2a705c474 100644 --- a/packages/plugins/@nocobase/plugin-workflow-delay/src/client/index.ts +++ b/packages/plugins/@nocobase/plugin-workflow-delay/src/client/index.ts @@ -13,7 +13,6 @@ export default class extends Plugin { // You can get and modify the app instance here async load() { const workflow = this.app.pm.get('workflow') as WorkflowPlugin; - const delayInstruction = new DelayInstruction(); - workflow.instructions.register(delayInstruction.type, delayInstruction); + workflow.registerInstruction('delay', DelayInstruction); } } diff --git a/packages/plugins/@nocobase/plugin-workflow-delay/src/server/DelayInstruction.ts b/packages/plugins/@nocobase/plugin-workflow-delay/src/server/DelayInstruction.ts index 66d5e68bb..21a748c59 100644 --- a/packages/plugins/@nocobase/plugin-workflow-delay/src/server/DelayInstruction.ts +++ b/packages/plugins/@nocobase/plugin-workflow-delay/src/server/DelayInstruction.ts @@ -16,15 +16,15 @@ interface DelayConfig { export default class extends Instruction { timers: Map = new Map(); - constructor(public plugin: WorkflowPlugin) { - super(plugin); + constructor(public workflow: WorkflowPlugin) { + super(workflow); - plugin.app.on('afterStart', this.load); - plugin.app.on('beforeStop', this.unload); + workflow.app.on('afterStart', this.load); + workflow.app.on('beforeStop', this.unload); } load = async () => { - const { model } = this.plugin.db.getCollection('jobs'); + const { model } = this.workflow.app.db.getCollection('jobs'); const jobs = (await model.findAll({ where: { status: JOB_STATUS.PENDING, @@ -79,7 +79,7 @@ export default class extends Instruction { job.execution = await job.getExecution(); } if (job.execution.status === EXECUTION_STATUS.STARTED) { - this.plugin.resume(job); + this.workflow.resume(job); } if (this.timers.get(job.id)) { this.timers.delete(job.id); diff --git a/packages/plugins/@nocobase/plugin-workflow-delay/src/server/Plugin.ts b/packages/plugins/@nocobase/plugin-workflow-delay/src/server/Plugin.ts index baab4fd11..e4685b6c1 100644 --- a/packages/plugins/@nocobase/plugin-workflow-delay/src/server/Plugin.ts +++ b/packages/plugins/@nocobase/plugin-workflow-delay/src/server/Plugin.ts @@ -4,11 +4,8 @@ import WorkflowPlugin from '@nocobase/plugin-workflow'; import DelayInstruction from './DelayInstruction'; export default class extends Plugin { - workflow: WorkflowPlugin; - async load() { - const workflowPlugin = this.app.getPlugin('workflow') as WorkflowPlugin; - this.workflow = workflowPlugin; - workflowPlugin.instructions.register('delay', new DelayInstruction(workflowPlugin)); + const workflowPlugin = this.app.getPlugin(WorkflowPlugin); + workflowPlugin.registerInstruction('delay', DelayInstruction); } } diff --git a/packages/plugins/@nocobase/plugin-workflow-dynamic-calculation/src/server/Plugin.ts b/packages/plugins/@nocobase/plugin-workflow-dynamic-calculation/src/server/Plugin.ts index fe5e67923..3fd33dcf1 100644 --- a/packages/plugins/@nocobase/plugin-workflow-dynamic-calculation/src/server/Plugin.ts +++ b/packages/plugins/@nocobase/plugin-workflow-dynamic-calculation/src/server/Plugin.ts @@ -5,15 +5,12 @@ import { ExpressionField } from './expression-field'; import { DynamicCalculation } from './DynamicCalculation'; export default class extends Plugin { - workflow: WorkflowPlugin; - async load() { this.db.registerFieldTypes({ expression: ExpressionField, }); - const workflowPlugin = this.app.getPlugin('workflow') as WorkflowPlugin; - this.workflow = workflowPlugin; - workflowPlugin.instructions.register('dynamic-calculation', new DynamicCalculation(workflowPlugin)); + const workflowPlugin = this.app.getPlugin(WorkflowPlugin); + workflowPlugin.registerInstruction('dynamic-calculation', DynamicCalculation); } } diff --git a/packages/plugins/@nocobase/plugin-workflow-form-trigger/src/client/FormTrigger.tsx b/packages/plugins/@nocobase/plugin-workflow-form-trigger/src/client/FormTrigger.tsx index 4840ecfe1..fd1ba08bd 100644 --- a/packages/plugins/@nocobase/plugin-workflow-form-trigger/src/client/FormTrigger.tsx +++ b/packages/plugins/@nocobase/plugin-workflow-form-trigger/src/client/FormTrigger.tsx @@ -6,7 +6,6 @@ import { NAMESPACE, useLang } from '../locale'; export default class extends Trigger { title = `{{t("Form event", { ns: "${NAMESPACE}" })}}`; - type = 'form'; description = `{{t("Event triggers when submitted a workflow bound form action.", { ns: "${NAMESPACE}" })}}`; fieldset = { collection: { diff --git a/packages/plugins/@nocobase/plugin-workflow-form-trigger/src/client/index.ts b/packages/plugins/@nocobase/plugin-workflow-form-trigger/src/client/index.ts index 6bbfcaea0..87681352a 100644 --- a/packages/plugins/@nocobase/plugin-workflow-form-trigger/src/client/index.ts +++ b/packages/plugins/@nocobase/plugin-workflow-form-trigger/src/client/index.ts @@ -13,7 +13,6 @@ export default class extends Plugin { // You can get and modify the app instance here async load() { const workflow = this.app.pm.get('workflow') as WorkflowPlugin; - const formTrigger = new FormTrigger(); - workflow.triggers.register(formTrigger.type, formTrigger); + workflow.registerTrigger('form', FormTrigger); } } diff --git a/packages/plugins/@nocobase/plugin-workflow-form-trigger/src/server/FormTrigger.ts b/packages/plugins/@nocobase/plugin-workflow-form-trigger/src/server/FormTrigger.ts index 16a4329a1..b7e85539c 100644 --- a/packages/plugins/@nocobase/plugin-workflow-form-trigger/src/server/FormTrigger.ts +++ b/packages/plugins/@nocobase/plugin-workflow-form-trigger/src/server/FormTrigger.ts @@ -5,10 +5,10 @@ import { Model, modelAssociationByKey } from '@nocobase/database'; import WorkflowPlugin, { Trigger, WorkflowModel, toJSON } from '@nocobase/plugin-workflow'; export default class extends Trigger { - constructor(plugin: WorkflowPlugin) { - super(plugin); + constructor(workflow: WorkflowPlugin) { + super(workflow); - plugin.app.resourcer.use(this.middleware); + workflow.app.resourcer.use(this.middleware); } async triggerAction(context, next) { @@ -58,7 +58,7 @@ export default class extends Trigger { }; const triggers = triggerWorkflows.split(',').map((trigger) => trigger.split('!')); - const workflowRepo = this.plugin.db.getRepository('workflows'); + const workflowRepo = this.workflow.db.getRepository('workflows'); const workflows = await workflowRepo.find({ filter: { key: triggers.map((trigger) => trigger[0]), @@ -95,11 +95,11 @@ export default class extends Trigger { appends, }); } - this.plugin.trigger(workflow, { data: toJSON(payload), ...userInfo }); + this.workflow.trigger(workflow, { data: toJSON(payload), ...userInfo }); }); } else { const data = trigger[1] ? get(values, trigger[1]) : values; - this.plugin.trigger(workflow, { + this.workflow.trigger(workflow, { data, ...userInfo, }); diff --git a/packages/plugins/@nocobase/plugin-workflow-form-trigger/src/server/Plugin.ts b/packages/plugins/@nocobase/plugin-workflow-form-trigger/src/server/Plugin.ts index 9024c72b4..f84f35e9f 100644 --- a/packages/plugins/@nocobase/plugin-workflow-form-trigger/src/server/Plugin.ts +++ b/packages/plugins/@nocobase/plugin-workflow-form-trigger/src/server/Plugin.ts @@ -4,11 +4,8 @@ import WorkflowPlugin from '@nocobase/plugin-workflow'; import FormTrigger from './FormTrigger'; export default class extends Plugin { - workflow: WorkflowPlugin; - async load() { - const workflowPlugin = this.app.getPlugin('workflow') as WorkflowPlugin; - this.workflow = workflowPlugin; + const workflowPlugin = this.app.getPlugin(WorkflowPlugin); workflowPlugin.triggers.register('form', new FormTrigger(workflowPlugin)); } } diff --git a/packages/plugins/@nocobase/plugin-workflow-loop/src/client/index.ts b/packages/plugins/@nocobase/plugin-workflow-loop/src/client/index.ts index a41d2e614..be1720785 100644 --- a/packages/plugins/@nocobase/plugin-workflow-loop/src/client/index.ts +++ b/packages/plugins/@nocobase/plugin-workflow-loop/src/client/index.ts @@ -13,7 +13,6 @@ export default class extends Plugin { // You can get and modify the app instance here async load() { const workflow = this.app.pm.get('workflow') as WorkflowPlugin; - const loopInstruction = new LoopInstruction(); - workflow.instructions.register(loopInstruction.type, loopInstruction); + workflow.registerInstruction('loop', LoopInstruction); } } diff --git a/packages/plugins/@nocobase/plugin-workflow-loop/src/server/Plugin.ts b/packages/plugins/@nocobase/plugin-workflow-loop/src/server/Plugin.ts index d18d63223..98dfb4a2b 100644 --- a/packages/plugins/@nocobase/plugin-workflow-loop/src/server/Plugin.ts +++ b/packages/plugins/@nocobase/plugin-workflow-loop/src/server/Plugin.ts @@ -4,11 +4,8 @@ import { default as WorkflowPlugin } from '@nocobase/plugin-workflow'; import LoopInstruction from './LoopInstruction'; export default class extends Plugin { - workflow: WorkflowPlugin; - async load() { - const workflowPlugin = this.app.getPlugin('workflow') as WorkflowPlugin; - this.workflow = workflowPlugin; - workflowPlugin.instructions.register('loop', new LoopInstruction(workflowPlugin)); + const workflowPlugin = this.app.getPlugin(WorkflowPlugin); + workflowPlugin.registerInstruction('loop', LoopInstruction); } } diff --git a/packages/plugins/@nocobase/plugin-workflow-loop/src/server/__tests__/instruction.test.ts b/packages/plugins/@nocobase/plugin-workflow-loop/src/server/__tests__/instruction.test.ts index c1c892461..1c4f1002a 100644 --- a/packages/plugins/@nocobase/plugin-workflow-loop/src/server/__tests__/instruction.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-loop/src/server/__tests__/instruction.test.ts @@ -1,6 +1,6 @@ import Database from '@nocobase/database'; import { Application } from '@nocobase/server'; -import { BRANCH_INDEX, EXECUTION_STATUS, JOB_STATUS } from '@nocobase/plugin-workflow'; +import { EXECUTION_STATUS, JOB_STATUS } from '@nocobase/plugin-workflow'; import { getApp, sleep } from '@nocobase/plugin-workflow-test'; import Plugin from '..'; @@ -404,7 +404,7 @@ describe('workflow > instructions > loop', () => { const n2 = await workflow.createNode({ type: 'loop', - branchIndex: BRANCH_INDEX.ON_TRUE, + branchIndex: 1, upstreamId: n1.id, config: { target: 0, @@ -442,7 +442,7 @@ describe('workflow > instructions > loop', () => { const n2 = await workflow.createNode({ type: 'loop', - branchIndex: BRANCH_INDEX.ON_TRUE, + branchIndex: 1, upstreamId: n1.id, config: { target: 2, diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/server/ManualInstruction.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/server/ManualInstruction.ts index 0ab1d5f26..5d74b1869 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/server/ManualInstruction.ts +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/server/ManualInstruction.ts @@ -85,8 +85,8 @@ function getMode(mode) { export default class extends Instruction { formTypes = new Registry(); - constructor(public plugin: WorkflowPlugin) { - super(plugin); + constructor(public workflow: WorkflowPlugin) { + super(workflow); initFormTypes(this); } @@ -103,7 +103,7 @@ export default class extends Instruction { }); // NOTE: batch create users jobs - const UserJobModel = processor.options.plugin.db.getModel('users_jobs'); + const UserJobModel = this.workflow.app.db.getModel('users_jobs'); await UserJobModel.bulkCreate( assignees.map((userId) => ({ userId, @@ -114,7 +114,7 @@ export default class extends Instruction { status: JOB_STATUS.PENDING, })), { - transaction: processor.transaction, + // transaction: processor.transaction, }, ); @@ -125,13 +125,13 @@ export default class extends Instruction { // NOTE: check all users jobs related if all done then continue as parallel const { assignees = [], mode } = node.config as ManualConfig; - const UserJobModel = processor.options.plugin.db.getModel('users_jobs'); + const UserJobModel = this.workflow.app.db.getModel('users_jobs'); const distribution = await UserJobModel.count({ where: { jobId: job.id, }, group: ['status'], - transaction: processor.transaction, + // transaction: processor.transaction, }); const submitted = distribution.reduce( diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/server/Plugin.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/server/Plugin.ts index 0e52c392d..6ddbed5d6 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/server/Plugin.ts +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/server/Plugin.ts @@ -3,16 +3,14 @@ import actions from '@nocobase/actions'; import { HandlerType } from '@nocobase/resourcer'; import WorkflowPlugin, { JOB_STATUS } from '@nocobase/plugin-workflow'; -import jobsCollection from './collecions/jobs'; -import usersCollection from './collecions/users'; -import usersJobsCollection from './collecions/users_jobs'; +import jobsCollection from './collections/jobs'; +import usersCollection from './collections/users'; +import usersJobsCollection from './collections/users_jobs'; import { submit } from './actions'; import ManualInstruction from './ManualInstruction'; export default class extends Plugin { - workflow: WorkflowPlugin; - async load() { this.app.db.collection(usersJobsCollection); this.app.db.extendCollection(usersCollection); @@ -41,8 +39,9 @@ export default class extends Plugin { }, }); - const workflowPlugin = this.app.getPlugin('workflow') as WorkflowPlugin; - this.workflow = workflowPlugin; - workflowPlugin.instructions.register('manual', new ManualInstruction(workflowPlugin)); + this.app.acl.allow('users_jobs', ['list', 'get', 'submit'], 'loggedIn'); + + const workflowPlugin = this.app.getPlugin(WorkflowPlugin); + workflowPlugin.registerInstruction('manual', ManualInstruction); } } diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/server/actions.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/server/actions.ts index c05a8db96..bc06a4f40 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/server/actions.ts +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/server/actions.ts @@ -81,7 +81,7 @@ export async function submit(context: Context, next) { await handler.call(instruction, userJob, forms[formKey], processor); } - await userJob.save({ transaction: processor.transaction }); + await userJob.save(); await processor.exit(); diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/server/collecions/jobs.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/server/collections/jobs.ts similarity index 100% rename from packages/plugins/@nocobase/plugin-workflow-manual/src/server/collecions/jobs.ts rename to packages/plugins/@nocobase/plugin-workflow-manual/src/server/collections/jobs.ts diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/server/collecions/users.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/server/collections/users.ts similarity index 100% rename from packages/plugins/@nocobase/plugin-workflow-manual/src/server/collecions/users.ts rename to packages/plugins/@nocobase/plugin-workflow-manual/src/server/collections/users.ts diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/server/collecions/users_jobs.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/server/collections/users_jobs.ts similarity index 100% rename from packages/plugins/@nocobase/plugin-workflow-manual/src/server/collecions/users_jobs.ts rename to packages/plugins/@nocobase/plugin-workflow-manual/src/server/collections/users_jobs.ts diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/server/forms/create.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/server/forms/create.ts index f0f9d2cee..a8df62961 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/server/forms/create.ts +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/server/forms/create.ts @@ -2,7 +2,7 @@ import { Processor } from '@nocobase/plugin-workflow'; import ManualInstruction from '../ManualInstruction'; export default async function (this: ManualInstruction, instance, { collection }, processor: Processor) { - const repo = this.plugin.db.getRepository(collection); + const repo = this.workflow.db.getRepository(collection); if (!repo) { throw new Error(`collection ${collection} for create data on manual node not found`); } @@ -18,6 +18,6 @@ export default async function (this: ManualInstruction, instance, { collection } context: { executionId: processor.execution.id, }, - transaction: processor.transaction, + // transaction: processor.transaction, }); } diff --git a/packages/plugins/@nocobase/plugin-workflow-manual/src/server/forms/update.ts b/packages/plugins/@nocobase/plugin-workflow-manual/src/server/forms/update.ts index a749c6b3a..62702b83a 100644 --- a/packages/plugins/@nocobase/plugin-workflow-manual/src/server/forms/update.ts +++ b/packages/plugins/@nocobase/plugin-workflow-manual/src/server/forms/update.ts @@ -2,7 +2,7 @@ import { Processor } from '@nocobase/plugin-workflow'; import ManualInstruction from '../ManualInstruction'; export default async function (this: ManualInstruction, instance, { collection, filter = {} }, processor: Processor) { - const repo = this.plugin.db.getRepository(collection); + const repo = this.workflow.db.getRepository(collection); if (!repo) { throw new Error(`collection ${collection} for update data on manual node not found`); } @@ -18,6 +18,6 @@ export default async function (this: ManualInstruction, instance, { collection, context: { executionId: processor.execution.id, }, - transaction: processor.transaction, + // transaction: processor.transaction, }); } diff --git a/packages/plugins/@nocobase/plugin-workflow-parallel/src/client/index.ts b/packages/plugins/@nocobase/plugin-workflow-parallel/src/client/index.ts index e175164d0..930e0c71f 100644 --- a/packages/plugins/@nocobase/plugin-workflow-parallel/src/client/index.ts +++ b/packages/plugins/@nocobase/plugin-workflow-parallel/src/client/index.ts @@ -13,7 +13,6 @@ export default class extends Plugin { // You can get and modify the app instance here async load() { const workflow = this.app.pm.get(WorkflowPlugin); - const parallelInstruction = new ParallelInstruction(); - workflow.instructions.register(parallelInstruction.type, parallelInstruction); + workflow.registerInstruction('parallel', ParallelInstruction); } } diff --git a/packages/plugins/@nocobase/plugin-workflow-parallel/src/server/ParallelInstruction.ts b/packages/plugins/@nocobase/plugin-workflow-parallel/src/server/ParallelInstruction.ts index e60001d00..5f5a69469 100644 --- a/packages/plugins/@nocobase/plugin-workflow-parallel/src/server/ParallelInstruction.ts +++ b/packages/plugins/@nocobase/plugin-workflow-parallel/src/server/ParallelInstruction.ts @@ -110,7 +110,7 @@ export default class extends Instruction { }); if (job.status === JOB_STATUS.PENDING) { - await job.save({ transaction: processor.transaction }); + await job.save(); return processor.exit(); } diff --git a/packages/plugins/@nocobase/plugin-workflow-parallel/src/server/Plugin.ts b/packages/plugins/@nocobase/plugin-workflow-parallel/src/server/Plugin.ts index 9caf5eee2..327020117 100644 --- a/packages/plugins/@nocobase/plugin-workflow-parallel/src/server/Plugin.ts +++ b/packages/plugins/@nocobase/plugin-workflow-parallel/src/server/Plugin.ts @@ -4,11 +4,8 @@ import WorkflowPlugin from '@nocobase/plugin-workflow'; import ParallelInstruction from './ParallelInstruction'; export default class extends Plugin { - workflow: WorkflowPlugin; - async load() { - const workflowPlugin = this.app.getPlugin('workflow') as WorkflowPlugin; - this.workflow = workflowPlugin; - workflowPlugin.instructions.register('parallel', new ParallelInstruction(workflowPlugin)); + const workflowPlugin = this.app.getPlugin(WorkflowPlugin); + workflowPlugin.registerInstruction('parallel', ParallelInstruction); } } diff --git a/packages/plugins/@nocobase/plugin-workflow-parallel/src/server/__tests__/instruction.test.ts b/packages/plugins/@nocobase/plugin-workflow-parallel/src/server/__tests__/instruction.test.ts index 980d30cf2..01de43a8b 100644 --- a/packages/plugins/@nocobase/plugin-workflow-parallel/src/server/__tests__/instruction.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow-parallel/src/server/__tests__/instruction.test.ts @@ -1,6 +1,6 @@ import Database from '@nocobase/database'; import { Application } from '@nocobase/server'; -import { BRANCH_INDEX, EXECUTION_STATUS, JOB_STATUS } from '@nocobase/plugin-workflow'; +import { EXECUTION_STATUS, JOB_STATUS } from '@nocobase/plugin-workflow'; import { getApp, sleep } from '@nocobase/plugin-workflow-test'; import Plugin from '..'; @@ -453,7 +453,7 @@ describe('workflow > instructions > parallel', () => { const n2 = await workflow.createNode({ type: 'parallel', - branchIndex: BRANCH_INDEX.ON_TRUE, + branchIndex: 1, upstreamId: n1.id, }); @@ -521,7 +521,7 @@ describe('workflow > instructions > parallel', () => { const n4 = await workflow.createNode({ type: 'echo', upstreamId: n3.id, - branchIndex: BRANCH_INDEX.ON_TRUE, + branchIndex: 1, }); const n5 = await workflow.createNode({ diff --git a/packages/plugins/@nocobase/plugin-workflow-request/src/client/RequestInstruction.tsx b/packages/plugins/@nocobase/plugin-workflow-request/src/client/RequestInstruction.tsx index bf8c4147c..c687a5644 100644 --- a/packages/plugins/@nocobase/plugin-workflow-request/src/client/RequestInstruction.tsx +++ b/packages/plugins/@nocobase/plugin-workflow-request/src/client/RequestInstruction.tsx @@ -1,8 +1,11 @@ import { ArrayItems } from '@formily/antd-v5'; -import { defaultFieldNames } from '@nocobase/client'; - -import { Instruction, WorkflowVariableInput, WorkflowVariableJSON } from '@nocobase/plugin-workflow/client'; +import { + Instruction, + WorkflowVariableInput, + WorkflowVariableJSON, + defaultFieldNames, +} from '@nocobase/plugin-workflow/client'; import { NAMESPACE } from '../locale'; diff --git a/packages/plugins/@nocobase/plugin-workflow-request/src/client/index.ts b/packages/plugins/@nocobase/plugin-workflow-request/src/client/index.ts index 7d210a23d..6667a5198 100644 --- a/packages/plugins/@nocobase/plugin-workflow-request/src/client/index.ts +++ b/packages/plugins/@nocobase/plugin-workflow-request/src/client/index.ts @@ -13,7 +13,6 @@ export default class extends Plugin { // You can get and modify the app instance here async load() { const workflow = this.app.pm.get('workflow') as WorkflowPlugin; - const requestInstruction = new RequestInstruction(); - workflow.instructions.register(requestInstruction.type, requestInstruction); + workflow.registerInstruction('request', RequestInstruction); } } diff --git a/packages/plugins/@nocobase/plugin-workflow-request/src/server/Plugin.ts b/packages/plugins/@nocobase/plugin-workflow-request/src/server/Plugin.ts index 0b07b555e..2c79ad4e5 100644 --- a/packages/plugins/@nocobase/plugin-workflow-request/src/server/Plugin.ts +++ b/packages/plugins/@nocobase/plugin-workflow-request/src/server/Plugin.ts @@ -4,11 +4,8 @@ import WorkflowPlugin from '@nocobase/plugin-workflow'; import RequestInstruction from './RequestInstruction'; export default class extends Plugin { - workflow: WorkflowPlugin; - async load() { - const workflowPlugin = this.app.getPlugin('workflow') as WorkflowPlugin; - this.workflow = workflowPlugin; - workflowPlugin.instructions.register('request', new RequestInstruction(workflowPlugin)); + const workflowPlugin = this.app.getPlugin(WorkflowPlugin); + workflowPlugin.registerInstruction('request', RequestInstruction); } } diff --git a/packages/plugins/@nocobase/plugin-workflow-request/src/server/RequestInstruction.ts b/packages/plugins/@nocobase/plugin-workflow-request/src/server/RequestInstruction.ts index ce034da76..1db953afb 100644 --- a/packages/plugins/@nocobase/plugin-workflow-request/src/server/RequestInstruction.ts +++ b/packages/plugins/@nocobase/plugin-workflow-request/src/server/RequestInstruction.ts @@ -65,7 +65,7 @@ export default class extends Instruction { }) .finally(() => { processor.logger.info(`request (#${node.id}) response received, status: ${job.get('status')}`); - this.plugin.resume(job); + this.workflow.resume(job); }); processor.logger.info(`request (#${node.id}) sent to "${config.url}", waiting for response...`); diff --git a/packages/plugins/@nocobase/plugin-workflow-sql/src/client/SQLInstruction.tsx b/packages/plugins/@nocobase/plugin-workflow-sql/src/client/SQLInstruction.tsx index a023ba90f..f6af07682 100644 --- a/packages/plugins/@nocobase/plugin-workflow-sql/src/client/SQLInstruction.tsx +++ b/packages/plugins/@nocobase/plugin-workflow-sql/src/client/SQLInstruction.tsx @@ -1,6 +1,6 @@ -import { css, defaultFieldNames } from '@nocobase/client'; +import { css } from '@nocobase/client'; -import { Instruction, WorkflowVariableRawTextArea } from '@nocobase/plugin-workflow/client'; +import { Instruction, WorkflowVariableRawTextArea, defaultFieldNames } from '@nocobase/plugin-workflow/client'; import { NAMESPACE } from '../locale'; diff --git a/packages/plugins/@nocobase/plugin-workflow-sql/src/client/index.ts b/packages/plugins/@nocobase/plugin-workflow-sql/src/client/index.ts index 65833be0f..d8b01547c 100644 --- a/packages/plugins/@nocobase/plugin-workflow-sql/src/client/index.ts +++ b/packages/plugins/@nocobase/plugin-workflow-sql/src/client/index.ts @@ -13,7 +13,6 @@ export default class extends Plugin { // You can get and modify the app instance here async load() { const workflow = this.app.pm.get('workflow') as WorkflowPlugin; - const sqlInstruction = new SQLInstruction(); - workflow.instructions.register(sqlInstruction.type, sqlInstruction); + workflow.registerInstruction('sql', SQLInstruction); } } diff --git a/packages/plugins/@nocobase/plugin-workflow-sql/src/server/Plugin.ts b/packages/plugins/@nocobase/plugin-workflow-sql/src/server/Plugin.ts index c2781901d..6cafd98bb 100644 --- a/packages/plugins/@nocobase/plugin-workflow-sql/src/server/Plugin.ts +++ b/packages/plugins/@nocobase/plugin-workflow-sql/src/server/Plugin.ts @@ -4,11 +4,8 @@ import WorkflowPlugin from '@nocobase/plugin-workflow'; import SQLInstruction from './SQLInstruction'; export default class extends Plugin { - workflow: WorkflowPlugin; - async load() { - const workflowPlugin = this.app.getPlugin('workflow') as WorkflowPlugin; - this.workflow = workflowPlugin; - workflowPlugin.instructions.register('sql', new SQLInstruction(workflowPlugin)); + const workflowPlugin = this.app.getPlugin(WorkflowPlugin); + workflowPlugin.registerInstruction('sql', SQLInstruction); } } diff --git a/packages/plugins/@nocobase/plugin-workflow-sql/src/server/SQLInstruction.ts b/packages/plugins/@nocobase/plugin-workflow-sql/src/server/SQLInstruction.ts index f75a1beaa..8d7b08554 100644 --- a/packages/plugins/@nocobase/plugin-workflow-sql/src/server/SQLInstruction.ts +++ b/packages/plugins/@nocobase/plugin-workflow-sql/src/server/SQLInstruction.ts @@ -11,7 +11,7 @@ export default class extends Instruction { } const result = await sequelize.query(sql, { - transaction: processor.transaction, + // transaction: processor.transaction, // plain: true, // model: db.getCollection(node.config.collection).model }); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/index.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/index.tsx index a03e59b28..4cfc061e0 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/index.tsx +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/index.tsx @@ -45,6 +45,26 @@ export default class extends Plugin { })); }; + registerTrigger(type: string, trigger: Trigger | { new (): Trigger }) { + if (typeof trigger === 'function') { + this.triggers.register(type, new trigger()); + } else if (trigger) { + this.triggers.register(type, trigger); + } else { + throw new TypeError('invalid trigger type to register'); + } + } + + registerInstruction(type: string, instruction: Instruction | { new (): Instruction }) { + if (typeof instruction === 'function') { + this.instructions.register(type, new instruction()); + } else if (instruction instanceof Instruction) { + this.instructions.register(type, instruction); + } else { + throw new TypeError('invalid instruction type to register'); + } + } + async load() { this.addRoutes(); this.addScopes(); @@ -57,15 +77,15 @@ export default class extends Plugin { aclSnippet: 'pm.workflow.workflows', }); - this.triggers.register('collection', new CollectionTrigger()); - this.triggers.register('schedule', new ScheduleTrigger()); + this.registerTrigger('collection', CollectionTrigger); + this.registerTrigger('schedule', ScheduleTrigger); - this.instructions.register('calculation', new CalculationInstruction()); - this.instructions.register('condition', new ConditionInstruction()); - this.instructions.register('query', new QueryInstruction()); - this.instructions.register('create', new CreateInstruction()); - this.instructions.register('update', new UpdateInstruction()); - this.instructions.register('destroy', new DestroyInstruction()); + this.registerInstruction('calculation', CalculationInstruction); + this.registerInstruction('condition', ConditionInstruction); + this.registerInstruction('query', QueryInstruction); + this.registerInstruction('create', CreateInstruction); + this.registerInstruction('update', UpdateInstruction); + this.registerInstruction('destroy', DestroyInstruction); } addScopes() { diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/calculation.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/calculation.tsx index dcf4d9ab1..31494a473 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/calculation.tsx +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/calculation.tsx @@ -1,11 +1,11 @@ -import { SchemaInitializerItemType, defaultFieldNames } from '@nocobase/client'; +import { SchemaInitializerItemType } from '@nocobase/client'; import { Evaluator, evaluators, getOptions } from '@nocobase/evaluators/client'; import { RadioWithTooltip } from '../components/RadioWithTooltip'; import { ValueBlock } from '../components/ValueBlock'; import { renderEngineReference } from '../components/renderEngineReference'; import { NAMESPACE, lang } from '../locale'; -import { BaseTypeSets, WorkflowVariableTextArea } from '../variable'; +import { BaseTypeSets, WorkflowVariableTextArea, defaultFieldNames } from '../variable'; import { Instruction } from '.'; export default class extends Instruction { diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/index.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/index.tsx index 24b026a3c..32f80ec3b 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/index.tsx +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/nodes/index.tsx @@ -30,7 +30,13 @@ import { JobStatusOptionsMap } from '../constants'; import { useGetAriaLabelOfAddButton } from '../hooks/useGetAriaLabelOfAddButton'; import { lang } from '../locale'; import useStyles from '../style'; -import { VariableOption, VariableOptions } from '../variable'; +import { UseVariableOptions, VariableOption } from '../variable'; + +export type NodeAvailableContext = { + workflow: object; + upstream: object; + branchIndex: number; +}; export abstract class Instruction { title: string; @@ -43,10 +49,10 @@ export abstract class Instruction { scope?: { [key: string]: any }; components?: { [key: string]: any }; Component?(props): JSX.Element; - useVariables?(node, options?): VariableOption; - useScopeVariables?(node, options?): VariableOptions; + useVariables?(node, options?: UseVariableOptions): VariableOption; + useScopeVariables?(node, options?): VariableOption[]; useInitializers?(node): SchemaInitializerItemType | null; - isAvailable?(ctx: object): boolean; + isAvailable?(ctx: NodeAvailableContext): boolean; } function useUpdateAction() { @@ -362,7 +368,7 @@ export function NodeDefaultView(props) { className: 'workflow-node-config-button', }, }, - [`${instruction.type}_${data.id}`]: { + [data.id]: { type: 'void', title: (
, options?: UseVariableOptions): VariableOption[]; fieldset: { [key: string]: ISchema }; view?: ISchema; scope?: { [key: string]: any }; diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/triggers/schedule/index.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/triggers/schedule/index.tsx index 8fd6f1618..973640d78 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/triggers/schedule/index.tsx +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/triggers/schedule/index.tsx @@ -9,7 +9,6 @@ import { SCHEDULE_MODE } from './constants'; export default class extends Trigger { title = `{{t("Schedule event", { ns: "${NAMESPACE}" })}}`; - type = 'schedule'; description = `{{t("Event will be scheduled and triggered base on time conditions.", { ns: "${NAMESPACE}" })}}`; fieldset = { config: { diff --git a/packages/plugins/@nocobase/plugin-workflow/src/client/variable.tsx b/packages/plugins/@nocobase/plugin-workflow/src/client/variable.tsx index 680b5621d..151884528 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/client/variable.tsx +++ b/packages/plugins/@nocobase/plugin-workflow/src/client/variable.tsx @@ -11,21 +11,26 @@ export type VariableOption = { key?: string; value?: string; label?: string; - children?: VariableOptions; + children?: VariableOption[] | null; [key: string]: any; }; -export type VariableOptions = VariableOption[] | null; - export type VariableDataType = - | string + | 'boolean' + | 'number' + | 'string' + | 'date' | { - type: string; - options?: { entity?: boolean; collection?: string }; + type: 'reference'; + options: { + collection: string; + multiple?: boolean; + entity?: boolean; + }; } - | ((field: any, appends?: string[]) => boolean); + | ((field: any) => boolean); -export type OptionsOfUseVariableOptions = { +export type UseVariableOptions = { types?: VariableDataType[]; fieldNames?: { label?: string; @@ -34,7 +39,6 @@ export type OptionsOfUseVariableOptions = { }; appends?: string[] | null; depth?: number; - current?: any; }; export const defaultFieldNames = { label: 'label', value: 'value', children: 'children' } as const; @@ -42,7 +46,7 @@ export const defaultFieldNames = { label: 'label', value: 'value', children: 'ch export const nodesOptions = { label: `{{t("Node result", { ns: "${NAMESPACE}" })}}`, value: '$jobsMapByNodeKey', - useOptions(options: OptionsOfUseVariableOptions) { + useOptions(options: UseVariableOptions) { const { instructions } = usePlugin(WorkflowPlugin); const current = useNodeContext(); const upstreams = useAvailableUpstreams(current); @@ -61,7 +65,7 @@ export const nodesOptions = { export const triggerOptions = { label: `{{t("Trigger variables", { ns: "${NAMESPACE}" })}}`, value: '$context', - useOptions(options: OptionsOfUseVariableOptions) { + useOptions(options: UseVariableOptions) { const { triggers } = usePlugin(WorkflowPlugin); const { workflow } = useFlowContext(); const trigger = triggers.get(workflow.type); @@ -72,7 +76,7 @@ export const triggerOptions = { export const scopeOptions = { label: `{{t("Scope variables", { ns: "${NAMESPACE}" })}}`, value: '$scopes', - useOptions(options: OptionsOfUseVariableOptions) { + useOptions(options: UseVariableOptions & { current: any }) { const { fieldNames = defaultFieldNames, current } = options; const { instructions } = usePlugin(WorkflowPlugin); const source = useNodeContext(); @@ -98,7 +102,7 @@ export const scopeOptions = { export const systemOptions = { label: `{{t("System variables", { ns: "${NAMESPACE}" })}}`, value: '$system', - useOptions({ types, fieldNames = defaultFieldNames }: OptionsOfUseVariableOptions) { + useOptions({ types, fieldNames = defaultFieldNames }: UseVariableOptions) { return [ ...(!types || types.includes('date') ? [ @@ -136,13 +140,12 @@ export const BaseTypeSets = { // { type: 'reference', options: { collection: 'attachments', multiple: false } } // { type: 'reference', options: { collection: 'myExpressions', entity: false } } -function matchFieldType(field, type): boolean { - const inputType = typeof type; - if (inputType === 'string') { +function matchFieldType(field, type: VariableDataType): boolean { + if (typeof type === 'string') { return BaseTypeSets[type]?.has(field.interface); } - if (inputType === 'object' && type.type === 'reference') { + if (typeof type === 'object' && type.type === 'reference') { if (isAssociationField(field)) { return ( type.options?.entity && (field.collectionName === type.options?.collection || type.options?.collection === '*') @@ -157,7 +160,7 @@ function matchFieldType(field, type): boolean { } } - if (inputType === 'function') { + if (typeof type === 'function') { return type(field); } @@ -232,7 +235,7 @@ function useOptions(scope, opts) { }; } -export function useWorkflowVariableOptions(options: OptionsOfUseVariableOptions = {}) { +export function useWorkflowVariableOptions(options: UseVariableOptions = {}) { const fieldNames = Object.assign({}, defaultFieldNames, options.fieldNames ?? {}); const opts = Object.assign(options, { fieldNames }); const result = [ diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/Plugin.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/Plugin.ts index 28723b0c2..41cea51cd 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/Plugin.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/Plugin.ts @@ -12,10 +12,10 @@ import Processor from './Processor'; import initActions from './actions'; import { EXECUTION_STATUS } from './constants'; import initFunctions, { CustomFunction } from './functions'; -import type Trigger from './triggers'; +import Trigger from './triggers'; import CollectionTrigger from './triggers/CollectionTrigger'; import ScheduleTrigger from './triggers/ScheduleTrigger'; -import type Instruction from './instructions'; +import Instruction from './instructions'; import CalculationInstruction from './instructions/CalculationInstruction'; import ConditionInstruction from './instructions/ConditionInstruction'; import CreateInstruction from './instructions/CreateInstruction'; @@ -112,29 +112,45 @@ export default class WorkflowPlugin extends Plugin { } }; - initTriggers(more: { [key: string]: T | { new (p: Plugin): T } } = {}) { - const { triggers } = this; - - triggers.register('collection', new CollectionTrigger(this)); - triggers.register('schedule', new ScheduleTrigger(this)); - - for (const [name, trigger] of Object.entries(more)) { - triggers.register(name, typeof trigger === 'function' ? new trigger(this) : trigger); + registerTrigger(type: string, trigger: T | { new (p: Plugin): T }) { + if (typeof trigger === 'function') { + this.triggers.register(type, new trigger(this)); + } else if (trigger) { + this.triggers.register(type, trigger); + } else { + throw new Error('invalid trigger type to register'); } } - initInstructions(more: { [key: string]: T | { new (p: Plugin): T } } = {}) { - const { instructions } = this; + registerInstruction(type: string, instruction: T | { new (p: Plugin): T }) { + if (typeof instruction === 'function') { + this.instructions.register(type, new instruction(this)); + } else if (instruction) { + this.instructions.register(type, instruction); + } else { + throw new Error('invalid instruction type to register'); + } + } - instructions.register('calculation', new CalculationInstruction(this)); - instructions.register('condition', new ConditionInstruction(this)); - instructions.register('create', new CreateInstruction(this)); - instructions.register('destroy', new DestroyInstruction(this)); - instructions.register('query', new QueryInstruction(this)); - instructions.register('update', new UpdateInstruction(this)); + private initTriggers(more: { [key: string]: T | { new (p: Plugin): T } } = {}) { + this.registerTrigger('collection', CollectionTrigger); + this.registerTrigger('schedule', ScheduleTrigger); + + for (const [name, trigger] of Object.entries(more)) { + this.registerTrigger(name, trigger); + } + } + + private initInstructions(more: { [key: string]: T | { new (p: Plugin): T } } = {}) { + this.registerInstruction('calculation', CalculationInstruction); + this.registerInstruction('condition', ConditionInstruction); + this.registerInstruction('create', CreateInstruction); + this.registerInstruction('destroy', DestroyInstruction); + this.registerInstruction('query', QueryInstruction); + this.registerInstruction('update', UpdateInstruction); for (const [name, instruction] of Object.entries({ ...more })) { - instructions.register(name, typeof instruction === 'function' ? new instruction(this) : instruction); + this.registerInstruction(name, instruction); } } @@ -171,7 +187,6 @@ export default class WorkflowPlugin extends Plugin { actions: ['workflows:list'], }); - this.app.acl.allow('users_jobs', ['list', 'get', 'submit'], 'loggedIn'); this.app.acl.allow('workflows', ['trigger'], 'loggedIn'); await db.import({ diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/Processor.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/Processor.ts index d1dccf60c..f8ddb1afa 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/Processor.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/Processor.ts @@ -25,8 +25,6 @@ export default class Processor { logger: Logger; - transaction?: Transaction; - nodes: FlowNodeModel[] = []; nodesMap = new Map(); jobsMap = new Map(); @@ -67,35 +65,18 @@ export default class Processor { }); } - private async getTransaction() { - if (!this.execution.workflow.options?.useTransaction) { - return; - } - - const { options } = this; - - // @ts-ignore - return options.transaction && !options.transaction.finished - ? options.transaction - : await options.plugin.db.sequelize.transaction(); - } - public async prepare() { const { execution } = this; if (!execution.workflow) { execution.workflow = await execution.getWorkflow(); } - const transaction = await this.getTransaction(); - this.transaction = transaction; - const nodes = await execution.workflow.getNodes(); this.makeNodes(nodes); const jobs = await execution.getJobs({ order: [['id', 'ASC']], - transaction, }); this.makeJobs(jobs); @@ -125,13 +106,6 @@ export default class Processor { await this.recall(node, job); } - private async commit() { - // @ts-ignore - if (this.transaction && (!this.options.transaction || this.options.transaction.finished)) { - await this.transaction.commit(); - } - } - private async exec(instruction: Runner, node: FlowNodeModel, prevJob) { let job; try { @@ -224,10 +198,9 @@ export default class Processor { async exit(s?: number) { if (typeof s === 'number') { const status = (this.constructor).StatusMap[s] ?? Math.sign(s); - await this.execution.update({ status }, { transaction: this.transaction }); + await this.execution.update({ status }); } this.logger.info(`execution (${this.execution.id}) exiting with status ${this.execution.status}`); - await this.commit(); return null; } @@ -237,22 +210,15 @@ export default class Processor { const { model } = database.getCollection('jobs'); let job; if (payload instanceof model) { - job = await payload.save({ transaction: this.transaction }); + job = await payload.save(); } else if (payload.id) { job = await model.findByPk(payload.id); - await job.update(payload, { - transaction: this.transaction, - }); + await job.update(payload); } else { - job = await model.create( - { - ...payload, - executionId: this.execution.id, - }, - { - transaction: this.transaction, - }, - ); + job = await model.create({ + ...payload, + executionId: this.execution.id, + }); } this.jobsMap.set(job.id, job); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/Processor.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/Processor.test.ts index d6431d8ab..53a209a31 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/Processor.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/Processor.test.ts @@ -1,11 +1,11 @@ -import Database from '@nocobase/database'; +import { MockDatabase } from '@nocobase/database'; import { MockServer } from '@nocobase/test'; import { getApp, sleep } from '@nocobase/plugin-workflow-test'; -import { BRANCH_INDEX, EXECUTION_STATUS, JOB_STATUS } from '../constants'; +import { EXECUTION_STATUS, JOB_STATUS } from '../constants'; describe('workflow > Processor', () => { let app: MockServer; - let db: Database; + let db: MockDatabase; let PostRepo; let WorkflowModel; let workflow; @@ -251,13 +251,13 @@ describe('workflow > Processor', () => { const n2 = await workflow.createNode({ type: 'echo', - branchIndex: BRANCH_INDEX.ON_TRUE, + branchIndex: 1, upstreamId: n1.id, }); await workflow.createNode({ type: 'echo', - branchIndex: BRANCH_INDEX.ON_FALSE, + branchIndex: 0, upstreamId: n1.id, }); @@ -283,7 +283,7 @@ describe('workflow > Processor', () => { const n2 = await workflow.createNode({ type: 'prompt', - branchIndex: BRANCH_INDEX.ON_TRUE, + branchIndex: 1, upstreamId: n1.id, }); @@ -323,7 +323,7 @@ describe('workflow > Processor', () => { const n2 = await workflow.createNode({ type: 'prompt->error', - branchIndex: BRANCH_INDEX.ON_TRUE, + branchIndex: 1, upstreamId: n1.id, }); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/instructions/condition.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/instructions/condition.test.ts index ba6fc145c..f42ea7695 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/instructions/condition.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/instructions/condition.test.ts @@ -1,7 +1,8 @@ import Database from '@nocobase/database'; import { Application } from '@nocobase/server'; import { getApp, sleep } from '@nocobase/plugin-workflow-test'; -import { BRANCH_INDEX, EXECUTION_STATUS, JOB_STATUS } from '../../constants'; +import { EXECUTION_STATUS, JOB_STATUS } from '../../constants'; +import { BRANCH_INDEX } from '../../instructions/ConditionInstruction'; describe('workflow > instructions > condition', () => { let app: Application; diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/actions/workflows.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/actions/workflows.ts index 64acbd11e..c8a45f831 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/actions/workflows.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/actions/workflows.ts @@ -54,12 +54,11 @@ export async function destroy(context: Context, next) { } export async function revision(context: Context, next) { - const plugin = context.app.getPlugin('workflow') as Plugin; - const { db } = context; + const plugin = context.app.getPlugin(Plugin); const repository = utils.getRepositoryFromParams(context); const { filterByTk, filter = {}, values = {} } = context.action.params; - context.body = await db.sequelize.transaction(async (transaction) => { + context.body = await context.db.sequelize.transaction(async (transaction) => { const origin = await repository.findOne({ filterByTk, filter, @@ -140,7 +139,7 @@ export async function revision(context: Context, next) { } export async function sync(context: Context, next) { - const plugin = context.app.getPlugin('workflow'); + const plugin = context.app.getPlugin(Plugin); const repository = utils.getRepositoryFromParams(context); const { filterByTk, filter = {} } = context.action.params; diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/collections/workflows.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/collections/workflows.ts index 56c02de01..ab743448a 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/collections/workflows.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/collections/workflows.ts @@ -35,11 +35,6 @@ export default function () { required: true, defaultValue: {}, }, - { - type: 'boolean', - name: 'useTransaction', - // defaultValue: true, - }, { type: 'hasMany', name: 'nodes', diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/constants.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/constants.ts index 1d346f3bd..5195bd724 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/constants.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/constants.ts @@ -8,7 +8,7 @@ export const EXECUTION_STATUS = { CANCELED: -4, REJECTED: -5, RETRY_NEEDED: -6, -}; +} as const; export const JOB_STATUS = { PENDING: 0, @@ -19,10 +19,4 @@ export const JOB_STATUS = { CANCELED: -4, REJECTED: -5, RETRY_NEEDED: -6, -}; - -export const BRANCH_INDEX = { - DEFAULT: null, - ON_TRUE: 1, - ON_FALSE: 0, -}; +} as const; diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/instructions/ConditionInstruction.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/instructions/ConditionInstruction.ts index 3ba591c9c..bd59b4e7a 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/instructions/ConditionInstruction.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/instructions/ConditionInstruction.ts @@ -7,6 +7,12 @@ import type { FlowNodeModel, JobModel } from '../types'; type Comparer = (a: any, b: any) => boolean; +export const BRANCH_INDEX = { + DEFAULT: null, + ON_TRUE: 1, + ON_FALSE: 0, +} as const; + export const calculators = new Registry(); // built-in functions diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/instructions/CreateInstruction.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/instructions/CreateInstruction.ts index edc2ca967..70f682bea 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/instructions/CreateInstruction.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/instructions/CreateInstruction.ts @@ -15,7 +15,7 @@ export class CreateInstruction extends Instruction { context: { executionId: processor.execution.id, }, - transaction: processor.transaction, + // transaction: processor.transaction, }); let result = created; @@ -28,7 +28,7 @@ export class CreateInstruction extends Instruction { result = await repository.findOne({ filterByTk: created[model.primaryKeyAttribute], appends: Array.from(includeFields), - transaction: processor.transaction, + // transaction: processor.transaction, }); } diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/instructions/DestroyInstruction.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/instructions/DestroyInstruction.ts index f6e4be160..abdd07ed9 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/instructions/DestroyInstruction.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/instructions/DestroyInstruction.ts @@ -14,7 +14,7 @@ export class DestroyInstruction extends Instruction { context: { executionId: processor.execution.id, }, - transaction: processor.transaction, + // transaction: processor.transaction, }); return { diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/instructions/QueryInstruction.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/instructions/QueryInstruction.ts index 3f13aeaf0..c46699df5 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/instructions/QueryInstruction.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/instructions/QueryInstruction.ts @@ -33,7 +33,7 @@ export class QueryInstruction extends Instruction { .filter((item) => item.field) .map((item) => `${item.direction?.toLowerCase() === 'desc' ? '-' : ''}${item.field}`), appends, - transaction: processor.transaction, + // transaction: processor.transaction, }); if (failOnEmpty && (multiple ? !result.length : !result)) { diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/instructions/UpdateInstruction.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/instructions/UpdateInstruction.ts index e95ef41ee..8aa89b5e5 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/instructions/UpdateInstruction.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/instructions/UpdateInstruction.ts @@ -14,7 +14,7 @@ export class UpdateInstruction extends Instruction { context: { executionId: processor.execution.id, }, - transaction: processor.transaction, + // transaction: processor.transaction, }); return { diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/instructions/index.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/instructions/index.ts index 4985d3682..ffb648f29 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/instructions/index.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/instructions/index.ts @@ -18,7 +18,7 @@ export type Runner = (node: FlowNodeModel, input: any, processor: Processor) => // what should a instruction do? // - base on input and context, do any calculations or system call (io), and produce a result or pending. export abstract class Instruction { - constructor(public plugin: Plugin) {} + constructor(public workflow: Plugin) {} abstract run(node: FlowNodeModel, input: any, processor: Processor): InstructionResult; diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/CollectionTrigger.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/CollectionTrigger.ts index 2ce9a30b8..da7c5cce0 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/CollectionTrigger.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/CollectionTrigger.ts @@ -85,7 +85,7 @@ async function handler(this: CollectionTrigger, workflow: WorkflowModel, data: M // TODO: `result.toJSON()` throws error const json = toJSON(result); - this.plugin.trigger( + this.workflow.trigger( workflow, { data: json }, { @@ -98,7 +98,7 @@ export default class CollectionTrigger extends Trigger { events = new Map(); on(workflow: WorkflowModel) { - const { db } = this.plugin.app; + const { db } = this.workflow.app; const { collection, mode } = workflow.config; const Collection = db.getCollection(collection); if (!Collection) { @@ -125,7 +125,7 @@ export default class CollectionTrigger extends Trigger { } off(workflow: WorkflowModel) { - const { db } = this.plugin.app; + const { db } = this.workflow.app; const { collection, mode } = workflow.config; const Collection = db.getCollection(collection); if (!Collection) { diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/ScheduleTrigger.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/ScheduleTrigger.ts index 3561f6706..3536fbc33 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/ScheduleTrigger.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/ScheduleTrigger.ts @@ -103,7 +103,7 @@ ScheduleModes.set(SCHEDULE_MODE.CONSTANT, { } } - this.plugin.trigger(workflow, { date: now }); + this.workflow.trigger(workflow, { date: now }); return 1; }, @@ -201,7 +201,7 @@ ScheduleModes.set(SCHEDULE_MODE.COLLECTION_FIELD, { this.setCache(workflow); }; this.events.set(name, listener); - this.plugin.app.db.on(event, listener); + this.workflow.app.db.on(event, listener); }, off(workflow) { @@ -211,12 +211,12 @@ ScheduleModes.set(SCHEDULE_MODE.COLLECTION_FIELD, { if (this.events.has(name)) { const listener = this.events.get(name); this.events.delete(name); - this.plugin.app.db.off(event, listener); + this.workflow.app.db.off(event, listener); } }, async shouldCache(workflow, now) { - const { db } = this.plugin.app; + const { db } = this.workflow.app; const { startsOn, endsOn, repeat, collection } = workflow.config; const timestamp = now.getTime(); @@ -305,7 +305,7 @@ ScheduleModes.set(SCHEDULE_MODE.COLLECTION_FIELD, { }, }); - const tsFn = DialectTimestampFnMap[this.plugin.app.db.options.dialect]; + const tsFn = DialectTimestampFnMap[this.workflow.app.db.options.dialect]; if (typeof repeat === 'number' && tsFn) { const modExp = fn( 'MOD', @@ -343,7 +343,7 @@ ScheduleModes.set(SCHEDULE_MODE.COLLECTION_FIELD, { }); } - const repo = this.plugin.app.db.getRepository(collection); + const repo = this.workflow.app.db.getRepository(collection); const instances = await repo.find({ where: { [Op.and]: conditions, @@ -357,7 +357,7 @@ ScheduleModes.set(SCHEDULE_MODE.COLLECTION_FIELD, { }); instances.forEach((item) => { - this.plugin.trigger(workflow, { + this.workflow.trigger(workflow, { date: now, data: item.toJSON(), }); @@ -423,10 +423,10 @@ export default class ScheduleTrigger extends Trigger { // caching workflows in range, default to 1min cacheCycle = 60_000; - constructor(plugin: Plugin) { - super(plugin); + constructor(workflow: Plugin) { + super(workflow); - plugin.app.on('beforeStop', () => { + workflow.app.on('beforeStop', () => { if (this.timer) { clearInterval(this.timer); } @@ -434,7 +434,7 @@ export default class ScheduleTrigger extends Trigger { } init() { - if (this.plugin.app.getPlugin('multi-app-share-collection')?.enabled && this.plugin.app.name !== 'main') { + if (this.workflow.app.getPlugin('multi-app-share-collection')?.enabled && this.workflow.app.name !== 'main') { return; } @@ -474,7 +474,7 @@ export default class ScheduleTrigger extends Trigger { async onTick(now) { // NOTE: trigger workflows in sequence when sqlite due to only one transaction - const isSqlite = this.plugin.app.db.options.dialect === 'sqlite'; + const isSqlite = this.workflow.app.db.options.dialect === 'sqlite'; return Array.from(this.cache.values()).reduce( (prev, workflow) => { if (!this.shouldTrigger(workflow, now)) { @@ -491,7 +491,7 @@ export default class ScheduleTrigger extends Trigger { } async reload() { - const WorkflowRepo = this.plugin.app.db.getRepository('workflows'); + const WorkflowRepo = this.workflow.app.db.getRepository('workflows'); const workflows = await WorkflowRepo.find({ filter: { enabled: true, type: 'schedule' }, }); @@ -510,7 +510,7 @@ export default class ScheduleTrigger extends Trigger { const should = await this.shouldCache(workflow, now); if (should) { - this.plugin.getLogger(workflow.id).info('caching scheduled workflow will run in next minute'); + this.workflow.getLogger(workflow.id).info('caching scheduled workflow will run in next minute'); } this.setCache(workflow, !should); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/index.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/index.ts index 1d7874276..408ceff87 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/index.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/index.ts @@ -3,7 +3,7 @@ import type Plugin from '../Plugin'; import type { WorkflowModel } from '../types'; export abstract class Trigger { - constructor(public readonly plugin: Plugin) {} + constructor(public readonly workflow: Plugin) {} abstract on(workflow: WorkflowModel): void; abstract off(workflow: WorkflowModel): void; duplicateConfig?(workflow: WorkflowModel, options: Transactionable): object | Promise; diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/types/Execution.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/types/Execution.ts index 875be8ceb..52db181e0 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/types/Execution.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/types/Execution.ts @@ -9,9 +9,6 @@ export default class ExecutionModel extends Model { declare title: string; declare context: any; declare status: number; - // NOTE: this duplicated column is for transaction in preparing cycle from workflow - declare useTransaction: boolean; - declare transaction: string; declare createdAt: Date; declare updatedAt: Date; diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/types/Workflow.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/types/Workflow.ts index 0bda86897..68c0f7f3d 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/types/Workflow.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/types/Workflow.ts @@ -19,7 +19,6 @@ export default class WorkflowModel extends Model { declare description?: string; declare type: string; declare config: any; - declare useTransaction: boolean; declare executed: number; declare createdAt: Date;