@nocobase/plugin-workflow 0.7.0-alpha.34 → 0.7.0-alpha.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/actions/index.js +31 -32
- package/lib/actions/nodes.js +310 -182
- package/lib/actions/workflows.js +260 -157
- package/lib/calculators/index.js +142 -90
- package/lib/collections/executions.js +40 -43
- package/lib/collections/flow_nodes.js +60 -65
- package/lib/collections/jobs.js +45 -47
- package/lib/collections/workflows.js +78 -87
- package/lib/constants.js +22 -17
- package/lib/index.js +71 -22
- package/lib/instructions/calculation.js +34 -29
- package/lib/instructions/condition.js +94 -87
- package/lib/instructions/create.js +43 -26
- package/lib/instructions/destroy.js +42 -25
- package/lib/instructions/index.js +46 -25
- package/lib/instructions/parallel.js +99 -84
- package/lib/instructions/prompt.js +21 -13
- package/lib/instructions/query.js +47 -29
- package/lib/instructions/update.js +44 -25
- package/lib/models/Execution.js +401 -248
- package/lib/models/FlowNode.js +18 -5
- package/lib/models/Job.js +18 -5
- package/lib/models/Workflow.js +132 -88
- package/lib/server.js +93 -66
- package/lib/triggers/collection.js +113 -51
- package/lib/triggers/index.js +25 -11
- package/package.json +7 -12
- package/esm/actions/index.d.ts +0 -1
- package/esm/actions/index.js +0 -14
- package/esm/actions/index.js.map +0 -1
- package/esm/actions/nodes.d.ts +0 -4
- package/esm/actions/nodes.js +0 -187
- package/esm/actions/nodes.js.map +0 -1
- package/esm/actions/workflows.d.ts +0 -3
- package/esm/actions/workflows.js +0 -163
- package/esm/actions/workflows.js.map +0 -1
- package/esm/calculators/index.d.ts +0 -38
- package/esm/calculators/index.js +0 -128
- package/esm/calculators/index.js.map +0 -1
- package/esm/collections/executions.d.ts +0 -3
- package/esm/collections/executions.js +0 -43
- package/esm/collections/executions.js.map +0 -1
- package/esm/collections/flow_nodes.d.ts +0 -3
- package/esm/collections/flow_nodes.js +0 -65
- package/esm/collections/flow_nodes.js.map +0 -1
- package/esm/collections/jobs.d.ts +0 -3
- package/esm/collections/jobs.js +0 -47
- package/esm/collections/jobs.js.map +0 -1
- package/esm/collections/workflows.d.ts +0 -3
- package/esm/collections/workflows.js +0 -87
- package/esm/collections/workflows.js.map +0 -1
- package/esm/constants.d.ts +0 -17
- package/esm/constants.js +0 -18
- package/esm/constants.js.map +0 -1
- package/esm/index.d.ts +0 -5
- package/esm/index.js +0 -6
- package/esm/index.js.map +0 -1
- package/esm/instructions/calculation.d.ts +0 -8
- package/esm/instructions/calculation.js +0 -55
- package/esm/instructions/calculation.js.map +0 -1
- package/esm/instructions/condition.d.ts +0 -5
- package/esm/instructions/condition.js +0 -99
- package/esm/instructions/condition.js.map +0 -1
- package/esm/instructions/create.d.ts +0 -8
- package/esm/instructions/create.js +0 -26
- package/esm/instructions/create.js.map +0 -1
- package/esm/instructions/destroy.d.ts +0 -8
- package/esm/instructions/destroy.js +0 -25
- package/esm/instructions/destroy.js.map +0 -1
- package/esm/instructions/index.d.ts +0 -15
- package/esm/instructions/index.js +0 -20
- package/esm/instructions/index.js.map +0 -1
- package/esm/instructions/parallel.d.ts +0 -13
- package/esm/instructions/parallel.js +0 -88
- package/esm/instructions/parallel.js.map +0 -1
- package/esm/instructions/prompt.d.ts +0 -7
- package/esm/instructions/prompt.js +0 -13
- package/esm/instructions/prompt.js.map +0 -1
- package/esm/instructions/query.d.ts +0 -8
- package/esm/instructions/query.js +0 -29
- package/esm/instructions/query.js.map +0 -1
- package/esm/instructions/update.d.ts +0 -9
- package/esm/instructions/update.js +0 -25
- package/esm/instructions/update.js.map +0 -1
- package/esm/models/Execution.d.ts +0 -51
- package/esm/models/Execution.js +0 -256
- package/esm/models/Execution.js.map +0 -1
- package/esm/models/FlowNode.d.ts +0 -17
- package/esm/models/FlowNode.js +0 -4
- package/esm/models/FlowNode.js.map +0 -1
- package/esm/models/Job.d.ts +0 -15
- package/esm/models/Job.js +0 -4
- package/esm/models/Job.js.map +0 -1
- package/esm/models/Workflow.d.ts +0 -29
- package/esm/models/Workflow.js +0 -88
- package/esm/models/Workflow.js.map +0 -1
- package/esm/server.d.ts +0 -5
- package/esm/server.js +0 -62
- package/esm/server.js.map +0 -1
- package/esm/triggers/collection.d.ts +0 -12
- package/esm/triggers/collection.js +0 -61
- package/esm/triggers/collection.js.map +0 -1
- package/esm/triggers/index.d.ts +0 -9
- package/esm/triggers/index.js +0 -6
- package/esm/triggers/index.js.map +0 -1
- package/lib/actions/index.js.map +0 -1
- package/lib/actions/nodes.js.map +0 -1
- package/lib/actions/workflows.js.map +0 -1
- package/lib/calculators/index.js.map +0 -1
- package/lib/collections/executions.js.map +0 -1
- package/lib/collections/flow_nodes.js.map +0 -1
- package/lib/collections/jobs.js.map +0 -1
- package/lib/collections/workflows.js.map +0 -1
- package/lib/constants.js.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/instructions/calculation.js.map +0 -1
- package/lib/instructions/condition.js.map +0 -1
- package/lib/instructions/create.js.map +0 -1
- package/lib/instructions/destroy.js.map +0 -1
- package/lib/instructions/index.js.map +0 -1
- package/lib/instructions/parallel.js.map +0 -1
- package/lib/instructions/prompt.js.map +0 -1
- package/lib/instructions/query.js.map +0 -1
- package/lib/instructions/update.js.map +0 -1
- package/lib/models/Execution.js.map +0 -1
- package/lib/models/FlowNode.js.map +0 -1
- package/lib/models/Job.js.map +0 -1
- package/lib/models/Workflow.js.map +0 -1
- package/lib/server.js.map +0 -1
- package/lib/triggers/collection.js.map +0 -1
- package/lib/triggers/index.js.map +0 -1
- package/tsconfig.build.json +0 -9
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { Registry } from '@nocobase/utils';
|
|
2
|
-
import ExecutionModel from '../models/Execution';
|
|
3
|
-
import FlowNodeModel from '../models/FlowNode';
|
|
4
|
-
export interface Job {
|
|
5
|
-
status: number;
|
|
6
|
-
result?: unknown;
|
|
7
|
-
[key: string]: unknown;
|
|
8
|
-
}
|
|
9
|
-
export declare type InstructionResult = Job | Promise<Job>;
|
|
10
|
-
export interface Instruction {
|
|
11
|
-
run(this: FlowNodeModel, input: any, execution: ExecutionModel): InstructionResult;
|
|
12
|
-
resume?(this: FlowNodeModel, input: any, execution: ExecutionModel): InstructionResult;
|
|
13
|
-
}
|
|
14
|
-
export declare const instructions: Registry<Instruction>;
|
|
15
|
-
export default instructions;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { Registry } from '@nocobase/utils';
|
|
2
|
-
import prompt from './prompt';
|
|
3
|
-
import calculation from './calculation';
|
|
4
|
-
import condition from './condition';
|
|
5
|
-
import parallel from './parallel';
|
|
6
|
-
import query from './query';
|
|
7
|
-
import create from './create';
|
|
8
|
-
import update from './update';
|
|
9
|
-
import destroy from './destroy';
|
|
10
|
-
export const instructions = new Registry();
|
|
11
|
-
instructions.register('prompt', prompt);
|
|
12
|
-
instructions.register('calculation', calculation);
|
|
13
|
-
instructions.register('condition', condition);
|
|
14
|
-
instructions.register('parallel', parallel);
|
|
15
|
-
instructions.register('query', query);
|
|
16
|
-
instructions.register('create', create);
|
|
17
|
-
instructions.register('update', update);
|
|
18
|
-
instructions.register('destroy', destroy);
|
|
19
|
-
export default instructions;
|
|
20
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/instructions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAK3C,OAAO,MAAM,MAAM,UAAU,CAAC;AAC9B,OAAO,WAAW,MAAM,eAAe,CAAC;AACxC,OAAO,SAAS,MAAM,aAAa,CAAC;AACpC,OAAO,QAAQ,MAAM,YAAY,CAAC;AAClC,OAAO,KAAK,MAAM,SAAS,CAAC;AAC5B,OAAO,MAAM,MAAM,UAAU,CAAC;AAC9B,OAAO,MAAM,MAAM,UAAU,CAAC;AAC9B,OAAO,OAAO,MAAM,WAAW,CAAC;AA+BhC,MAAM,CAAC,MAAM,YAAY,GAAG,IAAI,QAAQ,EAAe,CAAC;AAExD,YAAY,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AACxC,YAAY,CAAC,QAAQ,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;AAClD,YAAY,CAAC,QAAQ,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;AAC9C,YAAY,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;AAC5C,YAAY,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AACtC,YAAY,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AACxC,YAAY,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;AACxC,YAAY,CAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;AAE1C,eAAe,YAAY,CAAC","sourcesContent":["import { Registry } from '@nocobase/utils';\n\nimport ExecutionModel from '../models/Execution';\nimport FlowNodeModel from '../models/FlowNode';\n\nimport prompt from './prompt';\nimport calculation from './calculation';\nimport condition from './condition';\nimport parallel from './parallel';\nimport query from './query';\nimport create from './create';\nimport update from './update';\nimport destroy from './destroy';\n\nexport interface Job {\n status: number;\n result?: unknown;\n [key: string]: unknown;\n}\n\nexport type InstructionResult = Job | Promise<Job>;\n\n// what should a instruction do?\n// - base on input and context, do any calculations or system call (io), and produce a result or pending.\nexport interface Instruction {\n run(\n this: FlowNodeModel,\n // what should input to be?\n // - just use previously output result for convenience?\n input: any,\n // what should context to be?\n // - could be the workflow execution object (containing context data)\n execution: ExecutionModel\n ): InstructionResult;\n\n // for start node in main flow (or branch) to resume when manual sub branch triggered\n resume?(\n this: FlowNodeModel,\n input: any,\n execution: ExecutionModel\n ): InstructionResult\n}\n\nexport const instructions = new Registry<Instruction>();\n\ninstructions.register('prompt', prompt);\ninstructions.register('calculation', calculation);\ninstructions.register('condition', condition);\ninstructions.register('parallel', parallel);\ninstructions.register('query', query);\ninstructions.register('create', create);\ninstructions.register('update', update);\ninstructions.register('destroy', destroy);\n\nexport default instructions;\n"]}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import ExecutionModel from "../models/Execution";
|
|
2
|
-
import FlowNodeModel from "../models/FlowNode";
|
|
3
|
-
import JobModel from "../models/Job";
|
|
4
|
-
export declare const PARALLEL_MODE: {
|
|
5
|
-
readonly ALL: "all";
|
|
6
|
-
readonly ANY: "any";
|
|
7
|
-
readonly RACE: "race";
|
|
8
|
-
};
|
|
9
|
-
declare const _default: {
|
|
10
|
-
run(this: FlowNodeModel, prevJob: JobModel, execution: ExecutionModel): Promise<any>;
|
|
11
|
-
resume(this: any, branchJob: any, execution: ExecutionModel): Promise<any>;
|
|
12
|
-
};
|
|
13
|
-
export default _default;
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
import { JOB_STATUS } from "../constants";
|
|
11
|
-
export const PARALLEL_MODE = {
|
|
12
|
-
ALL: 'all',
|
|
13
|
-
ANY: 'any',
|
|
14
|
-
RACE: 'race'
|
|
15
|
-
};
|
|
16
|
-
const StatusGetters = {
|
|
17
|
-
[PARALLEL_MODE.ALL](result) {
|
|
18
|
-
if (result.some(j => j && j.status === JOB_STATUS.REJECTED)) {
|
|
19
|
-
return JOB_STATUS.REJECTED;
|
|
20
|
-
}
|
|
21
|
-
if (result.every(j => j && j.status === JOB_STATUS.RESOLVED)) {
|
|
22
|
-
return JOB_STATUS.RESOLVED;
|
|
23
|
-
}
|
|
24
|
-
return JOB_STATUS.PENDING;
|
|
25
|
-
},
|
|
26
|
-
[PARALLEL_MODE.ANY](result) {
|
|
27
|
-
return result.some(j => j && j.status === JOB_STATUS.RESOLVED)
|
|
28
|
-
? JOB_STATUS.RESOLVED
|
|
29
|
-
: (result.some(j => j && j.status === JOB_STATUS.PENDING)
|
|
30
|
-
? JOB_STATUS.PENDING
|
|
31
|
-
: JOB_STATUS.REJECTED);
|
|
32
|
-
},
|
|
33
|
-
[PARALLEL_MODE.RACE](result) {
|
|
34
|
-
return result.some(j => j && j.status === JOB_STATUS.RESOLVED)
|
|
35
|
-
? JOB_STATUS.RESOLVED
|
|
36
|
-
: (result.some(j => j && j.status === JOB_STATUS.REJECTED)
|
|
37
|
-
? JOB_STATUS.REJECTED
|
|
38
|
-
: JOB_STATUS.PENDING);
|
|
39
|
-
}
|
|
40
|
-
};
|
|
41
|
-
export default {
|
|
42
|
-
run(prevJob, execution) {
|
|
43
|
-
var _a;
|
|
44
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
45
|
-
const branches = execution.nodes
|
|
46
|
-
.filter(item => item.upstream === this && item.branchIndex !== null)
|
|
47
|
-
.sort((a, b) => a.branchIndex - b.branchIndex);
|
|
48
|
-
const job = yield execution.saveJob({
|
|
49
|
-
status: JOB_STATUS.PENDING,
|
|
50
|
-
result: Array(branches.length).fill(null),
|
|
51
|
-
nodeId: this.id,
|
|
52
|
-
upstreamId: (_a = prevJob === null || prevJob === void 0 ? void 0 : prevJob.id) !== null && _a !== void 0 ? _a : null
|
|
53
|
-
});
|
|
54
|
-
// NOTE:
|
|
55
|
-
// use `reduce` but not `Promise.all` here to avoid racing manupulating db.
|
|
56
|
-
// for users, this is almost equivalent to `Promise.all`,
|
|
57
|
-
// because of the delay is not significant sensible.
|
|
58
|
-
// another better aspect of this is, it could handle sequenced branches in future.
|
|
59
|
-
yield branches.reduce((promise, branch) => promise.then(() => execution.run(branch, job)), Promise.resolve());
|
|
60
|
-
return execution.end(this, job);
|
|
61
|
-
});
|
|
62
|
-
},
|
|
63
|
-
resume(branchJob, execution) {
|
|
64
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
65
|
-
const job = execution.findBranchParentJob(branchJob, this);
|
|
66
|
-
const { result, status } = job;
|
|
67
|
-
// if parallel has been done (resolved / rejected), do not care newly executed branch jobs.
|
|
68
|
-
if (status !== JOB_STATUS.PENDING) {
|
|
69
|
-
return null;
|
|
70
|
-
}
|
|
71
|
-
// find the index of the node which start the branch
|
|
72
|
-
const jobNode = execution.nodesMap.get(branchJob.nodeId);
|
|
73
|
-
const { branchIndex } = execution.findBranchStartNode(jobNode);
|
|
74
|
-
const { mode = PARALLEL_MODE.ALL } = this.config || {};
|
|
75
|
-
const newResult = [...result.slice(0, branchIndex), branchJob.get(), ...result.slice(branchIndex + 1)];
|
|
76
|
-
job.set({
|
|
77
|
-
result: newResult,
|
|
78
|
-
status: StatusGetters[mode](newResult)
|
|
79
|
-
});
|
|
80
|
-
if (job.status === JOB_STATUS.PENDING) {
|
|
81
|
-
yield job.save({ transaction: execution.tx });
|
|
82
|
-
return execution.end(this, job);
|
|
83
|
-
}
|
|
84
|
-
return job;
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
//# sourceMappingURL=parallel.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parallel.js","sourceRoot":"","sources":["../../src/instructions/parallel.ts"],"names":[],"mappings":"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","sourcesContent":["import { JOB_STATUS } from \"../constants\";\nimport ExecutionModel from \"../models/Execution\";\nimport FlowNodeModel from \"../models/FlowNode\";\nimport JobModel from \"../models/Job\";\n\nexport const PARALLEL_MODE = {\n ALL: 'all',\n ANY: 'any',\n RACE: 'race'\n} as const;\n\nconst StatusGetters = {\n [PARALLEL_MODE.ALL](result) {\n if (result.some(j => j && j.status === JOB_STATUS.REJECTED)) {\n return JOB_STATUS.REJECTED;\n }\n if (result.every(j => j && j.status === JOB_STATUS.RESOLVED)) {\n return JOB_STATUS.RESOLVED;\n }\n return JOB_STATUS.PENDING;\n },\n [PARALLEL_MODE.ANY](result) {\n return result.some(j => j && j.status === JOB_STATUS.RESOLVED)\n ? JOB_STATUS.RESOLVED\n : (\n result.some(j => j && j.status === JOB_STATUS.PENDING)\n ? JOB_STATUS.PENDING\n : JOB_STATUS.REJECTED\n )\n },\n [PARALLEL_MODE.RACE](result) {\n return result.some(j => j && j.status === JOB_STATUS.RESOLVED)\n ? JOB_STATUS.RESOLVED\n : (\n result.some(j => j && j.status === JOB_STATUS.REJECTED)\n ? JOB_STATUS.REJECTED\n : JOB_STATUS.PENDING\n )\n }\n};\n\nexport default {\n async run(this: FlowNodeModel, prevJob: JobModel, execution: ExecutionModel) {\n const branches = execution.nodes\n .filter(item => item.upstream === this && item.branchIndex !== null)\n .sort((a, b) => a.branchIndex - b.branchIndex);\n\n const job = await execution.saveJob({\n status: JOB_STATUS.PENDING,\n result: Array(branches.length).fill(null),\n nodeId: this.id,\n upstreamId: prevJob?.id ?? null\n });\n\n // NOTE:\n // use `reduce` but not `Promise.all` here to avoid racing manupulating db.\n // for users, this is almost equivalent to `Promise.all`,\n // because of the delay is not significant sensible.\n // another better aspect of this is, it could handle sequenced branches in future.\n await branches.reduce((promise: Promise<any>, branch) => promise.then(() => execution.run(branch, job)), Promise.resolve());\n\n return execution.end(this, job);\n },\n\n async resume(this, branchJob, execution: ExecutionModel) {\n const job = execution.findBranchParentJob(branchJob, this);\n\n const { result, status } = job;\n // if parallel has been done (resolved / rejected), do not care newly executed branch jobs.\n if (status !== JOB_STATUS.PENDING) {\n return null;\n }\n\n // find the index of the node which start the branch\n const jobNode = execution.nodesMap.get(branchJob.nodeId);\n const { branchIndex } = execution.findBranchStartNode(jobNode);\n const { mode = PARALLEL_MODE.ALL } = this.config || {};\n\n const newResult = [...result.slice(0, branchIndex), branchJob.get(), ...result.slice(branchIndex + 1)];\n job.set({\n result: newResult,\n status: StatusGetters[mode](newResult)\n });\n\n if (job.status === JOB_STATUS.PENDING) {\n await job.save({ transaction: execution.tx });\n return execution.end(this, job);\n }\n\n return job;\n }\n};\n"]}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { JOB_STATUS } from "../constants";
|
|
2
|
-
export default {
|
|
3
|
-
run(input, execution) {
|
|
4
|
-
return {
|
|
5
|
-
status: JOB_STATUS.PENDING
|
|
6
|
-
};
|
|
7
|
-
},
|
|
8
|
-
resume(job, execution) {
|
|
9
|
-
job.set('status', JOB_STATUS.RESOLVED);
|
|
10
|
-
return job;
|
|
11
|
-
}
|
|
12
|
-
};
|
|
13
|
-
//# sourceMappingURL=prompt.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/instructions/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,eAAe;IACb,GAAG,CAAO,KAAK,EAAE,SAAS;QACxB,OAAO;YACL,MAAM,EAAE,UAAU,CAAC,OAAO;SAC3B,CAAC;IACJ,CAAC;IAED,MAAM,CAAO,GAAG,EAAE,SAAS;QACzB,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAAC,CAAC;QACvC,OAAO,GAAG,CAAC;IACb,CAAC;CACF,CAAC","sourcesContent":["import { JOB_STATUS } from \"../constants\";\n\nexport default {\n run(this, input, execution) {\n return {\n status: JOB_STATUS.PENDING\n };\n },\n\n resume(this, job, execution) {\n job.set('status', JOB_STATUS.RESOLVED);\n return job;\n }\n};\n"]}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
import { JOB_STATUS } from "../constants";
|
|
11
|
-
export default {
|
|
12
|
-
run(input, execution) {
|
|
13
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
14
|
-
const { collection, multiple, params = {} } = this.config;
|
|
15
|
-
const repo = this.constructor.database.getRepository(collection);
|
|
16
|
-
const options = execution.getParsedValue(params);
|
|
17
|
-
const result = yield (multiple ? repo.find : repo.findOne).call(repo, Object.assign(Object.assign({}, options), {
|
|
18
|
-
// NOTE: `raw` to avoid getting undefined value from Proxied model instance (#380)
|
|
19
|
-
// e.g. Object.prototype.hasOwnProperty.call(result, 'id') // false
|
|
20
|
-
// so the properties can not be get by json-templates(object-path)
|
|
21
|
-
raw: true, transaction: execution.tx }));
|
|
22
|
-
return {
|
|
23
|
-
result,
|
|
24
|
-
status: JOB_STATUS.RESOLVED
|
|
25
|
-
};
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
//# sourceMappingURL=query.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/instructions/query.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,eAAe;IACP,GAAG,CAAsB,KAAK,EAAE,SAAS;;YAC7C,MAAM,EACJ,UAAU,EACV,QAAQ,EACR,MAAM,GAAG,EAAE,EACZ,GAAG,IAAI,CAAC,MAAM,CAAC;YAEhB,MAAM,IAAI,GAA0B,IAAI,CAAC,WAAY,CAAC,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;YACzF,MAAM,OAAO,GAAG,SAAS,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;YACjD,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,kCAC/D,OAAO;gBACV,kFAAkF;gBAClF,mEAAmE;gBACnE,kEAAkE;gBAClE,GAAG,EAAE,IAAI,EACT,WAAW,EAAE,SAAS,CAAC,EAAE,IACzB,CAAC;YAEH,OAAO;gBACL,MAAM;gBACN,MAAM,EAAE,UAAU,CAAC,QAAQ;aAC5B,CAAC;QACJ,CAAC;KAAA;CACF,CAAC","sourcesContent":["import { JOB_STATUS } from \"../constants\";\nimport FlowNodeModel from \"../models/FlowNode\";\n\nexport default {\n async run(this: FlowNodeModel, input, execution) {\n const {\n collection,\n multiple,\n params = {}\n } = this.config;\n\n const repo = (<typeof FlowNodeModel>this.constructor).database.getRepository(collection);\n const options = execution.getParsedValue(params);\n const result = await (multiple ? repo.find : repo.findOne).call(repo, {\n ...options,\n // NOTE: `raw` to avoid getting undefined value from Proxied model instance (#380)\n // e.g. Object.prototype.hasOwnProperty.call(result, 'id') // false\n // so the properties can not be get by json-templates(object-path)\n raw: true,\n transaction: execution.tx\n });\n\n return {\n result,\n status: JOB_STATUS.RESOLVED\n };\n }\n};\n"]}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import ExecutionModel from "../models/Execution";
|
|
2
|
-
import FlowNodeModel from "../models/FlowNode";
|
|
3
|
-
declare const _default: {
|
|
4
|
-
run(this: FlowNodeModel, input: any, execution: ExecutionModel): Promise<{
|
|
5
|
-
result: import("@nocobase/database").Model<any, any> | import("@nocobase/database").Model<any, any>[];
|
|
6
|
-
status: number;
|
|
7
|
-
}>;
|
|
8
|
-
};
|
|
9
|
-
export default _default;
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
import { JOB_STATUS } from "../constants";
|
|
11
|
-
export default {
|
|
12
|
-
run(input, execution) {
|
|
13
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
14
|
-
const { collection, multiple = false, params = {} } = this.config;
|
|
15
|
-
const repo = this.constructor.database.getRepository(collection);
|
|
16
|
-
const options = execution.getParsedValue(params);
|
|
17
|
-
const result = yield repo.update(Object.assign(Object.assign({}, options), { transaction: execution.tx }));
|
|
18
|
-
return {
|
|
19
|
-
result: multiple ? result : (result[0] || null),
|
|
20
|
-
status: JOB_STATUS.RESOLVED
|
|
21
|
-
};
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
};
|
|
25
|
-
//# sourceMappingURL=update.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/instructions/update.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAI1C,eAAe;IACP,GAAG,CAAsB,KAAK,EAAE,SAAyB;;YAC7D,MAAM,EACJ,UAAU,EACV,QAAQ,GAAG,KAAK,EAChB,MAAM,GAAG,EAAE,EACZ,GAAG,IAAI,CAAC,MAAM,CAAC;YAEhB,MAAM,IAAI,GAA0B,IAAI,CAAC,WAAY,CAAC,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;YACzF,MAAM,OAAO,GAAG,SAAS,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;YACjD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,iCAC3B,OAAO,KACV,WAAW,EAAE,SAAS,CAAC,EAAE,IACzB,CAAC;YAEH,OAAO;gBACL,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;gBAC/C,MAAM,EAAE,UAAU,CAAC,QAAQ;aAC5B,CAAC;QACJ,CAAC;KAAA;CACF,CAAA","sourcesContent":["import { JOB_STATUS } from \"../constants\";\nimport ExecutionModel from \"../models/Execution\";\nimport FlowNodeModel from \"../models/FlowNode\";\n\nexport default {\n async run(this: FlowNodeModel, input, execution: ExecutionModel) {\n const {\n collection,\n multiple = false,\n params = {}\n } = this.config;\n\n const repo = (<typeof FlowNodeModel>this.constructor).database.getRepository(collection);\n const options = execution.getParsedValue(params);\n const result = await repo.update({\n ...options,\n transaction: execution.tx\n });\n\n return {\n result: multiple ? result : (result[0] || null),\n status: JOB_STATUS.RESOLVED\n };\n }\n}\n"]}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { Database, Model } from '@nocobase/database';
|
|
2
|
-
import { BelongsToGetAssociationMixin, HasManyGetAssociationsMixin, Transaction } from 'sequelize';
|
|
3
|
-
import WorkflowModel from './Workflow';
|
|
4
|
-
import FlowNodeModel from './FlowNode';
|
|
5
|
-
import JobModel from './Job';
|
|
6
|
-
export interface ExecutionOptions {
|
|
7
|
-
transaction?: Transaction;
|
|
8
|
-
}
|
|
9
|
-
export default class ExecutionModel extends Model {
|
|
10
|
-
static readonly database: Database;
|
|
11
|
-
id: number;
|
|
12
|
-
title: string;
|
|
13
|
-
context: any;
|
|
14
|
-
status: number;
|
|
15
|
-
useTransaction: boolean;
|
|
16
|
-
transaction: string;
|
|
17
|
-
createdAt: Date;
|
|
18
|
-
updatedAt: Date;
|
|
19
|
-
workflow?: WorkflowModel;
|
|
20
|
-
getWorkflow: BelongsToGetAssociationMixin<WorkflowModel>;
|
|
21
|
-
jobs?: JobModel[];
|
|
22
|
-
getJobs: HasManyGetAssociationsMixin<JobModel>;
|
|
23
|
-
options: ExecutionOptions;
|
|
24
|
-
tx: Transaction;
|
|
25
|
-
nodes: Array<FlowNodeModel>;
|
|
26
|
-
nodesMap: Map<number, FlowNodeModel>;
|
|
27
|
-
jobsMap: Map<number, JobModel>;
|
|
28
|
-
jobsMapByNodeId: {
|
|
29
|
-
[key: number]: any;
|
|
30
|
-
};
|
|
31
|
-
static StatusMap: {
|
|
32
|
-
[x: number]: number;
|
|
33
|
-
};
|
|
34
|
-
makeNodes(nodes?: any[]): void;
|
|
35
|
-
makeJobs(jobs: Array<JobModel>): void;
|
|
36
|
-
getTransaction(): Promise<Transaction>;
|
|
37
|
-
prepare(options: any, commit?: boolean): Promise<void>;
|
|
38
|
-
start(options: ExecutionOptions): Promise<void>;
|
|
39
|
-
resume(job: JobModel, options: ExecutionOptions): Promise<void>;
|
|
40
|
-
private commit;
|
|
41
|
-
private exec;
|
|
42
|
-
run(node: any, input?: any): any;
|
|
43
|
-
end(node: any, job: any): any;
|
|
44
|
-
recall(node: any, job: any): any;
|
|
45
|
-
exit(job: JobModel | null): Promise<any>;
|
|
46
|
-
saveJob(payload: any): Promise<JobModel>;
|
|
47
|
-
findBranchStartNode(node: FlowNodeModel): FlowNodeModel | null;
|
|
48
|
-
findBranchParentNode(node: FlowNodeModel): FlowNodeModel | null;
|
|
49
|
-
findBranchParentJob(job: JobModel, node: FlowNodeModel): JobModel | null;
|
|
50
|
-
getParsedValue(value: any, node?: any): any;
|
|
51
|
-
}
|
package/esm/models/Execution.js
DELETED
|
@@ -1,256 +0,0 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
import { Model } from '@nocobase/database';
|
|
11
|
-
import parse from 'json-templates';
|
|
12
|
-
import { EXECUTION_STATUS, JOB_STATUS } from '../constants';
|
|
13
|
-
import instructions from '../instructions';
|
|
14
|
-
import calculators from '../calculators';
|
|
15
|
-
export default class ExecutionModel extends Model {
|
|
16
|
-
constructor() {
|
|
17
|
-
super(...arguments);
|
|
18
|
-
this.nodes = [];
|
|
19
|
-
this.nodesMap = new Map();
|
|
20
|
-
this.jobsMap = new Map();
|
|
21
|
-
this.jobsMapByNodeId = {};
|
|
22
|
-
}
|
|
23
|
-
// make dual linked nodes list then cache
|
|
24
|
-
makeNodes(nodes = []) {
|
|
25
|
-
this.nodes = nodes;
|
|
26
|
-
nodes.forEach((node) => {
|
|
27
|
-
this.nodesMap.set(node.id, node);
|
|
28
|
-
});
|
|
29
|
-
nodes.forEach((node) => {
|
|
30
|
-
if (node.upstreamId) {
|
|
31
|
-
node.upstream = this.nodesMap.get(node.upstreamId);
|
|
32
|
-
}
|
|
33
|
-
if (node.downstreamId) {
|
|
34
|
-
node.downstream = this.nodesMap.get(node.downstreamId);
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
makeJobs(jobs) {
|
|
39
|
-
jobs.forEach((job) => {
|
|
40
|
-
this.jobsMap.set(job.id, job);
|
|
41
|
-
// TODO: should consider cycle, and from previous job
|
|
42
|
-
this.jobsMapByNodeId[job.nodeId] = job.result;
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
getTransaction() {
|
|
46
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
47
|
-
const { sequelize } = this.constructor.database;
|
|
48
|
-
if (!this.useTransaction) {
|
|
49
|
-
return undefined;
|
|
50
|
-
}
|
|
51
|
-
const { options } = this;
|
|
52
|
-
// @ts-ignore
|
|
53
|
-
const transaction = options.transaction && !options.transaction.finished
|
|
54
|
-
? options.transaction
|
|
55
|
-
: sequelize.transaction();
|
|
56
|
-
// @ts-ignore
|
|
57
|
-
if (this.transaction !== transaction.id) {
|
|
58
|
-
// @ts-ignore
|
|
59
|
-
yield this.update({ transaction: transaction.id }, { transaction });
|
|
60
|
-
}
|
|
61
|
-
return transaction;
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
prepare(options, commit = false) {
|
|
65
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
66
|
-
this.options = options || {};
|
|
67
|
-
const transaction = yield this.getTransaction();
|
|
68
|
-
this.tx = transaction;
|
|
69
|
-
if (!this.workflow) {
|
|
70
|
-
this.workflow = yield this.getWorkflow({ transaction });
|
|
71
|
-
}
|
|
72
|
-
const nodes = yield this.workflow.getNodes({ transaction });
|
|
73
|
-
this.makeNodes(nodes);
|
|
74
|
-
const jobs = yield this.getJobs({
|
|
75
|
-
order: [['id', 'ASC']],
|
|
76
|
-
transaction,
|
|
77
|
-
});
|
|
78
|
-
this.makeJobs(jobs);
|
|
79
|
-
if (commit) {
|
|
80
|
-
yield this.commit();
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
start(options) {
|
|
85
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
86
|
-
if (this.status !== EXECUTION_STATUS.STARTED) {
|
|
87
|
-
throw new Error(`execution was ended with status ${this.status}`);
|
|
88
|
-
}
|
|
89
|
-
yield this.prepare(options);
|
|
90
|
-
if (this.nodes.length) {
|
|
91
|
-
const head = this.nodes.find(item => !item.upstream);
|
|
92
|
-
yield this.run(head, { result: this.context });
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
yield this.exit(null);
|
|
96
|
-
}
|
|
97
|
-
yield this.commit();
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
resume(job, options) {
|
|
101
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
102
|
-
if (this.status !== EXECUTION_STATUS.STARTED) {
|
|
103
|
-
throw new Error(`execution was ended with status ${this.status}`);
|
|
104
|
-
}
|
|
105
|
-
yield this.prepare(options);
|
|
106
|
-
const node = this.nodesMap.get(job.nodeId);
|
|
107
|
-
yield this.recall(node, job);
|
|
108
|
-
yield this.commit();
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
commit() {
|
|
112
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
113
|
-
// @ts-ignore
|
|
114
|
-
if (this.tx && (!this.options.transaction || this.options.transaction.finished)) {
|
|
115
|
-
yield this.tx.commit();
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
exec(instruction, node, prevJob) {
|
|
120
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
121
|
-
let job;
|
|
122
|
-
try {
|
|
123
|
-
// call instruction to get result and status
|
|
124
|
-
job = yield instruction.call(node, prevJob, this);
|
|
125
|
-
if (!job) {
|
|
126
|
-
return null;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
catch (err) {
|
|
130
|
-
// for uncaught error, set to rejected
|
|
131
|
-
job = {
|
|
132
|
-
result: err instanceof Error
|
|
133
|
-
? { message: err.message, stack: process.env.NODE_ENV === 'production' ? [] : err.stack }
|
|
134
|
-
: err,
|
|
135
|
-
status: JOB_STATUS.REJECTED,
|
|
136
|
-
};
|
|
137
|
-
// if previous job is from resuming
|
|
138
|
-
if (prevJob && prevJob.nodeId === node.id) {
|
|
139
|
-
prevJob.set(job);
|
|
140
|
-
job = prevJob;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
let savedJob;
|
|
144
|
-
// TODO(optimize): many checking of resuming or new could be improved
|
|
145
|
-
// could be implemented separately in exec() / resume()
|
|
146
|
-
if (job instanceof Model) {
|
|
147
|
-
savedJob = (yield job.save({ transaction: this.tx }));
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
const upstreamId = prevJob instanceof Model ? prevJob.get('id') : null;
|
|
151
|
-
savedJob = yield this.saveJob(Object.assign({ nodeId: node.id, upstreamId }, job));
|
|
152
|
-
}
|
|
153
|
-
if (savedJob.status === JOB_STATUS.RESOLVED && node.downstream) {
|
|
154
|
-
// run next node
|
|
155
|
-
return this.run(node.downstream, savedJob);
|
|
156
|
-
}
|
|
157
|
-
// all nodes in scope have been executed
|
|
158
|
-
return this.end(node, savedJob);
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
run(node, input) {
|
|
162
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
163
|
-
const { run } = instructions.get(node.type);
|
|
164
|
-
if (typeof run !== 'function') {
|
|
165
|
-
return Promise.reject(new Error('`run` should be implemented for customized execution of the node'));
|
|
166
|
-
}
|
|
167
|
-
return this.exec(run, node, input);
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
// parent node should take over the control
|
|
171
|
-
end(node, job) {
|
|
172
|
-
const parentNode = this.findBranchParentNode(node);
|
|
173
|
-
// no parent, means on main flow
|
|
174
|
-
if (parentNode) {
|
|
175
|
-
return this.recall(parentNode, job);
|
|
176
|
-
}
|
|
177
|
-
// really done for all nodes
|
|
178
|
-
// * should mark execution as done with last job status
|
|
179
|
-
return this.exit(job);
|
|
180
|
-
}
|
|
181
|
-
recall(node, job) {
|
|
182
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
183
|
-
const { resume } = instructions.get(node.type);
|
|
184
|
-
if (typeof resume !== 'function') {
|
|
185
|
-
return Promise.reject(new Error('`resume` should be implemented because the node made branch'));
|
|
186
|
-
}
|
|
187
|
-
return this.exec(resume, node, job);
|
|
188
|
-
});
|
|
189
|
-
}
|
|
190
|
-
exit(job) {
|
|
191
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
192
|
-
const status = job ? ExecutionModel.StatusMap[job.status] : EXECUTION_STATUS.RESOLVED;
|
|
193
|
-
yield this.update({ status }, { transaction: this.tx });
|
|
194
|
-
return null;
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
// TODO(optimize)
|
|
198
|
-
saveJob(payload) {
|
|
199
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
200
|
-
const { database } = this.constructor;
|
|
201
|
-
const { model } = database.getCollection('jobs');
|
|
202
|
-
const [job] = (yield model.upsert(Object.assign(Object.assign({}, payload), { executionId: this.id }), { transaction: this.tx }));
|
|
203
|
-
this.jobsMap.set(job.id, job);
|
|
204
|
-
this.jobsMapByNodeId[job.nodeId] = job.result;
|
|
205
|
-
return job;
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
// find the first node in current branch
|
|
209
|
-
findBranchStartNode(node) {
|
|
210
|
-
for (let n = node; n; n = n.upstream) {
|
|
211
|
-
if (n.branchIndex !== null) {
|
|
212
|
-
return n;
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
return null;
|
|
216
|
-
}
|
|
217
|
-
// find the node start current branch
|
|
218
|
-
findBranchParentNode(node) {
|
|
219
|
-
for (let n = node; n; n = n.upstream) {
|
|
220
|
-
if (n.branchIndex !== null) {
|
|
221
|
-
return n.upstream;
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
return null;
|
|
225
|
-
}
|
|
226
|
-
findBranchParentJob(job, node) {
|
|
227
|
-
for (let j = job; j; j = this.jobsMap.get(j.upstreamId)) {
|
|
228
|
-
if (j.nodeId === node.id) {
|
|
229
|
-
return j;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
return null;
|
|
233
|
-
}
|
|
234
|
-
getParsedValue(value, node) {
|
|
235
|
-
const injectedFns = {};
|
|
236
|
-
const scope = {
|
|
237
|
-
execution: this,
|
|
238
|
-
node
|
|
239
|
-
};
|
|
240
|
-
for (let [name, fn] of calculators.getEntities()) {
|
|
241
|
-
injectedFns[name] = fn.bind(scope);
|
|
242
|
-
}
|
|
243
|
-
return parse(value)({
|
|
244
|
-
$context: this.context,
|
|
245
|
-
$jobsMapByNodeId: this.jobsMapByNodeId,
|
|
246
|
-
$fn: injectedFns
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
ExecutionModel.StatusMap = {
|
|
251
|
-
[JOB_STATUS.PENDING]: EXECUTION_STATUS.STARTED,
|
|
252
|
-
[JOB_STATUS.RESOLVED]: EXECUTION_STATUS.RESOLVED,
|
|
253
|
-
[JOB_STATUS.REJECTED]: EXECUTION_STATUS.REJECTED,
|
|
254
|
-
[JOB_STATUS.CANCELLED]: EXECUTION_STATUS.CANCELLED,
|
|
255
|
-
};
|
|
256
|
-
//# sourceMappingURL=Execution.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Execution.js","sourceRoot":"","sources":["../../src/models/Execution.ts"],"names":[],"mappings":"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","sourcesContent":["import { Database, Model } from '@nocobase/database';\nimport parse from 'json-templates';\nimport { BelongsToGetAssociationMixin, HasManyGetAssociationsMixin, Transaction } from 'sequelize';\nimport { EXECUTION_STATUS, JOB_STATUS } from '../constants';\nimport instructions from '../instructions';\nimport WorkflowModel from './Workflow';\nimport FlowNodeModel from './FlowNode';\nimport JobModel from './Job';\nimport calculators from '../calculators';\n\nexport interface ExecutionOptions {\n transaction?: Transaction;\n}\n\nexport default class ExecutionModel extends Model {\n declare static readonly database: Database;\n\n declare id: number;\n declare title: string;\n declare context: any;\n declare status: number;\n // NOTE: this duplicated column is for transaction in preparing cycle from workflow\n declare useTransaction: boolean;\n declare transaction: string;\n\n declare createdAt: Date;\n declare updatedAt: Date;\n\n declare workflow?: WorkflowModel;\n declare getWorkflow: BelongsToGetAssociationMixin<WorkflowModel>;\n\n declare jobs?: JobModel[];\n declare getJobs: HasManyGetAssociationsMixin<JobModel>;\n\n options: ExecutionOptions;\n\n tx: Transaction;\n\n nodes: Array<FlowNodeModel> = [];\n nodesMap = new Map<number, FlowNodeModel>();\n jobsMap = new Map<number, JobModel>();\n jobsMapByNodeId: { [key: number]: any } = {};\n\n static StatusMap = {\n [JOB_STATUS.PENDING]: EXECUTION_STATUS.STARTED,\n [JOB_STATUS.RESOLVED]: EXECUTION_STATUS.RESOLVED,\n [JOB_STATUS.REJECTED]: EXECUTION_STATUS.REJECTED,\n [JOB_STATUS.CANCELLED]: EXECUTION_STATUS.CANCELLED,\n };\n\n // make dual linked nodes list then cache\n makeNodes(nodes = []) {\n this.nodes = nodes;\n\n nodes.forEach((node) => {\n this.nodesMap.set(node.id, node);\n });\n\n nodes.forEach((node) => {\n if (node.upstreamId) {\n node.upstream = this.nodesMap.get(node.upstreamId);\n }\n\n if (node.downstreamId) {\n node.downstream = this.nodesMap.get(node.downstreamId);\n }\n });\n }\n\n makeJobs(jobs: Array<JobModel>) {\n jobs.forEach((job) => {\n this.jobsMap.set(job.id, job);\n // TODO: should consider cycle, and from previous job\n this.jobsMapByNodeId[job.nodeId] = job.result;\n });\n }\n\n async getTransaction() {\n const { sequelize } = (<typeof ExecutionModel>this.constructor).database;\n\n if (!this.useTransaction) {\n return undefined;\n }\n\n const { options } = this;\n\n // @ts-ignore\n const transaction = options.transaction && !options.transaction.finished\n ? options.transaction\n : sequelize.transaction();\n\n // @ts-ignore\n if (this.transaction !== transaction.id) {\n // @ts-ignore\n await this.update({ transaction: transaction.id }, { transaction });\n }\n return transaction;\n }\n\n async prepare(options, commit = false) {\n this.options = options || {};\n const transaction = await this.getTransaction();\n this.tx = transaction;\n\n if (!this.workflow) {\n this.workflow = await this.getWorkflow({ transaction });\n }\n\n const nodes = await this.workflow.getNodes({ transaction });\n\n this.makeNodes(nodes);\n\n const jobs = await this.getJobs({\n order: [['id', 'ASC']],\n transaction,\n });\n\n this.makeJobs(jobs);\n\n if (commit) {\n await this.commit();\n }\n }\n\n public async start(options: ExecutionOptions) {\n if (this.status !== EXECUTION_STATUS.STARTED) {\n throw new Error(`execution was ended with status ${this.status}`);\n }\n await this.prepare(options);\n if (this.nodes.length) {\n const head = this.nodes.find(item => !item.upstream);\n await this.run(head, { result: this.context });\n } else {\n await this.exit(null);\n }\n await this.commit();\n }\n\n public async resume(job: JobModel, options: ExecutionOptions) {\n if (this.status !== EXECUTION_STATUS.STARTED) {\n throw new Error(`execution was ended with status ${this.status}`);\n }\n await this.prepare(options);\n const node = this.nodesMap.get(job.nodeId);\n await this.recall(node, job);\n await this.commit();\n }\n\n private async commit() {\n // @ts-ignore\n if (this.tx && (!this.options.transaction || this.options.transaction.finished)) {\n await this.tx.commit();\n }\n }\n\n private async exec(instruction: Function, node: FlowNodeModel, prevJob) {\n let job;\n try {\n // call instruction to get result and status\n job = await instruction.call(node, prevJob, this);\n if (!job) {\n return null;\n }\n } catch (err) {\n // for uncaught error, set to rejected\n job = {\n result: err instanceof Error\n ? { message: err.message, stack: process.env.NODE_ENV === 'production' ? [] : err.stack }\n : err,\n status: JOB_STATUS.REJECTED,\n };\n // if previous job is from resuming\n if (prevJob && prevJob.nodeId === node.id) {\n prevJob.set(job);\n job = prevJob;\n }\n }\n\n let savedJob;\n // TODO(optimize): many checking of resuming or new could be improved\n // could be implemented separately in exec() / resume()\n if (job instanceof Model) {\n savedJob = (await job.save({ transaction: this.tx })) as unknown as JobModel;\n } else {\n const upstreamId = prevJob instanceof Model ? prevJob.get('id') : null;\n savedJob = await this.saveJob({\n nodeId: node.id,\n upstreamId,\n ...job,\n });\n }\n\n if (savedJob.status === JOB_STATUS.RESOLVED && node.downstream) {\n // run next node\n return this.run(node.downstream, savedJob);\n }\n\n // all nodes in scope have been executed\n return this.end(node, savedJob);\n }\n\n public async run(node, input?) {\n const { run } = instructions.get(node.type);\n if (typeof run !== 'function') {\n return Promise.reject(new Error('`run` should be implemented for customized execution of the node'));\n }\n\n return this.exec(run, node, input);\n }\n\n // parent node should take over the control\n public end(node, job) {\n const parentNode = this.findBranchParentNode(node);\n // no parent, means on main flow\n if (parentNode) {\n return this.recall(parentNode, job);\n }\n\n // really done for all nodes\n // * should mark execution as done with last job status\n return this.exit(job);\n }\n\n async recall(node, job) {\n const { resume } = instructions.get(node.type);\n if (typeof resume !== 'function') {\n return Promise.reject(new Error('`resume` should be implemented because the node made branch'));\n }\n\n return this.exec(resume, node, job);\n }\n\n async exit(job: JobModel | null) {\n const status = job ? ExecutionModel.StatusMap[job.status] : EXECUTION_STATUS.RESOLVED;\n await this.update({ status }, { transaction: this.tx });\n return null;\n }\n\n // TODO(optimize)\n async saveJob(payload) {\n const { database } = <typeof ExecutionModel>this.constructor;\n const { model } = database.getCollection('jobs');\n const [job] = (await model.upsert(\n {\n ...payload,\n executionId: this.id,\n },\n { transaction: this.tx },\n )) as unknown as [JobModel, boolean | null];\n this.jobsMap.set(job.id, job);\n this.jobsMapByNodeId[job.nodeId] = job.result;\n\n return job;\n }\n\n // find the first node in current branch\n findBranchStartNode(node: FlowNodeModel): FlowNodeModel | null {\n for (let n = node; n; n = n.upstream) {\n if (n.branchIndex !== null) {\n return n;\n }\n }\n return null;\n }\n\n // find the node start current branch\n findBranchParentNode(node: FlowNodeModel): FlowNodeModel | null {\n for (let n = node; n; n = n.upstream) {\n if (n.branchIndex !== null) {\n return n.upstream;\n }\n }\n return null;\n }\n\n findBranchParentJob(job: JobModel, node: FlowNodeModel): JobModel | null {\n for (let j = job; j; j = this.jobsMap.get(j.upstreamId)) {\n if (j.nodeId === node.id) {\n return j;\n }\n }\n return null;\n }\n\n public getParsedValue(value, node?) {\n const injectedFns = {};\n const scope = {\n execution: this,\n node\n };\n for (let [name, fn] of calculators.getEntities()) {\n injectedFns[name] = fn.bind(scope);\n }\n\n return parse(value)({\n $context: this.context,\n $jobsMapByNodeId: this.jobsMapByNodeId,\n $fn: injectedFns\n });\n }\n}\n"]}
|
package/esm/models/FlowNode.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { Database, Model } from '@nocobase/database';
|
|
2
|
-
import { BelongsToGetAssociationMixin } from 'sequelize';
|
|
3
|
-
import WorkflowModel from './Workflow';
|
|
4
|
-
export default class FlowNodeModel extends Model {
|
|
5
|
-
static readonly database: Database;
|
|
6
|
-
id: number;
|
|
7
|
-
title: string;
|
|
8
|
-
branchIndex: null | number;
|
|
9
|
-
type: string;
|
|
10
|
-
config: any;
|
|
11
|
-
createdAt: Date;
|
|
12
|
-
updatedAt: Date;
|
|
13
|
-
upstream: FlowNodeModel;
|
|
14
|
-
downstream: FlowNodeModel;
|
|
15
|
-
workflow?: WorkflowModel;
|
|
16
|
-
getWorkflow: BelongsToGetAssociationMixin<WorkflowModel>;
|
|
17
|
-
}
|
package/esm/models/FlowNode.js
DELETED