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

View File

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

View File

@ -34,28 +34,27 @@ export default class WorkflowModel extends Model {
filter: { enabled: true }
});
workflows.forEach(workflow => {
// @ts-ignore
workflow.mount();
workflows.forEach((workflow: WorkflowModel) => {
workflow.toggle();
});
this.addHook('afterCreate', (model: WorkflowModel) => model.mount());
// TODO: afterUpdate, afterDestroy
this.addHook('afterCreate', (model: WorkflowModel) => model.toggle());
this.addHook('afterUpdate', (model: WorkflowModel) => model.toggle());
this.addHook('afterDestroy', (model: WorkflowModel) => model.toggle(false));
}
async mount() {
if (!this.get('enabled')) {
return;
}
getHookId() {
return `workflow-${this.get('id')}`;
}
async toggle(enable?: boolean) {
const type = this.get('type');
const config = this.get('config');
const trigger = getTrigger(type);
trigger.call(this, config, this.start.bind(this));
}
// TODO
async unmount() {
const { on, off } = getTrigger(type);
if (typeof enable !== 'undefined' ? enable : this.get('enabled')) {
on.call(this, this.start.bind(this));
} else {
off.call(this);
}
}
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 * as dataChangeTriggers from './data-change';
import modelTrigger from './model';
export interface ITrigger {
(this: WorkflowModel, config: any): void
export interface Trigger {
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);
}
export function get(type: string): ITrigger | undefined {
export function get(type: string): Trigger | undefined {
return triggers.get(type);
}
for (const key in dataChangeTriggers) {
if (dataChangeTriggers.hasOwnProperty(key)) {
register(key, dataChangeTriggers[key]);
}
}
register(modelTrigger.name, modelTrigger);

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());
}
}
}
}