fix(plugin-workflow): fix destroy node bug (#2553)

This commit is contained in:
Junyi 2023-08-28 21:33:53 +07:00 committed by GitHub
parent b23112fd2e
commit 1a82e92ae3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 101 additions and 19 deletions

View File

@ -0,0 +1,84 @@
import { MockServer } from '@nocobase/test';
import Database from '@nocobase/database';
import { getApp, sleep } from '..';
describe('workflow > actions > workflows', () => {
let app: MockServer;
let agent;
let db: Database;
let PostModel;
let PostRepo;
let WorkflowModel;
beforeEach(async () => {
app = await getApp();
agent = app.agent();
db = app.db;
WorkflowModel = db.getCollection('workflows').model;
PostModel = db.getCollection('posts').model;
PostRepo = db.getCollection('posts').repository;
});
afterEach(() => app.destroy());
describe('destroy', () => {
it('node in executed workflow could not be destroyed', async () => {
const workflow = await WorkflowModel.create({
enabled: true,
type: 'collection',
config: {
mode: 1,
collection: 'posts',
},
});
const n1 = await workflow.createNode({
type: 'echo',
});
await PostRepo.create({});
await sleep(500);
const { status } = await agent.resource('flow_nodes').destroy({
filterByTk: n1.id,
});
expect(status).toBe(400);
});
it('cascading destroy all nodes in sub-branches', async () => {
const workflow = await WorkflowModel.create({
enabled: true,
type: 'collection',
config: {
mode: 1,
collection: 'posts',
},
});
const n1 = await workflow.createNode({
type: 'echo',
});
const n2 = await workflow.createNode({
type: 'echo',
branchIndex: 0,
upstreamId: n1.id,
});
const n3 = await workflow.createNode({
type: 'echo',
branchIndex: 0,
upstreamId: n2.id,
});
await agent.resource('flow_nodes').destroy({
filterByTk: n1.id,
});
const nodes = await workflow.getNodes();
expect(nodes.length).toBe(0);
});
});
});

View File

@ -17,10 +17,10 @@ export default function ({ app }) {
...make('workflows', workflows),
...make('workflows.nodes', {
create: nodes.create,
destroy: nodes.destroy,
}),
...make('flow_nodes', {
update: nodes.update,
destroy: nodes.destroy,
}),
...make('executions', executions),
});

View File

@ -1,5 +1,5 @@
import { Context, utils } from '@nocobase/actions';
import { MultipleRelationRepository, Op } from '@nocobase/database';
import { MultipleRelationRepository, Op, Repository } from '@nocobase/database';
import type { WorkflowModel } from '../types';
export async function create(context: Context, next) {
@ -109,22 +109,20 @@ function searchBranchDownstreams(nodes, from) {
export async function destroy(context: Context, next) {
const { db } = context;
const repository = utils.getRepositoryFromParams(context) as MultipleRelationRepository;
const repository = utils.getRepositoryFromParams(context) as Repository;
const { filterByTk } = context.action.params;
context.body = await db.sequelize.transaction(async (transaction) => {
const workflow = (await repository.getSourceModel(transaction)) as WorkflowModel;
if (workflow.executed) {
context.throw(400, 'Nodes in executed workflow could not be deleted');
}
const fields = ['id', 'upstreamId', 'downstreamId', 'branchIndex'];
const instance = await repository.findOne({
filterByTk,
fields: [...fields, 'workflowId'],
appends: ['upstream', 'downstream'],
transaction,
appends: ['upstream', 'downstream', 'workflow'],
});
if (instance.workflow.executed) {
context.throw(400, 'Nodes in executed workflow could not be deleted');
}
await db.sequelize.transaction(async (transaction) => {
const { upstream, downstream } = instance.get();
if (upstream && upstream.downstreamId === instance.id) {
@ -159,7 +157,7 @@ export async function destroy(context: Context, next) {
nodesMap.set(item.id, item);
});
// overwrite
nodesMap.set(instance.id, instance);
// nodesMap.set(instance.id, instance);
// make linked list
nodes.forEach((item) => {
if (item.upstreamId) {
@ -170,16 +168,16 @@ export async function destroy(context: Context, next) {
}
});
const branchNodes = searchBranchNodes(nodes, instance);
const branchNodes = searchBranchNodes(nodes, nodesMap.get(instance.id));
await repository.destroy({
filterByTk: [instance.id, ...branchNodes.map((item) => item.id)],
transaction,
});
return instance;
});
context.body = instance;
await next();
}