@izara_project/izara-core-library-asynchronous-flow 1.0.27 → 1.0.29
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 +4 -2
- package/src/awaitingMultipleSteps.js +121 -40
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"author": "Sven Mason <thebarbariansven@gmail.com>",
|
|
4
4
|
"license": "AGPL-3.0-or-later",
|
|
5
5
|
"homepage": "https://bitbucket.org/izara-core-libraries/izara-core-library-asynchronous-flow#readme",
|
|
6
|
-
"version": "1.0.
|
|
6
|
+
"version": "1.0.29",
|
|
7
7
|
"description": "Shared asynchronous flow logic",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"main": "index.js",
|
|
@@ -31,5 +31,7 @@
|
|
|
31
31
|
"@izara_project/izara-core-library-sqs": "^1.0.7"
|
|
32
32
|
},
|
|
33
33
|
"peerDependenciesMeta": {},
|
|
34
|
-
"dependencies": {
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@izara_project/izara-shared-core": "^1.0.12"
|
|
36
|
+
}
|
|
35
37
|
}
|
|
@@ -18,6 +18,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
18
18
|
import { NoRetryError } from '@izara_project/izara-core-library-core';
|
|
19
19
|
import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
|
|
20
20
|
|
|
21
|
+
import { identifierUuid } from '@izara_project/izara-shared-core';
|
|
22
|
+
|
|
21
23
|
//====================================== AwaitingMultipleSteps
|
|
22
24
|
// AwaitingMultipleSteps is when a flow is awaiting multiple external flows before it can continue
|
|
23
25
|
// One awaitingStepId can have multiple pendingStepIds that are awaiting it
|
|
@@ -192,6 +194,73 @@ export async function createAwaitingMultipleSteps(
|
|
|
192
194
|
await Promise.all(promiseArray);
|
|
193
195
|
}
|
|
194
196
|
|
|
197
|
+
/**
|
|
198
|
+
* Create new awaiting multiple steps for a pending step.
|
|
199
|
+
* @async
|
|
200
|
+
* @param {IzContext} _izContext
|
|
201
|
+
* @param {string} pendingStepId
|
|
202
|
+
* @param {number} countAwaitingMultipleSteps
|
|
203
|
+
* @param {Object.<string, any>} [additionalAttributes={}] - Shared attributes stored for every step in AwaitingMultipleStepByPending.
|
|
204
|
+
* The same object is applied to all steps (caller cannot know the generated UUIDs beforehand).
|
|
205
|
+
* @returns {Promise<string[]>} The list of awaiting step IDs created.
|
|
206
|
+
*/
|
|
207
|
+
export async function createNewAwaitingMultipleSteps(
|
|
208
|
+
_izContext,
|
|
209
|
+
pendingStepId,
|
|
210
|
+
countAwaitingMultipleSteps,
|
|
211
|
+
additionalAttributes = {}
|
|
212
|
+
) {
|
|
213
|
+
_izContext.logger.debug('[Lib:AsyncFlow:createNewAwaitingMultipleSteps] Input: ', {
|
|
214
|
+
pendingStepId,
|
|
215
|
+
countAwaitingMultipleSteps,
|
|
216
|
+
additionalAttributes
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
const awaitingStepIds = Array.from({ length: countAwaitingMultipleSteps }, () => identifierUuid());
|
|
220
|
+
|
|
221
|
+
const promiseArray = [];
|
|
222
|
+
|
|
223
|
+
for (const awaitingStepId of awaitingStepIds) {
|
|
224
|
+
const attributesWhenCreate = {
|
|
225
|
+
awaitingStepId: awaitingStepId,
|
|
226
|
+
pendingStepId: pendingStepId,
|
|
227
|
+
complete: false,
|
|
228
|
+
errorsFound: [],
|
|
229
|
+
};
|
|
230
|
+
promiseArray.push(
|
|
231
|
+
dynamodbSharedLib.putItem(
|
|
232
|
+
_izContext,
|
|
233
|
+
dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleSteps'),
|
|
234
|
+
attributesWhenCreate
|
|
235
|
+
)
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
const attributesForPending = {
|
|
239
|
+
...attributesWhenCreate,
|
|
240
|
+
additionalAttributes: additionalAttributes
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
promiseArray.push(
|
|
244
|
+
dynamodbSharedLib.putItem(
|
|
245
|
+
_izContext,
|
|
246
|
+
dynamodbSharedLib.tableName(
|
|
247
|
+
_izContext,
|
|
248
|
+
'AwaitingMultipleStepByPending'
|
|
249
|
+
),
|
|
250
|
+
attributesForPending
|
|
251
|
+
)
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
_izContext.logger.debug('putItem:AwaitingMultipleStepByPending', {
|
|
255
|
+
awaitingStepId: attributesWhenCreate.awaitingStepId
|
|
256
|
+
});
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
await Promise.all(promiseArray);
|
|
260
|
+
|
|
261
|
+
return awaitingStepIds;
|
|
262
|
+
}
|
|
263
|
+
|
|
195
264
|
/**
|
|
196
265
|
* Find all pendingStepIds that are waiting on a given awaitingStepId (multiple).
|
|
197
266
|
* @async
|
|
@@ -348,56 +417,46 @@ export async function checkAllAwaitingStepsFinished(
|
|
|
348
417
|
errorsFound = [],
|
|
349
418
|
additionalAttributes = {}
|
|
350
419
|
) {
|
|
351
|
-
|
|
352
420
|
await checkAllAwaitingStepsFinishedShared(
|
|
353
421
|
_izContext,
|
|
354
422
|
pendingStepId,
|
|
355
|
-
currentAwaitingStepId
|
|
356
|
-
errorsFound
|
|
357
|
-
additionalAttributes
|
|
423
|
+
currentAwaitingStepId,
|
|
424
|
+
errorsFound,
|
|
425
|
+
additionalAttributes
|
|
358
426
|
);
|
|
359
427
|
|
|
360
|
-
|
|
428
|
+
const items = await dynamodbSharedLib.query(
|
|
361
429
|
_izContext,
|
|
362
430
|
dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleStepByPending'),
|
|
363
|
-
{
|
|
364
|
-
|
|
365
|
-
},
|
|
366
|
-
{
|
|
367
|
-
limit: 50 // arbitrary limit so not pull too many results, need >2 because some others might be marked as "complete" = true
|
|
368
|
-
}
|
|
431
|
+
{ pendingStepId },
|
|
432
|
+
{ limit: 50 }
|
|
369
433
|
);
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
if (
|
|
375
|
-
currentAwaitingStepId &&
|
|
376
|
-
listPendingStepIds.Items[idx].awaitingStepId == currentAwaitingStepId
|
|
377
|
-
) {
|
|
378
|
-
continue;
|
|
379
|
-
}
|
|
380
|
-
// if any record found not set to complete then there are steps not yet finished
|
|
381
|
-
if (!listPendingStepIds.Items[idx].complete) {
|
|
382
|
-
return false;
|
|
383
|
-
}
|
|
434
|
+
|
|
435
|
+
for (const item of items.Items) {
|
|
436
|
+
if (item.awaitingStepId === currentAwaitingStepId) continue;
|
|
437
|
+
if (!item.complete) return false;
|
|
384
438
|
}
|
|
385
439
|
|
|
386
|
-
return true;
|
|
440
|
+
return true;
|
|
387
441
|
}
|
|
388
442
|
|
|
389
443
|
|
|
390
444
|
/**
|
|
391
445
|
* Checks if all awaiting steps for a pending step are complete after marking the current one as complete.
|
|
392
|
-
* If all steps are finished,
|
|
393
|
-
* If any other step is not yet complete,
|
|
446
|
+
* If all steps are finished, returns an object with `isComplete: true` and the collected data.
|
|
447
|
+
* If any other step is not yet complete, returns `isComplete: false` with null data.
|
|
394
448
|
* @async
|
|
395
449
|
* @param {IzContext} _izContext
|
|
396
450
|
* @param {string} pendingStepId
|
|
397
451
|
* @param {string|null} [currentAwaitingStepId=null] - The step that has just finished.
|
|
398
452
|
* @param {any[]} [errorsFound=[]]
|
|
399
453
|
* @param {Attrs} [additionalAttributes={}]
|
|
400
|
-
* @returns {Promise<
|
|
454
|
+
* @returns {Promise<{
|
|
455
|
+
* isComplete: boolean,
|
|
456
|
+
* collectedAttributes: Record<string, any>|null,
|
|
457
|
+
* collectedErrors: any[],
|
|
458
|
+
* sharedAdditionalAttributes: any|null
|
|
459
|
+
* }>}
|
|
401
460
|
*/
|
|
402
461
|
export async function checkAllAwaitingStepsFinishedWithReturnParams(
|
|
403
462
|
_izContext,
|
|
@@ -406,44 +465,66 @@ export async function checkAllAwaitingStepsFinishedWithReturnParams(
|
|
|
406
465
|
errorsFound = [],
|
|
407
466
|
additionalAttributes = {}
|
|
408
467
|
) {
|
|
468
|
+
_izContext.logger.debug('Lib:checkAllAwaitingStepsFinishedWithReturnParams', {
|
|
469
|
+
pendingStepId,
|
|
470
|
+
currentAwaitingStepId,
|
|
471
|
+
errorsFound,
|
|
472
|
+
additionalAttributes
|
|
473
|
+
});
|
|
409
474
|
|
|
410
475
|
await checkAllAwaitingStepsFinishedShared(
|
|
411
476
|
_izContext,
|
|
412
477
|
pendingStepId,
|
|
413
|
-
currentAwaitingStepId
|
|
414
|
-
errorsFound
|
|
415
|
-
additionalAttributes
|
|
478
|
+
currentAwaitingStepId,
|
|
479
|
+
errorsFound,
|
|
480
|
+
additionalAttributes
|
|
416
481
|
);
|
|
417
482
|
|
|
418
483
|
const awaitingStepItems = await dynamodbSharedLib.query(
|
|
419
484
|
_izContext,
|
|
420
485
|
dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleStepByPending'),
|
|
421
486
|
{ pendingStepId },
|
|
422
|
-
{
|
|
423
|
-
limit: 50
|
|
424
|
-
}
|
|
487
|
+
{ limit: 50 }
|
|
425
488
|
);
|
|
426
489
|
|
|
427
490
|
_izContext.logger.debug('awaitingStepItems:::', awaitingStepItems);
|
|
428
491
|
|
|
429
|
-
|
|
430
|
-
const collectedErrors = [];
|
|
431
|
-
|
|
492
|
+
// Pass 1: check completeness of all other steps before collecting any data
|
|
432
493
|
for (const item of awaitingStepItems.Items) {
|
|
433
494
|
if (item.awaitingStepId !== currentAwaitingStepId && !item.complete) {
|
|
434
|
-
return
|
|
495
|
+
return {
|
|
496
|
+
isComplete: false,
|
|
497
|
+
collectedAttributes: null,
|
|
498
|
+
collectedErrors: [],
|
|
499
|
+
sharedAdditionalAttributes: null
|
|
500
|
+
};
|
|
435
501
|
}
|
|
502
|
+
}
|
|
436
503
|
|
|
504
|
+
// Pass 2: all steps are complete — collect errors and attributes
|
|
505
|
+
const collectedAttributes = {};
|
|
506
|
+
const collectedErrors = [];
|
|
507
|
+
let sharedAdditionalAttributes = null;
|
|
508
|
+
|
|
509
|
+
for (const item of awaitingStepItems.Items) {
|
|
437
510
|
if (item.errorsFound?.length > 0) {
|
|
438
511
|
collectedErrors.push(...item.errorsFound);
|
|
439
512
|
}
|
|
440
513
|
|
|
441
514
|
if (item.additionalAttributes) {
|
|
442
515
|
collectedAttributes[item.awaitingStepId] = item.additionalAttributes;
|
|
516
|
+
if (sharedAdditionalAttributes === null) {
|
|
517
|
+
sharedAdditionalAttributes = item.additionalAttributes;
|
|
518
|
+
}
|
|
443
519
|
}
|
|
444
520
|
}
|
|
445
521
|
|
|
446
|
-
return
|
|
522
|
+
return {
|
|
523
|
+
isComplete: true,
|
|
524
|
+
collectedAttributes,
|
|
525
|
+
collectedErrors,
|
|
526
|
+
sharedAdditionalAttributes
|
|
527
|
+
};
|
|
447
528
|
}
|
|
448
529
|
|
|
449
530
|
|