Merge branch 'next' into develop

This commit is contained in:
nocobase[bot] 2025-02-17 16:17:24 +00:00
commit 160f487ef4
5 changed files with 90 additions and 2 deletions

View File

@ -97,7 +97,12 @@ export default class extends Instruction {
const { result, status } = job;
// NOTE: if loop has been done (resolved / rejected), do not care newly executed branch jobs.
if (status !== JOB_STATUS.PENDING) {
return processor.exit();
processor.logger.warn(`loop (${job.nodeId}) has been done, ignore newly resumed event`);
return null;
}
if (branchJob.id !== job.id && branchJob.status === JOB_STATUS.PENDING) {
return null;
}
const nextIndex = result.looped + 1;

View File

@ -780,6 +780,60 @@ describe('workflow > instructions > loop', () => {
expect(jobs[0].status).toBe(JOB_STATUS.RESOLVED);
expect(jobs[0].result).toEqual({ looped: 2 });
});
it('exit as continue with async node inside', async () => {
const n1 = await workflow.createNode({
type: 'loop',
config: {
target: 2,
exit: EXIT.CONTINUE,
},
});
const n2 = await workflow.createNode({
type: 'pending',
upstreamId: n1.id,
branchIndex: 0,
});
const post = await PostRepo.create({ values: { title: 't1' } });
await sleep(500);
const [e1] = await workflow.getExecutions();
expect(e1.status).toBe(EXECUTION_STATUS.STARTED);
const j1s = await e1.getJobs({ order: [['id', 'ASC']] });
expect(j1s.length).toBe(2);
j1s[1].set('status', JOB_STATUS.RESOLVED);
plugin.resume(j1s[1]);
await sleep(500);
const [e2] = await workflow.getExecutions();
expect(e2.status).toBe(EXECUTION_STATUS.STARTED);
const j2s = await e2.getJobs({ order: [['id', 'ASC']] });
expect(j2s.length).toBe(3);
expect(j2s[0].result).toEqual({ looped: 1 });
expect(j2s[1].status).toBe(JOB_STATUS.RESOLVED);
expect(j2s[2].status).toBe(JOB_STATUS.PENDING);
j2s[2].set('status', JOB_STATUS.RESOLVED);
plugin.resume(j2s[2]);
await sleep(500);
const [e3] = await workflow.getExecutions();
expect(e3.status).toBe(EXECUTION_STATUS.RESOLVED);
const j3s = await e3.getJobs({ order: [['id', 'ASC']] });
expect(j3s.length).toBe(3);
expect(j3s[0].result).toEqual({ looped: 2 });
expect(j3s[1].status).toBe(JOB_STATUS.RESOLVED);
expect(j3s[2].status).toBe(JOB_STATUS.RESOLVED);
});
});
});

View File

@ -46,6 +46,12 @@ export default {
status: 0,
};
},
resume(node, job) {
if (node.config.status != null) {
job.set('status', node.config.status);
}
return job;
},
test() {
return {
status: 0,

View File

@ -234,7 +234,7 @@ export default class Processor {
if (parentNode) {
this.logger.debug(`not on main, recall to parent entry node (${node.id})})`);
await this.recall(parentNode, job);
return job;
return null;
}
// really done for all nodes

View File

@ -41,6 +41,29 @@ describe('workflow > Processor', () => {
afterEach(() => app.destroy());
describe('base', () => {
it.skip('saveJob', async () => {
const execution = await workflow.createExecution({
key: workflow.key,
context: {},
status: EXECUTION_STATUS.STARTED,
eventKey: '123',
});
const processor = plugin.createProcessor(execution);
const job1 = await processor.saveJob({
status: JOB_STATUS.RESOLVED,
result: null,
});
const job2 = await processor.saveJob({
status: JOB_STATUS.RESOLVED,
result: 'abc',
});
expect(job2).toBeDefined();
});
it('empty workflow without any nodes', async () => {
const post = await PostRepo.create({ values: { title: 't1' } });