@nocobase/plugin-workflow 0.7.0-alpha.83 → 0.7.1-alpha.5
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/Plugin.d.ts +18 -0
- package/lib/Plugin.js +285 -0
- package/lib/Processor.d.ts +40 -0
- package/lib/Processor.js +440 -0
- package/lib/actions/workflows.d.ts +1 -2
- package/lib/actions/workflows.js +13 -87
- package/lib/calculators/index.d.ts +2 -2
- package/lib/calculators/index.js +4 -4
- package/lib/collections/executions.js +7 -15
- package/lib/collections/jobs.js +7 -26
- package/lib/collections/workflows.d.ts +1 -2
- package/lib/collections/workflows.js +67 -67
- package/lib/index.d.ts +4 -3
- package/lib/index.js +24 -10
- package/lib/instructions/calculation.d.ts +1 -1
- package/lib/instructions/calculation.js +4 -6
- package/lib/instructions/condition.d.ts +2 -2
- package/lib/instructions/condition.js +15 -19
- package/lib/instructions/create.d.ts +1 -1
- package/lib/instructions/create.js +8 -12
- package/lib/instructions/delay.d.ts +14 -0
- package/lib/instructions/delay.js +138 -0
- package/lib/instructions/destroy.d.ts +1 -1
- package/lib/instructions/destroy.js +8 -12
- package/lib/instructions/index.d.ts +11 -8
- package/lib/instructions/index.js +43 -13
- package/lib/instructions/parallel.d.ts +3 -3
- package/lib/instructions/parallel.js +15 -19
- package/lib/instructions/prompt.d.ts +2 -2
- package/lib/instructions/prompt.js +2 -2
- package/lib/instructions/query.d.ts +2 -1
- package/lib/instructions/query.js +9 -13
- package/lib/instructions/update.d.ts +2 -2
- package/lib/instructions/update.js +10 -14
- package/lib/models/Execution.d.ts +2 -33
- package/lib/models/Execution.js +2 -397
- package/lib/models/Workflow.d.ts +2 -2
- package/lib/models/Workflow.js +1 -81
- package/lib/triggers/collection.d.ts +2 -6
- package/lib/triggers/collection.js +62 -27
- package/lib/triggers/index.d.ts +11 -4
- package/lib/triggers/index.js +52 -5
- package/lib/triggers/schedule.d.ts +4 -7
- package/lib/triggers/schedule.js +205 -135
- package/package.json +8 -9
- package/lib/server.d.ts +0 -10
- package/lib/server.js +0 -124
package/lib/triggers/schedule.js
CHANGED
|
@@ -15,16 +15,18 @@ function _cronParser() {
|
|
|
15
15
|
return data;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
function
|
|
19
|
-
const data = require("
|
|
18
|
+
function _sequelize() {
|
|
19
|
+
const data = require("sequelize");
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
_sequelize = function _sequelize() {
|
|
22
22
|
return data;
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
return data;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
var _ = require("..");
|
|
29
|
+
|
|
28
30
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
29
31
|
|
|
30
32
|
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
@@ -51,7 +53,8 @@ ScheduleModes.set(SCHEDULE_MODE.CONSTANT, {
|
|
|
51
53
|
shouldCache(workflow, now) {
|
|
52
54
|
const _workflow$config = workflow.config,
|
|
53
55
|
startsOn = _workflow$config.startsOn,
|
|
54
|
-
endsOn = _workflow$config.endsOn
|
|
56
|
+
endsOn = _workflow$config.endsOn,
|
|
57
|
+
repeat = _workflow$config.repeat;
|
|
55
58
|
const timestamp = now.getTime();
|
|
56
59
|
|
|
57
60
|
if (startsOn) {
|
|
@@ -60,6 +63,10 @@ ScheduleModes.set(SCHEDULE_MODE.CONSTANT, {
|
|
|
60
63
|
if (!startTime || startTime > timestamp + this.cacheCycle) {
|
|
61
64
|
return false;
|
|
62
65
|
}
|
|
66
|
+
|
|
67
|
+
if (typeof repeat === 'number' && repeat > this.cacheCycle && (timestamp - startTime) % repeat > this.cacheCycle) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
63
70
|
}
|
|
64
71
|
|
|
65
72
|
if (endsOn) {
|
|
@@ -74,7 +81,20 @@ ScheduleModes.set(SCHEDULE_MODE.CONSTANT, {
|
|
|
74
81
|
},
|
|
75
82
|
|
|
76
83
|
trigger(workflow, date) {
|
|
77
|
-
|
|
84
|
+
const _workflow$config2 = workflow.config,
|
|
85
|
+
startsOn = _workflow$config2.startsOn,
|
|
86
|
+
endsOn = _workflow$config2.endsOn,
|
|
87
|
+
repeat = _workflow$config2.repeat;
|
|
88
|
+
|
|
89
|
+
if (startsOn && typeof repeat === 'number') {
|
|
90
|
+
const startTime = Date.parse(startsOn);
|
|
91
|
+
|
|
92
|
+
if ((startTime - date.getTime()) % repeat) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return this.plugin.trigger(workflow, {
|
|
78
98
|
date
|
|
79
99
|
});
|
|
80
100
|
}
|
|
@@ -83,7 +103,7 @@ ScheduleModes.set(SCHEDULE_MODE.CONSTANT, {
|
|
|
83
103
|
|
|
84
104
|
function getDateRangeFilter(on, now, dir) {
|
|
85
105
|
const timestamp = now.getTime();
|
|
86
|
-
const op = dir < 0 ?
|
|
106
|
+
const op = dir < 0 ? _sequelize().Op.lt : _sequelize().Op.gte;
|
|
87
107
|
|
|
88
108
|
switch (typeof on) {
|
|
89
109
|
case 'string':
|
|
@@ -101,6 +121,11 @@ function getDateRangeFilter(on, now, dir) {
|
|
|
101
121
|
offset = _on$offset === void 0 ? 0 : _on$offset,
|
|
102
122
|
_on$unit = on.unit,
|
|
103
123
|
unit = _on$unit === void 0 ? 1000 : _on$unit;
|
|
124
|
+
|
|
125
|
+
if (!field) {
|
|
126
|
+
return {};
|
|
127
|
+
}
|
|
128
|
+
|
|
104
129
|
return {
|
|
105
130
|
[field]: {
|
|
106
131
|
[op]: new Date(timestamp + offset * unit * dir)
|
|
@@ -114,7 +139,7 @@ function getDateRangeFilter(on, now, dir) {
|
|
|
114
139
|
return {};
|
|
115
140
|
}
|
|
116
141
|
|
|
117
|
-
function getDataOptionTime(data, on,
|
|
142
|
+
function getDataOptionTime(data, on, dir = 1) {
|
|
118
143
|
switch (typeof on) {
|
|
119
144
|
case 'string':
|
|
120
145
|
const time = Date.parse(on);
|
|
@@ -137,66 +162,75 @@ function getHookId(workflow, type) {
|
|
|
137
162
|
return `${type}#${workflow.id}`;
|
|
138
163
|
}
|
|
139
164
|
|
|
165
|
+
const DialectTimestampFnMap = {
|
|
166
|
+
postgres(col) {
|
|
167
|
+
return `CAST(FLOOR(extract(epoch from "${col}")) AS INTEGER)`;
|
|
168
|
+
},
|
|
169
|
+
|
|
170
|
+
mysql(col) {
|
|
171
|
+
return `CAST(FLOOR(UNIX_TIMESTAMP(\`${col}\`)) AS SIGNED INTEGER)`;
|
|
172
|
+
},
|
|
173
|
+
|
|
174
|
+
sqlite(col) {
|
|
175
|
+
return `CAST(FLOOR(unixepoch(${col})) AS INTEGER)`;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
};
|
|
179
|
+
DialectTimestampFnMap.mariadb = DialectTimestampFnMap.mysql;
|
|
140
180
|
ScheduleModes.set(SCHEDULE_MODE.COLLECTION_FIELD, {
|
|
141
181
|
on(workflow) {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
182
|
+
var _this = this;
|
|
183
|
+
|
|
184
|
+
const _workflow$config3 = workflow.config,
|
|
185
|
+
collection = _workflow$config3.collection,
|
|
186
|
+
startsOn = _workflow$config3.startsOn,
|
|
187
|
+
endsOn = _workflow$config3.endsOn,
|
|
188
|
+
repeat = _workflow$config3.repeat;
|
|
147
189
|
const event = `${collection}.afterSave`;
|
|
148
190
|
const name = getHookId(workflow, event);
|
|
149
191
|
|
|
150
192
|
if (!this.events.has(name)) {
|
|
151
193
|
// NOTE: toggle cache depends on new date
|
|
152
|
-
const listener = (
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
// * cron only : invalid
|
|
164
|
-
// * startsOn and endsOn: equal to only startsOn
|
|
165
|
-
// * startsOn and cron : startsOn in cycle and cron in cycle
|
|
166
|
-
// * endsOn and cron : invalid
|
|
167
|
-
// * all : all rules effect
|
|
168
|
-
// * none : invalid
|
|
169
|
-
// this means, startsOn and cron should be present at least one
|
|
170
|
-
// and no startsOn equals run on cron, and could ends on endsOn,
|
|
171
|
-
// this will be a little wired, only means the end date should use collection field.
|
|
172
|
-
const now = new Date();
|
|
173
|
-
now.setMilliseconds(0);
|
|
174
|
-
const timestamp = now.getTime();
|
|
175
|
-
const startTime = getDataOptionTime(data, startsOn, now);
|
|
176
|
-
const endTime = getDataOptionTime(data, endsOn, now, -1);
|
|
177
|
-
|
|
178
|
-
if (!startTime && !cron) {
|
|
179
|
-
return;
|
|
180
|
-
}
|
|
194
|
+
const listener = /*#__PURE__*/function () {
|
|
195
|
+
var _ref = _asyncToGenerator(function* (data, options) {
|
|
196
|
+
const now = new Date();
|
|
197
|
+
now.setMilliseconds(0);
|
|
198
|
+
const timestamp = now.getTime();
|
|
199
|
+
const startTime = getDataOptionTime(data, startsOn);
|
|
200
|
+
const endTime = getDataOptionTime(data, endsOn, -1);
|
|
201
|
+
|
|
202
|
+
if (!startTime && !repeat) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
181
205
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
206
|
+
if (startTime && startTime > timestamp + _this.cacheCycle) {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
185
209
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
210
|
+
if (endTime && endTime <= timestamp) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
189
213
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
214
|
+
if (!nextInCycle.call(_this, workflow, now)) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
193
217
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
218
|
+
if (typeof repeat === 'number' && repeat > _this.cacheCycle && (timestamp - startTime) % repeat > _this.cacheCycle) {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
console.log('set cache', now);
|
|
223
|
+
|
|
224
|
+
_this.setCache(workflow);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
return function listener(_x, _x2) {
|
|
228
|
+
return _ref.apply(this, arguments);
|
|
229
|
+
};
|
|
230
|
+
}();
|
|
197
231
|
|
|
198
232
|
this.events.set(name, listener);
|
|
199
|
-
this.db.on(`${collection}.afterSave`, listener);
|
|
233
|
+
this.plugin.app.db.on(`${collection}.afterSave`, listener);
|
|
200
234
|
}
|
|
201
235
|
},
|
|
202
236
|
|
|
@@ -208,21 +242,22 @@ ScheduleModes.set(SCHEDULE_MODE.COLLECTION_FIELD, {
|
|
|
208
242
|
if (this.events.has(name)) {
|
|
209
243
|
const listener = this.events.get(name);
|
|
210
244
|
this.events.delete(name);
|
|
211
|
-
this.db.off(`${collection}.afterSave`, listener);
|
|
245
|
+
this.plugin.app.db.off(`${collection}.afterSave`, listener);
|
|
212
246
|
}
|
|
213
247
|
},
|
|
214
248
|
|
|
215
249
|
shouldCache(workflow, now) {
|
|
216
|
-
var
|
|
250
|
+
var _this2 = this;
|
|
217
251
|
|
|
218
252
|
return _asyncToGenerator(function* () {
|
|
219
|
-
const _workflow$
|
|
220
|
-
startsOn = _workflow$
|
|
221
|
-
endsOn = _workflow$
|
|
222
|
-
|
|
253
|
+
const _workflow$config4 = workflow.config,
|
|
254
|
+
startsOn = _workflow$config4.startsOn,
|
|
255
|
+
endsOn = _workflow$config4.endsOn,
|
|
256
|
+
repeat = _workflow$config4.repeat,
|
|
257
|
+
collection = _workflow$config4.collection;
|
|
223
258
|
const starts = getDateRangeFilter(startsOn, now, -1);
|
|
224
259
|
|
|
225
|
-
if (!starts) {
|
|
260
|
+
if (!starts || !Object.keys(starts).length) {
|
|
226
261
|
return false;
|
|
227
262
|
}
|
|
228
263
|
|
|
@@ -232,33 +267,42 @@ ScheduleModes.set(SCHEDULE_MODE.COLLECTION_FIELD, {
|
|
|
232
267
|
return false;
|
|
233
268
|
}
|
|
234
269
|
|
|
235
|
-
const
|
|
270
|
+
const conditions = [starts, ends].filter(item => Boolean(Object.keys(item).length)); // when repeat is number, means repeat after startsOn
|
|
271
|
+
// (now - startsOn) % repeat <= cacheCycle
|
|
236
272
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
273
|
+
const db = _this2.plugin.app.db;
|
|
274
|
+
const tsFn = DialectTimestampFnMap[db.options.dialect];
|
|
275
|
+
|
|
276
|
+
if (repeat && typeof repeat === 'number' && repeat > _this2.cacheCycle && tsFn) {
|
|
277
|
+
const uts = now.getTime();
|
|
278
|
+
conditions.push((0, _sequelize().where)((0, _sequelize().fn)('MOD', (0, _sequelize().literal)(`${Math.round(uts / 1000)} - ${tsFn(startsOn.field)}`), Math.round(repeat / 1000)), {
|
|
279
|
+
[_sequelize().Op.lt]: Math.round(_this2.cacheCycle / 1000)
|
|
280
|
+
})); // conditions.push(literal(`mod(${uts} - ${tsFn(startsOn.field)} * 1000, ${repeat}) < ${this.cacheCycle}`));
|
|
240
281
|
}
|
|
241
282
|
|
|
242
|
-
const
|
|
283
|
+
const _db$getCollection = db.getCollection(collection),
|
|
284
|
+
model = _db$getCollection.model;
|
|
243
285
|
|
|
244
|
-
const count = yield
|
|
245
|
-
|
|
286
|
+
const count = yield model.count({
|
|
287
|
+
where: {
|
|
288
|
+
[_sequelize().Op.and]: conditions
|
|
289
|
+
}
|
|
246
290
|
});
|
|
247
291
|
return Boolean(count);
|
|
248
292
|
})();
|
|
249
293
|
},
|
|
250
294
|
|
|
251
295
|
trigger(workflow, date) {
|
|
252
|
-
var
|
|
296
|
+
var _this3 = this;
|
|
253
297
|
|
|
254
298
|
return _asyncToGenerator(function* () {
|
|
255
|
-
var _startsOn$offset, _startsOn$unit
|
|
299
|
+
var _startsOn$offset, _startsOn$unit;
|
|
256
300
|
|
|
257
|
-
const _workflow$
|
|
258
|
-
collection = _workflow$
|
|
259
|
-
startsOn = _workflow$
|
|
260
|
-
endsOn = _workflow$
|
|
261
|
-
|
|
301
|
+
const _workflow$config5 = workflow.config,
|
|
302
|
+
collection = _workflow$config5.collection,
|
|
303
|
+
startsOn = _workflow$config5.startsOn,
|
|
304
|
+
endsOn = _workflow$config5.endsOn,
|
|
305
|
+
repeat = _workflow$config5.repeat;
|
|
262
306
|
|
|
263
307
|
if (typeof startsOn !== 'object') {
|
|
264
308
|
return;
|
|
@@ -266,23 +310,30 @@ ScheduleModes.set(SCHEDULE_MODE.COLLECTION_FIELD, {
|
|
|
266
310
|
|
|
267
311
|
const timestamp = date.getTime();
|
|
268
312
|
const startTimestamp = timestamp - ((_startsOn$offset = startsOn.offset) !== null && _startsOn$offset !== void 0 ? _startsOn$offset : 0) * ((_startsOn$unit = startsOn.unit) !== null && _startsOn$unit !== void 0 ? _startsOn$unit : 1000);
|
|
269
|
-
|
|
313
|
+
const conditions = [];
|
|
270
314
|
|
|
271
|
-
if (!
|
|
315
|
+
if (!repeat) {
|
|
272
316
|
// startsOn exactly equal to now in 1s
|
|
273
|
-
|
|
317
|
+
conditions.push({
|
|
274
318
|
[startsOn.field]: {
|
|
275
|
-
|
|
276
|
-
|
|
319
|
+
[_sequelize().Op.gte]: new Date(startTimestamp),
|
|
320
|
+
[_sequelize().Op.lt]: new Date(startTimestamp + 1000)
|
|
277
321
|
}
|
|
278
|
-
};
|
|
322
|
+
});
|
|
279
323
|
} else {
|
|
280
324
|
// startsOn not after now
|
|
281
|
-
|
|
325
|
+
conditions.push({
|
|
282
326
|
[startsOn.field]: {
|
|
283
|
-
|
|
327
|
+
[_sequelize().Op.lt]: new Date(startTimestamp)
|
|
284
328
|
}
|
|
285
|
-
};
|
|
329
|
+
});
|
|
330
|
+
const tsFn = DialectTimestampFnMap[_this3.plugin.app.db.options.dialect];
|
|
331
|
+
|
|
332
|
+
if (typeof repeat === 'number' && tsFn) {
|
|
333
|
+
conditions.push((0, _sequelize().where)((0, _sequelize().fn)('MOD', (0, _sequelize().literal)(`${Math.round(timestamp / 1000)} - ${tsFn(startsOn.field)}`), Math.round(repeat / 1000)), {
|
|
334
|
+
[_sequelize().Op.eq]: 0
|
|
335
|
+
})); // conditions.push(literal(`MOD(CAST(${timestamp} AS BIGINT) - CAST((FLOOR(${tsFn(startsOn.field)}) AS BIGINT) * 1000), ${repeat}) = 0`));
|
|
336
|
+
}
|
|
286
337
|
|
|
287
338
|
switch (typeof endsOn) {
|
|
288
339
|
case 'string':
|
|
@@ -295,9 +346,16 @@ ScheduleModes.set(SCHEDULE_MODE.COLLECTION_FIELD, {
|
|
|
295
346
|
break;
|
|
296
347
|
|
|
297
348
|
case 'object':
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
349
|
+
if (endsOn.field) {
|
|
350
|
+
var _endsOn$offset, _endsOn$unit;
|
|
351
|
+
|
|
352
|
+
conditions.push({
|
|
353
|
+
[endsOn.field]: {
|
|
354
|
+
[_sequelize().Op.gte]: new Date(timestamp - ((_endsOn$offset = endsOn.offset) !== null && _endsOn$offset !== void 0 ? _endsOn$offset : 0) * ((_endsOn$unit = endsOn.unit) !== null && _endsOn$unit !== void 0 ? _endsOn$unit : 1000) + 1000)
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
|
|
301
359
|
break;
|
|
302
360
|
|
|
303
361
|
default:
|
|
@@ -305,14 +363,21 @@ ScheduleModes.set(SCHEDULE_MODE.COLLECTION_FIELD, {
|
|
|
305
363
|
}
|
|
306
364
|
}
|
|
307
365
|
|
|
308
|
-
const
|
|
366
|
+
const _this3$plugin$app$db$ = _this3.plugin.app.db.getCollection(collection),
|
|
367
|
+
model = _this3$plugin$app$db$.model;
|
|
309
368
|
|
|
310
|
-
const instances = yield
|
|
311
|
-
|
|
369
|
+
const instances = yield model.findAll({
|
|
370
|
+
where: {
|
|
371
|
+
[_sequelize().Op.and]: conditions
|
|
372
|
+
}
|
|
312
373
|
});
|
|
313
|
-
|
|
374
|
+
|
|
375
|
+
if (instances.length) {
|
|
376
|
+
console.log(instances.length, 'rows trigger at', date);
|
|
377
|
+
}
|
|
378
|
+
|
|
314
379
|
instances.forEach(item => {
|
|
315
|
-
|
|
380
|
+
_this3.plugin.trigger(workflow, {
|
|
316
381
|
date,
|
|
317
382
|
data: item.get()
|
|
318
383
|
});
|
|
@@ -322,21 +387,29 @@ ScheduleModes.set(SCHEDULE_MODE.COLLECTION_FIELD, {
|
|
|
322
387
|
|
|
323
388
|
});
|
|
324
389
|
|
|
325
|
-
function
|
|
326
|
-
const
|
|
390
|
+
function nextInCycle(workflow, now) {
|
|
391
|
+
const repeat = workflow.config.repeat; // no repeat means no need to rerun
|
|
327
392
|
// but if in current cycle, should be put in cache
|
|
328
|
-
// no
|
|
393
|
+
// no repeat but in current cycle means startsOn has been configured
|
|
329
394
|
// so we need to more info to determine if necessary config items
|
|
330
395
|
|
|
331
|
-
if (!
|
|
396
|
+
if (!repeat) {
|
|
332
397
|
return true;
|
|
333
398
|
}
|
|
334
399
|
|
|
400
|
+
switch (typeof repeat) {
|
|
401
|
+
case 'string':
|
|
402
|
+
break;
|
|
403
|
+
|
|
404
|
+
default:
|
|
405
|
+
return true;
|
|
406
|
+
}
|
|
407
|
+
|
|
335
408
|
const currentDate = new Date(now);
|
|
336
409
|
currentDate.setMilliseconds(-1);
|
|
337
410
|
const timestamp = now.getTime();
|
|
338
411
|
|
|
339
|
-
const interval = _cronParser().default.parseExpression(
|
|
412
|
+
const interval = _cronParser().default.parseExpression(repeat, {
|
|
340
413
|
currentDate
|
|
341
414
|
});
|
|
342
415
|
|
|
@@ -349,13 +422,11 @@ function cronInCycle(workflow, now) {
|
|
|
349
422
|
return false;
|
|
350
423
|
}
|
|
351
424
|
|
|
352
|
-
class ScheduleTrigger {
|
|
425
|
+
class ScheduleTrigger extends _.Trigger {
|
|
353
426
|
// running interval, default to 1s
|
|
354
427
|
// caching workflows in range, default to 1min
|
|
355
|
-
constructor({
|
|
356
|
-
|
|
357
|
-
}) {
|
|
358
|
-
this.db = void 0;
|
|
428
|
+
constructor(plugin) {
|
|
429
|
+
super(plugin);
|
|
359
430
|
this.events = new Map();
|
|
360
431
|
this.timer = null;
|
|
361
432
|
this.cache = new Map();
|
|
@@ -373,8 +444,7 @@ class ScheduleTrigger {
|
|
|
373
444
|
}
|
|
374
445
|
};
|
|
375
446
|
|
|
376
|
-
|
|
377
|
-
app.on('beforeStop', () => {
|
|
447
|
+
plugin.app.on('beforeStop', () => {
|
|
378
448
|
if (this.timer) {
|
|
379
449
|
clearInterval(this.timer);
|
|
380
450
|
}
|
|
@@ -397,21 +467,21 @@ class ScheduleTrigger {
|
|
|
397
467
|
}
|
|
398
468
|
|
|
399
469
|
onTick(now) {
|
|
400
|
-
var
|
|
470
|
+
var _this4 = this;
|
|
401
471
|
|
|
402
472
|
return _asyncToGenerator(function* () {
|
|
403
473
|
// NOTE: trigger workflows in sequence when sqlite due to only one transaction
|
|
404
|
-
const isSqlite =
|
|
405
|
-
return Array.from(
|
|
406
|
-
if (!
|
|
474
|
+
const isSqlite = _this4.plugin.app.db.options.dialect === 'sqlite';
|
|
475
|
+
return Array.from(_this4.cache.values()).reduce((prev, workflow) => {
|
|
476
|
+
if (!_this4.shouldTrigger(workflow, now)) {
|
|
407
477
|
return prev;
|
|
408
478
|
}
|
|
409
479
|
|
|
410
480
|
if (isSqlite) {
|
|
411
|
-
return prev.then(() =>
|
|
481
|
+
return prev.then(() => _this4.trigger(workflow, now));
|
|
412
482
|
}
|
|
413
483
|
|
|
414
|
-
|
|
484
|
+
_this4.trigger(workflow, now);
|
|
415
485
|
|
|
416
486
|
return null;
|
|
417
487
|
}, isSqlite ? Promise.resolve() : null);
|
|
@@ -419,10 +489,10 @@ class ScheduleTrigger {
|
|
|
419
489
|
}
|
|
420
490
|
|
|
421
491
|
reload() {
|
|
422
|
-
var
|
|
492
|
+
var _this5 = this;
|
|
423
493
|
|
|
424
494
|
return _asyncToGenerator(function* () {
|
|
425
|
-
const WorkflowModel =
|
|
495
|
+
const WorkflowModel = _this5.plugin.app.db.getCollection('workflows').model;
|
|
426
496
|
|
|
427
497
|
const workflows = yield WorkflowModel.findAll({
|
|
428
498
|
where: {
|
|
@@ -432,33 +502,33 @@ class ScheduleTrigger {
|
|
|
432
502
|
include: [{
|
|
433
503
|
association: 'executions',
|
|
434
504
|
attributes: ['id', 'createdAt'],
|
|
435
|
-
|
|
505
|
+
separate: true,
|
|
436
506
|
limit: 1,
|
|
437
507
|
order: [['createdAt', 'DESC']]
|
|
438
508
|
}],
|
|
439
509
|
group: ['id']
|
|
440
510
|
}); // NOTE: clear cached jobs in last cycle
|
|
441
511
|
|
|
442
|
-
|
|
512
|
+
_this5.cache = new Map();
|
|
443
513
|
|
|
444
|
-
|
|
514
|
+
_this5.inspect(workflows);
|
|
445
515
|
})();
|
|
446
516
|
}
|
|
447
517
|
|
|
448
518
|
inspect(workflows) {
|
|
449
|
-
var
|
|
519
|
+
var _this6 = this;
|
|
450
520
|
|
|
451
521
|
const now = new Date();
|
|
452
522
|
now.setMilliseconds(0);
|
|
453
523
|
workflows.forEach( /*#__PURE__*/function () {
|
|
454
|
-
var
|
|
455
|
-
const should = yield
|
|
524
|
+
var _ref2 = _asyncToGenerator(function* (workflow) {
|
|
525
|
+
const should = yield _this6.shouldCache(workflow, now);
|
|
456
526
|
|
|
457
|
-
|
|
527
|
+
_this6.setCache(workflow, !should);
|
|
458
528
|
});
|
|
459
529
|
|
|
460
|
-
return function (
|
|
461
|
-
return
|
|
530
|
+
return function (_x3) {
|
|
531
|
+
return _ref2.apply(this, arguments);
|
|
462
532
|
};
|
|
463
533
|
}());
|
|
464
534
|
}
|
|
@@ -468,7 +538,7 @@ class ScheduleTrigger {
|
|
|
468
538
|
}
|
|
469
539
|
|
|
470
540
|
shouldCache(workflow, now) {
|
|
471
|
-
var
|
|
541
|
+
var _this7 = this;
|
|
472
542
|
|
|
473
543
|
return _asyncToGenerator(function* () {
|
|
474
544
|
var _iteratorAbruptCompletion = false;
|
|
@@ -477,10 +547,10 @@ class ScheduleTrigger {
|
|
|
477
547
|
var _iteratorError;
|
|
478
548
|
|
|
479
549
|
try {
|
|
480
|
-
for (var _iterator = _asyncIterator(
|
|
550
|
+
for (var _iterator = _asyncIterator(_this7.constructor.CacheRules), _step; _iteratorAbruptCompletion = !(_step = yield _iterator.next()).done; _iteratorAbruptCompletion = false) {
|
|
481
551
|
const rule = _step.value;
|
|
482
552
|
|
|
483
|
-
if (!(yield rule.call(
|
|
553
|
+
if (!(yield rule.call(_this7, workflow, now))) {
|
|
484
554
|
return false;
|
|
485
555
|
}
|
|
486
556
|
}
|
|
@@ -525,12 +595,12 @@ class ScheduleTrigger {
|
|
|
525
595
|
}
|
|
526
596
|
|
|
527
597
|
trigger(workflow, date) {
|
|
528
|
-
var
|
|
598
|
+
var _this8 = this;
|
|
529
599
|
|
|
530
600
|
return _asyncToGenerator(function* () {
|
|
531
601
|
const mode = workflow.config.mode;
|
|
532
602
|
const modeHandlers = ScheduleModes.get(mode);
|
|
533
|
-
return modeHandlers.trigger.call(
|
|
603
|
+
return modeHandlers.trigger.call(_this8, workflow, date);
|
|
534
604
|
})();
|
|
535
605
|
}
|
|
536
606
|
|
|
@@ -564,23 +634,23 @@ exports.default = ScheduleTrigger;
|
|
|
564
634
|
ScheduleTrigger.CacheRules = [// ({ enabled }) => enabled,
|
|
565
635
|
({
|
|
566
636
|
config,
|
|
567
|
-
|
|
568
|
-
}) => config.limit ?
|
|
637
|
+
allExecuted
|
|
638
|
+
}) => config.limit ? allExecuted < config.limit : true, ({
|
|
569
639
|
config
|
|
570
|
-
}) => ['
|
|
640
|
+
}) => ['repeat', 'startsOn'].some(key => config[key]), nextInCycle, function (workflow, now) {
|
|
571
641
|
const mode = workflow.config.mode;
|
|
572
642
|
const modeHandlers = ScheduleModes.get(mode);
|
|
573
643
|
return modeHandlers.shouldCache.call(this, workflow, now);
|
|
574
644
|
}];
|
|
575
645
|
ScheduleTrigger.TriggerRules = [({
|
|
576
646
|
config,
|
|
577
|
-
|
|
578
|
-
}) => config.limit ?
|
|
647
|
+
allExecuted
|
|
648
|
+
}) => config.limit ? allExecuted < config.limit : true, ({
|
|
579
649
|
config
|
|
580
|
-
}) => ['
|
|
581
|
-
const
|
|
650
|
+
}) => ['repeat', 'startsOn'].some(key => config[key]), function (workflow, now) {
|
|
651
|
+
const repeat = workflow.config.repeat;
|
|
582
652
|
|
|
583
|
-
if (
|
|
653
|
+
if (typeof repeat !== 'string') {
|
|
584
654
|
return true;
|
|
585
655
|
}
|
|
586
656
|
|
|
@@ -588,7 +658,7 @@ ScheduleTrigger.TriggerRules = [({
|
|
|
588
658
|
currentDate.setMilliseconds(-1);
|
|
589
659
|
const timestamp = now.getTime();
|
|
590
660
|
|
|
591
|
-
const interval = _cronParser().default.parseExpression(
|
|
661
|
+
const interval = _cronParser().default.parseExpression(repeat, {
|
|
592
662
|
currentDate
|
|
593
663
|
});
|
|
594
664
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/plugin-workflow",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.1-alpha.5",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"licenses": [
|
|
@@ -10,16 +10,15 @@
|
|
|
10
10
|
}
|
|
11
11
|
],
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@nocobase/actions": "0.7.
|
|
14
|
-
"@nocobase/database": "0.7.
|
|
15
|
-
"@nocobase/server": "0.7.
|
|
16
|
-
"@nocobase/utils": "0.7.
|
|
13
|
+
"@nocobase/actions": "0.7.1-alpha.5",
|
|
14
|
+
"@nocobase/database": "0.7.1-alpha.5",
|
|
15
|
+
"@nocobase/server": "0.7.1-alpha.5",
|
|
16
|
+
"@nocobase/utils": "0.7.1-alpha.5",
|
|
17
17
|
"cron-parser": "4.4.0",
|
|
18
|
-
"json-templates": "^4.2.0"
|
|
19
|
-
"lodash": "^4.17.21"
|
|
18
|
+
"json-templates": "^4.2.0"
|
|
20
19
|
},
|
|
21
20
|
"devDependencies": {
|
|
22
|
-
"@nocobase/test": "0.7.
|
|
21
|
+
"@nocobase/test": "0.7.1-alpha.5"
|
|
23
22
|
},
|
|
24
|
-
"gitHead": "
|
|
23
|
+
"gitHead": "c9159c6cf4b7deb80e87122d4b7967a510b8ae7c"
|
|
25
24
|
}
|
package/lib/server.d.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { Plugin } from '@nocobase/server';
|
|
2
|
-
import WorkflowModel from './models/Workflow';
|
|
3
|
-
import { Trigger } from './triggers';
|
|
4
|
-
import { Registry } from '@nocobase/utils';
|
|
5
|
-
export default class extends Plugin {
|
|
6
|
-
triggers: Registry<Trigger>;
|
|
7
|
-
getName(): string;
|
|
8
|
-
load(options?: {}): Promise<void>;
|
|
9
|
-
toggle(workflow: WorkflowModel, enable?: boolean): void;
|
|
10
|
-
}
|