diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/triggers/schedule/mode-static.test.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/triggers/schedule/mode-static.test.ts index 7f74f8cbd0..8be1efcefa 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/triggers/schedule/mode-static.test.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/__tests__/triggers/schedule/mode-static.test.ts @@ -3,6 +3,8 @@ import { MockServer } from '@nocobase/test'; import Database from '@nocobase/database'; import { getApp, sleep } from '@nocobase/plugin-workflow-test'; +import Plugin from '../../..'; + async function sleepToEvenSecond() { const now = new Date(); // NOTE: align to even(0, 2, ...) + 0.5 seconds to start @@ -23,7 +25,6 @@ describe('workflow > triggers > schedule > static mode', () => { let db: Database; let PostRepo; let CategoryRepo; - let WorkflowModel; let WorkflowRepo; beforeEach(async () => { @@ -31,7 +32,6 @@ describe('workflow > triggers > schedule > static mode', () => { db = app.db; const workflow = db.getCollection('workflows'); - WorkflowModel = workflow.model; WorkflowRepo = workflow.repository; PostRepo = db.getCollection('posts').repository; CategoryRepo = db.getCollection('categories').repository; @@ -41,11 +41,13 @@ describe('workflow > triggers > schedule > static mode', () => { describe('configuration', () => { it('neither startsOn nor repeat configurated', async () => { - const workflow = await WorkflowModel.create({ - enabled: true, - type: 'schedule', - config: { - mode: 0, + const workflow = await WorkflowRepo.create({ + values: { + enabled: true, + type: 'schedule', + config: { + mode: 0, + }, }, }); @@ -62,12 +64,14 @@ describe('workflow > triggers > schedule > static mode', () => { start.setMilliseconds(0); start.setSeconds(start.getSeconds() + 2); - const workflow = await WorkflowModel.create({ - enabled: true, - type: 'schedule', - config: { - mode: 0, - startsOn: start.toISOString(), + const workflow = await WorkflowRepo.create({ + values: { + enabled: true, + type: 'schedule', + config: { + mode: 0, + startsOn: start.toISOString(), + }, }, }); @@ -80,13 +84,15 @@ describe('workflow > triggers > schedule > static mode', () => { it('on every 2 seconds', async () => { const start = await sleepToEvenSecond(); - const workflow = await WorkflowModel.create({ - enabled: true, - type: 'schedule', - config: { - mode: 0, - startsOn: start.toISOString(), - repeat: '*/2 * * * * *', + const workflow = await WorkflowRepo.create({ + values: { + enabled: true, + type: 'schedule', + config: { + mode: 0, + startsOn: start.toISOString(), + repeat: '*/2 * * * * *', + }, }, }); @@ -101,14 +107,16 @@ describe('workflow > triggers > schedule > static mode', () => { it('on every even seconds and limit 1', async () => { const start = await sleepToEvenSecond(); - const workflow = await WorkflowModel.create({ - enabled: true, - type: 'schedule', - config: { - mode: 0, - startsOn: start.toISOString(), - repeat: '*/2 * * * * *', - limit: 1, + const workflow = await WorkflowRepo.create({ + values: { + enabled: true, + type: 'schedule', + config: { + mode: 0, + startsOn: start.toISOString(), + repeat: '*/2 * * * * *', + limit: 1, + }, }, }); @@ -123,14 +131,16 @@ describe('workflow > triggers > schedule > static mode', () => { const start = new Date(); start.setMilliseconds(0); - const workflow = await WorkflowModel.create({ - enabled: true, - type: 'schedule', - config: { - mode: 0, - startsOn: start.toISOString(), - repeat: 2000, - limit: 1, + const workflow = await WorkflowRepo.create({ + values: { + enabled: true, + type: 'schedule', + config: { + mode: 0, + startsOn: start.toISOString(), + repeat: 2000, + limit: 1, + }, }, }); @@ -149,13 +159,15 @@ describe('workflow > triggers > schedule > static mode', () => { await sleep(1500); - const workflow = await WorkflowModel.create({ - enabled: true, - type: 'schedule', - config: { - mode: 0, - startsOn, - repeat: `${now.getSeconds()} * * * * *`, + const workflow = await WorkflowRepo.create({ + values: { + enabled: true, + type: 'schedule', + config: { + mode: 0, + startsOn, + repeat: `${now.getSeconds()} * * * * *`, + }, }, }); @@ -170,12 +182,14 @@ describe('workflow > triggers > schedule > static mode', () => { it('no repeat triggered then update to repeat', async () => { const start = await sleepToEvenSecond(); - const workflow = await WorkflowModel.create({ - enabled: true, - type: 'schedule', - config: { - mode: 0, - startsOn: start.toISOString(), + const workflow = await WorkflowRepo.create({ + values: { + enabled: true, + type: 'schedule', + config: { + mode: 0, + startsOn: start.toISOString(), + }, }, }); @@ -207,13 +221,15 @@ describe('workflow > triggers > schedule > static mode', () => { const future = new Date(); future.setSeconds(future.getSeconds() + 2); - const workflow = await WorkflowModel.create({ - enabled: true, - type: 'schedule', - config: { - mode: 0, - startsOn: future.toISOString(), - repeat: 1000, + const workflow = await WorkflowRepo.create({ + values: { + enabled: true, + type: 'schedule', + config: { + mode: 0, + startsOn: future.toISOString(), + repeat: 1000, + }, }, }); @@ -265,7 +281,10 @@ describe('workflow > triggers > schedule > static mode', () => { }); await sleep(3000); - await WorkflowModel.update({ enabled: false }, { where: { enabled: true } }); + await WorkflowRepo.update({ + values: { enabled: false }, + filter: { enabled: true }, + }); const [e1] = await w1.getExecutions(); expect(e1).toBeDefined(); @@ -287,12 +306,14 @@ describe('workflow > triggers > schedule > static mode', () => { start.setMilliseconds(0); start.setSeconds(start.getSeconds() + 2); - const workflow = await WorkflowModel.create({ - enabled: true, - type: 'schedule', - config: { - mode: 0, - startsOn: start.toISOString(), + const workflow = await WorkflowRepo.create({ + values: { + enabled: true, + type: 'schedule', + config: { + mode: 0, + startsOn: start.toISOString(), + }, }, }); @@ -315,12 +336,14 @@ describe('workflow > triggers > schedule > static mode', () => { start.setMilliseconds(0); start.setSeconds(start.getSeconds() + 2); - const workflow = await WorkflowModel.create({ - enabled: true, - type: 'schedule', - config: { - mode: 0, - startsOn: start.toISOString(), + const workflow = await WorkflowRepo.create({ + values: { + enabled: true, + type: 'schedule', + config: { + mode: 0, + startsOn: start.toISOString(), + }, }, }); @@ -337,4 +360,32 @@ describe('workflow > triggers > schedule > static mode', () => { expect(c2).toBe(1); }); }); + + describe('duplications', () => { + it('same workflow should not be triggered in same time more than once', async () => { + await sleepToEvenSecond(); + + const start = new Date(); + start.setMilliseconds(0); + start.setSeconds(start.getSeconds() + 2); + + const workflow = await WorkflowRepo.create({ + values: { + enabled: true, + type: 'schedule', + config: { + mode: 0, + startsOn: start.toISOString(), + }, + }, + }); + + (app.pm.get('workflow') as Plugin).trigger(workflow, { date: start }); + + await sleep(3000); + + const e1s = await workflow.getExecutions(); + expect(e1s.length).toBe(1); + }); + }); }); diff --git a/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/ScheduleTrigger/index.ts b/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/ScheduleTrigger/index.ts index 8a23d7b4fa..7f11b42ab1 100644 --- a/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/ScheduleTrigger/index.ts +++ b/packages/plugins/@nocobase/plugin-workflow/src/server/triggers/ScheduleTrigger/index.ts @@ -44,7 +44,7 @@ export default class ScheduleTrigger extends Trigger { } const existed = await workflow.countExecutions({ where: { - 'context.date': context.date, + 'context.date': context.date instanceof Date ? context.date.toISOString() : context.date, }, transaction: options.transaction, });