feat(plugin-workflow): use toggle instead of mount and unmount

This commit is contained in:
mytharcher 2022-01-28 21:02:32 +08:00
parent e592d03f18
commit f9182c4004
6 changed files with 82 additions and 65 deletions

View File

@ -10,28 +10,22 @@ describe('execution', () => {
let db: Database; let db: Database;
let PostModel; let PostModel;
let WorkflowModel; let WorkflowModel;
let WorkflowRepository;
let workflow; let workflow;
beforeEach(async () => { beforeEach(async () => {
app = await getApp(); app = await getApp();
db = app.db; db = app.db;
WorkflowRepository = db.getCollection('workflows').repository;
WorkflowModel = db.getCollection('workflows').model; WorkflowModel = db.getCollection('workflows').model;
PostModel = db.getCollection('posts').model; PostModel = db.getCollection('posts').model;
// TODO(question): why the hooks of creating workflow won't run by using `WorkflowModel.create()`? workflow = await WorkflowModel.create({
// maybe the model is not the original defined one which hooks have been added. title: 'test workflow',
// @see database/../collections.ts@L99: `this.model = class extends M {};` enabled: true,
workflow = await WorkflowRepository.create({ type: 'model',
values: { config: {
title: 'condition workflow', mode: 1,
enabled: true, collection: 'posts'
type: 'afterCreate',
config: {
collection: 'posts'
}
} }
}); });
}); });

View File

@ -10,25 +10,21 @@ describe('workflow > instructions > condition', () => {
let db: Database; let db: Database;
let PostModel; let PostModel;
let WorkflowModel; let WorkflowModel;
let WorkflowRepository;
let workflow; let workflow;
beforeEach(async () => { beforeEach(async () => {
app = await getApp(); app = await getApp();
db = app.db; db = app.db;
WorkflowRepository = db.getCollection('workflows').repository;
WorkflowModel = db.getCollection('workflows').model; WorkflowModel = db.getCollection('workflows').model;
PostModel = db.getCollection('posts').model; PostModel = db.getCollection('posts').model;
workflow = await WorkflowRepository.create({ workflow = await WorkflowModel.create({
values: { title: 'test workflow',
title: 'condition workflow', enabled: true,
enabled: true, type: 'afterCreate',
type: 'afterCreate', config: {
config: { collection: 'posts'
collection: 'posts'
}
} }
}); });
}); });

View File

@ -34,28 +34,27 @@ export default class WorkflowModel extends Model {
filter: { enabled: true } filter: { enabled: true }
}); });
workflows.forEach(workflow => { workflows.forEach((workflow: WorkflowModel) => {
// @ts-ignore workflow.toggle();
workflow.mount();
}); });
this.addHook('afterCreate', (model: WorkflowModel) => model.mount()); this.addHook('afterCreate', (model: WorkflowModel) => model.toggle());
// TODO: afterUpdate, afterDestroy this.addHook('afterUpdate', (model: WorkflowModel) => model.toggle());
this.addHook('afterDestroy', (model: WorkflowModel) => model.toggle(false));
} }
async mount() { getHookId() {
if (!this.get('enabled')) { return `workflow-${this.get('id')}`;
return; }
}
async toggle(enable?: boolean) {
const type = this.get('type'); const type = this.get('type');
const config = this.get('config'); const { on, off } = getTrigger(type);
const trigger = getTrigger(type); if (typeof enable !== 'undefined' ? enable : this.get('enabled')) {
trigger.call(this, config, this.start.bind(this)); on.call(this, this.start.bind(this));
} } else {
off.call(this);
// TODO }
async unmount() {
} }
async start(context: Object, options) { async start(context: Object, options) {

View File

@ -1,14 +0,0 @@
import WorkflowModel from "../models/Workflow";
export interface IDataChangeTriggerConfig {
collection: string;
// TODO: ICondition
filter: any;
}
export function afterCreate(this: WorkflowModel, config: IDataChangeTriggerConfig, callback: Function) {
// @ts-ignore
const { database } = this.constructor;
const { model } = database.getCollection(config.collection);
model.addHook('afterCreate', `workflow-${this.get('id')}`, (data: any, options) => callback({ data }, options));
}

View File

@ -1,22 +1,20 @@
import WorkflowModel from '../models/Workflow'; import WorkflowModel from '../models/Workflow';
import * as dataChangeTriggers from './data-change'; import modelTrigger from './model';
export interface ITrigger { export interface Trigger {
(this: WorkflowModel, config: any): void name: string;
on(this: WorkflowModel, callback: Function): void;
off(this: WorkflowModel): void;
} }
const triggers = new Map<string, ITrigger>(); const triggers = new Map<string, Trigger>();
export function register(type: string, trigger: ITrigger): void { export function register(type: string, trigger: Trigger): void {
triggers.set(type, trigger); triggers.set(type, trigger);
} }
export function get(type: string): ITrigger | undefined { export function get(type: string): Trigger | undefined {
return triggers.get(type); return triggers.get(type);
} }
for (const key in dataChangeTriggers) { register(modelTrigger.name, modelTrigger);
if (dataChangeTriggers.hasOwnProperty(key)) {
register(key, dataChangeTriggers[key]);
}
}

View File

@ -0,0 +1,44 @@
import WorkflowModel from "../models/Workflow";
export interface ModelChangeTriggerConfig {
collection: string;
// TODO: ICondition
filter: any;
}
const MODE_BITMAP = {
CREATE: 1,
UPDATE: 2,
DESTROY: 4
};
const MODE_BITMAP_EVENTS = new Map();
MODE_BITMAP_EVENTS.set(MODE_BITMAP.CREATE, 'afterCreate');
MODE_BITMAP_EVENTS.set(MODE_BITMAP.UPDATE, 'afterUpdate');
MODE_BITMAP_EVENTS.set(MODE_BITMAP.DESTROY, 'afterDestroy');
export default {
name: 'model',
on(this: WorkflowModel, callback: Function) {
const { database } = <typeof WorkflowModel>this.constructor;
const { collection, mode } = this.config;
const { model } = database.getCollection(collection);
const handler = (data: any, options) => callback({ data }, options);
// TODO: duplication when mode change should be considered
for (let [key, event] of MODE_BITMAP_EVENTS.entries()) {
if (mode & key) {
model.addHook(event, this.getHookId(), handler);
}
}
},
off(this: WorkflowModel) {
const { database } = <typeof WorkflowModel>this.constructor;
const { collection, mode } = this.config;
const { model } = database.getCollection(collection);
for (let [key, event] of MODE_BITMAP_EVENTS.entries()) {
if (mode & key) {
model.removeHook(event, this.getHookId());
}
}
}
}