codehooks-js 1.3.3 → 1.3.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/package.json +1 -1
- package/workflow/engine.mjs +67 -50
package/package.json
CHANGED
package/workflow/engine.mjs
CHANGED
|
@@ -141,54 +141,68 @@ class StepsEngine extends EventEmitter {
|
|
|
141
141
|
|
|
142
142
|
StepsEngine.getInstance().emit('stateUpdated', { workflowName: stepsName, state: newState, instanceId });
|
|
143
143
|
|
|
144
|
-
// If there is no next step, the workflow is completed
|
|
145
|
-
if (nextStep === null) {
|
|
146
|
-
console.log('No next step, steps workflow completed');
|
|
147
|
-
StepsEngine.getInstance().emit('completed', { message: 'Steps workflow completed', ...newState });
|
|
148
|
-
return;
|
|
149
|
-
}
|
|
150
144
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
145
|
+
|
|
146
|
+
|
|
154
147
|
try {
|
|
155
|
-
//
|
|
156
|
-
func
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
148
|
+
// Get the next step function
|
|
149
|
+
const func = StepsEngine.getInstance().getDefinition(stepsName, nextStep);
|
|
150
|
+
|
|
151
|
+
// Wrap the callback in a Promise to ensure proper async handling
|
|
152
|
+
await new Promise((resolve, reject) => {
|
|
153
|
+
func({...newState, instanceId: newState._id}, async (nextStep, userState, options) => {
|
|
154
|
+
try {
|
|
155
|
+
// Protect system-level properties
|
|
156
|
+
const protectedState = {
|
|
157
|
+
_id: newState._id,
|
|
158
|
+
nextStep: newState.nextStep,
|
|
159
|
+
createdAt: newState.createdAt,
|
|
160
|
+
updatedAt: newState.updatedAt,
|
|
161
|
+
instanceId: newState.instanceId,
|
|
162
|
+
workflowName: newState.workflowName
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
// Merge states with userState taking precedence, but protecting system fields
|
|
166
|
+
const mergedState = {
|
|
167
|
+
...userState,
|
|
168
|
+
...protectedState
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
// If there is no next step, the workflow is completed
|
|
172
|
+
if (nextStep === null) {
|
|
173
|
+
delete mergedState._id;
|
|
174
|
+
const completionTime = (new Date(mergedState.updatedAt) - new Date(mergedState.createdAt)) / 1000;
|
|
175
|
+
|
|
176
|
+
const finalresult = await connection.updateOne(StepsEngine.collectionName,
|
|
177
|
+
{ _id: instanceId },
|
|
178
|
+
{ $set: { ...mergedState, nextStep: null, updatedAt: new Date().toISOString() } });
|
|
179
|
+
console.log(`Workflow ${stepsName} ${instanceId} is completed in time: ${completionTime}s 🎉`);
|
|
180
|
+
StepsEngine.getInstance().emit('completed', { ...finalresult});
|
|
181
|
+
resolve();
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
174
184
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
stepsName
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
185
|
+
// Enqueue the next step
|
|
186
|
+
console.debug('enqueuing step', nextStep, instanceId);
|
|
187
|
+
await connection.enqueue(`${StepsEngine.queuePrefix}_${stepsName}_${nextStep}`, {
|
|
188
|
+
stepsName: stepsName,
|
|
189
|
+
goto: nextStep,
|
|
190
|
+
state: mergedState,
|
|
191
|
+
options: options,
|
|
192
|
+
instanceId: instanceId
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
StepsEngine.getInstance().emit('stepEnqueued', { workflowName: stepsName, step: nextStep, state: newState, instanceId });
|
|
196
|
+
resolve();
|
|
197
|
+
} catch (error) {
|
|
198
|
+
console.error('error', error.message);
|
|
199
|
+
reject(error);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
189
202
|
});
|
|
190
203
|
} catch (error) {
|
|
191
204
|
console.error('Error in step function: '+nextStep, error.message);
|
|
205
|
+
StepsEngine.getInstance().emit('error', { workflowName: stepsName, step: nextStep, state: newState, instanceId, error: error.message });
|
|
192
206
|
const connection = await Datastore.open();
|
|
193
207
|
await connection.updateOne(StepsEngine.collectionName,
|
|
194
208
|
{ _id: instanceId },
|
|
@@ -216,10 +230,13 @@ class StepsEngine extends EventEmitter {
|
|
|
216
230
|
// Validate each step in the definition
|
|
217
231
|
for (const [stepName, step] of Object.entries(definition)) {
|
|
218
232
|
try {
|
|
219
|
-
if (stepName !==
|
|
220
|
-
|
|
221
|
-
|
|
233
|
+
if (stepName !== undefined) {
|
|
234
|
+
//console.log('registering queue for step', `${StepsEngine.queuePrefix}_${name}_${stepName}`);
|
|
235
|
+
app.worker(`${StepsEngine.queuePrefix}_${name}_${stepName}`, async function(req, res) {
|
|
222
236
|
try {
|
|
237
|
+
|
|
238
|
+
const { stepsName, goto, state, instanceId, options } = req.body.payload;
|
|
239
|
+
console.debug('worker job', stepName, instanceId);
|
|
223
240
|
const qid = await StepsEngine.getInstance().handleNextStep(stepsName, goto, state, instanceId, options);
|
|
224
241
|
} catch (error) {
|
|
225
242
|
console.error('Error in step function: ' + stepName, error.message);
|
|
@@ -260,8 +277,8 @@ class StepsEngine extends EventEmitter {
|
|
|
260
277
|
const connection = await Datastore.open();
|
|
261
278
|
// Create a new steps state in the database
|
|
262
279
|
const newState = await connection.insertOne(StepsEngine.collectionName,
|
|
263
|
-
{ ...initialState, nextStep: firstStepName, createdAt: new Date().toISOString() });
|
|
264
|
-
const { _id: ID } = await connection.enqueue(`${StepsEngine.queuePrefix}_${name}`, {
|
|
280
|
+
{ ...initialState, nextStep: firstStepName, createdAt: new Date().toISOString(), workflowName: name });
|
|
281
|
+
const { _id: ID } = await connection.enqueue(`${StepsEngine.queuePrefix}_${name}_${firstStepName}`, {
|
|
265
282
|
stepsName: name,
|
|
266
283
|
goto: firstStepName,
|
|
267
284
|
state: newState,
|
|
@@ -323,11 +340,11 @@ class StepsEngine extends EventEmitter {
|
|
|
323
340
|
throw new Error(`No steps found with instanceId: ${instanceId}`);
|
|
324
341
|
}
|
|
325
342
|
|
|
326
|
-
console.
|
|
343
|
+
console.debug('continue state', state);
|
|
327
344
|
StepsEngine.getInstance().emit('workflowContinued', { stepsName, step: state.nextStep, instanceId });
|
|
328
345
|
|
|
329
346
|
return new Promise(async (resolve, reject) => {
|
|
330
|
-
const { _id: ID } = await connection.enqueue(`${StepsEngine.queuePrefix}`, {
|
|
347
|
+
const { _id: ID } = await connection.enqueue(`${StepsEngine.queuePrefix}_${stepsName}_${state.nextStep}`, {
|
|
331
348
|
stepsName,
|
|
332
349
|
goto: state.nextStep,
|
|
333
350
|
state: state,
|
|
@@ -361,7 +378,7 @@ class StepsEngine extends EventEmitter {
|
|
|
361
378
|
return new Promise(async (resolve, reject) => {
|
|
362
379
|
const connection = await Datastore.open();
|
|
363
380
|
const states = await connection.find(StepsEngine.collectionName, filter).toArray();
|
|
364
|
-
console.
|
|
381
|
+
console.debug('listSteps', StepsEngine.collectionName, filter, states.length);
|
|
365
382
|
resolve(states);
|
|
366
383
|
});
|
|
367
384
|
}
|