refactor(plugin-workflow): adjust some api (#1067)

This commit is contained in:
Junyi 2022-11-10 13:33:52 +08:00 committed by GitHub
parent 1bd3e93588
commit 8a8478cf4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 46 additions and 39 deletions

View File

@ -612,6 +612,7 @@ export default {
'Control': '流程控制',
'Collection operations': '数据表操作',
'Extended': '扩展类型',
'Node type': '节点类型',

View File

@ -49,6 +49,7 @@ export function AddButton({ upstream, branchIndex = null }: AddButtonProps) {
const groups = [
{ value: 'control', name: '{{t("Control")}}' },
{ value: 'collection', name: '{{t("Collection operations")}}' },
{ value: 'extended', name: '{{t("Extended")}}' },
];
const instructionList = (Array.from(instructions.getValues()) as Instruction[]);
@ -58,21 +59,24 @@ export function AddButton({ upstream, branchIndex = null }: AddButtonProps) {
trigger={['click']}
overlay={
<Menu onClick={ev => onCreate(ev)}>
{groups.map(group => (
<Menu.ItemGroup key={group.value} title={compile(group.name)}>
{instructionList.filter(item => item.group === group.value).map(item => item.options
? (
<Menu.SubMenu key={item.type} title={compile(item.title)}>
{item.options.map(option => (
<Menu.Item key={option.key}>{compile(option.label)}</Menu.Item>
))}
</Menu.SubMenu>
)
: (
<Menu.Item key={item.type}>{compile(item.title)}</Menu.Item>
))}
</Menu.ItemGroup>
))}
{groups.map(group => {
const groupInstructions = instructionList.filter(item => item.group === group.value);
return groupInstructions.length ? (
<Menu.ItemGroup key={group.value} title={compile(group.name)}>
{groupInstructions.map(item => item.options
? (
<Menu.SubMenu key={item.type} title={compile(item.title)}>
{item.options.map(option => (
<Menu.Item key={option.key}>{compile(option.label)}</Menu.Item>
))}
</Menu.SubMenu>
)
: (
<Menu.Item key={item.type}>{compile(item.title)}</Menu.Item>
))}
</Menu.ItemGroup>
) : null;
})}
</Menu>
}
disabled={workflow.executed}

View File

@ -1,4 +1,5 @@
export { triggers } from './triggers';
export * from './nodes';
export { calculators } from './calculators';
export * from './FlowContext';
export { WorkflowProvider as default } from './WorkflowProvider';

View File

@ -13,6 +13,7 @@ import ExecutionModel from './models/Execution';
import WorkflowModel from './models/Workflow';
import Processor from './Processor';
import initTriggers, { Trigger } from './triggers';
import JobModel from './models/Job';
@ -80,7 +81,9 @@ export default class WorkflowPlugin extends Plugin {
db.on('workflows.afterSave', (model: WorkflowModel) => this.toggle(model));
db.on('workflows.afterDestroy', (model: WorkflowModel) => this.toggle(model, false));
this.app.on('afterLoadAll', async () => this.extensions.reduce((promise, extend) => promise.then(() => extend(this)), Promise.resolve()));
this.app.on('afterLoad', async () => {
this.extensions.reduce((promise, extend) => promise.then(() => extend(this)), Promise.resolve());
});
// [Life Cycle]:
// * load all workflows in db
@ -196,6 +199,14 @@ export default class WorkflowPlugin extends Plugin {
return execution;
}
async resume(job) {
if (!job.execution) {
job.execution = await job.getExecution();
}
const processor = this.createProcessor(job.execution);
return processor.resume(job);
}
createProcessor(execution: ExecutionModel, options = {}): Processor {
return new Processor(execution, { ...options, plugin: this });
}

View File

@ -6,6 +6,7 @@ import { EXECUTION_STATUS, JOB_STATUS } from '../../constants';
// NOTE: skipped because time is not stable on github ci, but should work in local
describe.skip('workflow > instructions > prompt', () => {
describe('base', () => {
let app: MockServer;

View File

@ -22,7 +22,6 @@ export async function submit(context: Context, next) {
await next();
const plugin = context.app.pm.get('workflow');
const processor = plugin.createProcessor(instance.execution);
// NOTE: resume the process and no `await` for quick returning
processor.resume(instance);
plugin.resume(instance);
}

View File

@ -1,4 +1,5 @@
export const EXECUTION_STATUS = {
CRETEAD: null,
STARTED: 0,
RESOLVED: 1,
REJECTED: -1,

View File

@ -52,7 +52,6 @@ export async function submit(context: Context, next) {
instance.job.latestUserJob = instance;
const plugin = context.app.pm.get('workflow');
const processor = plugin.createProcessor(instance.execution);
// NOTE: resume the process and no `await` for quick returning
processor.resume(instance.job);
plugin.resume(instance.job);
}

View File

@ -1,6 +1,6 @@
export * from './calculators';
export * from './constants';
export * from './instructions';
export * from './triggers';
export * from './Processor';
export * from './calculators';
// export * from './instructions';
export { Trigger } from './triggers';
export { default as Processor } from './Processor';
export { default } from './Plugin';

View File

@ -15,25 +15,15 @@ export type Job = {
export type InstructionResult = Job | Promise<Job>;
export type Runner = (node: FlowNodeModel, input: any, processor: Processor) => InstructionResult;
// what should a instruction do?
// - base on input and context, do any calculations or system call (io), and produce a result or pending.
export interface Instruction {
run(
node: FlowNodeModel,
// what should input to be?
// - just use previously output result for convenience?
input: any,
// what should context to be?
// - could be the workflow execution object (containing context data)
processor: Processor
): InstructionResult;
run: Runner;
// for start node in main flow (or branch) to resume when manual sub branch triggered
resume?(
node: FlowNodeModel,
input: any,
processor: Processor
): InstructionResult
resume?: Runner
}
type InstructionConstructor<T> = { new(p: Plugin): T };

View File

@ -52,7 +52,7 @@ export default class implements Instruction {
const { actionName, resourceName } = context.action;
if (actionName === 'submit'
&& resourceName === 'jobs'
&& this.middlewares.length
// && this.middlewares.length
) {
return compose([loadJob, ...this.middlewares])(context, next);
}