@izara_project/izara-core-library-asynchronous-flow 1.0.47 → 1.0.48

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 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.47",
6
+ "version": "1.0.48",
7
7
  "description": "Shared asynchronous flow logic",
8
8
  "type": "module",
9
9
  "main": "index.js",
@@ -16,8 +16,8 @@
16
16
  },
17
17
  "devDependencies": {
18
18
  "@izara_project/izara-core-library-core": "^1.0.32",
19
- "@izara_project/izara-core-library-dynamodb": "^1.0.21",
20
- "@izara_project/izara-core-library-external-request": "^1.0.30",
19
+ "@izara_project/izara-core-library-dynamodb": "^1.0.22",
20
+ "@izara_project/izara-core-library-external-request": "^1.0.32",
21
21
  "@izara_project/izara-core-library-logger": "^1.0.11",
22
22
  "@izara_project/izara-core-library-sns": "^1.0.8",
23
23
  "@izara_project/izara-core-library-sqs": "^1.0.7",
@@ -168,7 +168,7 @@ export async function createAwaitingMultipleSteps(
168
168
 
169
169
  return {
170
170
  awaitingStepId,
171
- additionalAttributes,
171
+ additionalAttributes: record.additionalAttributes,
172
172
  message: {
173
173
  ...record.message,
174
174
  parentFlowId: awaitingStepId
@@ -194,10 +194,7 @@ export async function createAwaitingMultipleSteps(
194
194
  }
195
195
 
196
196
  return {
197
- awaitingStepId: createAwaitingStepId(
198
- awaitingStepId,
199
- prefix
200
- ),
197
+ awaitingStepId: createAwaitingStepId(awaitingStepId, prefix),
201
198
  additionalAttributes: mergedAttributes
202
199
  };
203
200
  }
@@ -373,6 +370,17 @@ export async function checkAllAwaitingStepsFinishedWithReturnParams(
373
370
  _assertPendingStepId(pendingStepId);
374
371
 
375
372
  if (currentAwaitingStepId) {
373
+ _izContext.logger.debug(
374
+ '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] Updating awaitingStepItem in DB',
375
+ {
376
+ pendingStepId,
377
+ awaitingStepId: currentAwaitingStepId,
378
+ complete: true,
379
+ errorsFound,
380
+ returnValues
381
+ }
382
+ );
383
+
376
384
  await dynamodbSharedLib.updateItem(
377
385
  _izContext,
378
386
  dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleStepByPending'),
@@ -386,6 +394,16 @@ export async function checkAllAwaitingStepsFinishedWithReturnParams(
386
394
  returnValues
387
395
  }
388
396
  );
397
+
398
+ _izContext.logger.debug(
399
+ '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] After updating awaitingStepItems',
400
+ {
401
+ pendingStepId,
402
+ awaitingStepId: currentAwaitingStepId,
403
+ errorsFound,
404
+ returnValues
405
+ }
406
+ );
389
407
  }
390
408
 
391
409
  const awaitingStepItems = await _queryAwaitingStepsByPendingStepId(
@@ -394,10 +412,30 @@ export async function checkAllAwaitingStepsFinishedWithReturnParams(
394
412
  );
395
413
 
396
414
  _izContext.logger.debug(
397
- '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] awaitingStepItems',
398
- { awaitingStepItems }
415
+ '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] Queried awaitingStepItems',
416
+ {
417
+ pendingStepId,
418
+ itemsCount: awaitingStepItems ? awaitingStepItems.length : 0,
419
+ awaitingStepItems
420
+ }
399
421
  );
400
422
 
423
+ if (!awaitingStepItems || awaitingStepItems.length === 0) {
424
+ _izContext.logger.warn(
425
+ '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] No awaiting steps found for pendingStepId',
426
+ { pendingStepId, currentAwaitingStepId }
427
+ );
428
+ return {
429
+ isComplete: false,
430
+ collectedReturnValueByAwaitingStepId: null,
431
+ collectedErrors: [
432
+ `No awaiting steps found for pendingStepId: ${pendingStepId}`
433
+ ],
434
+ returnValues: null,
435
+ additionalAttributes: null
436
+ };
437
+ }
438
+
401
439
  const hasIncomplete = awaitingStepItems.some(
402
440
  item => item.awaitingStepId !== currentAwaitingStepId && !item.complete
403
441
  );
@@ -407,7 +445,64 @@ export async function checkAllAwaitingStepsFinishedWithReturnParams(
407
445
  defaultAttrs = awaitingStepItems[0].additionalAttributes;
408
446
  }
409
447
 
448
+ _izContext.logger.debug(
449
+ '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] Completion check status',
450
+ {
451
+ pendingStepId,
452
+ currentAwaitingStepId,
453
+ hasIncomplete,
454
+ defaultAttrs
455
+ }
456
+ );
457
+
410
458
  if (hasIncomplete) {
459
+ _izContext.logger.debug(
460
+ '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] Incomplete steps remaining',
461
+ {
462
+ pendingStepId,
463
+ incompleteSteps: awaitingStepItems
464
+ .filter(
465
+ item =>
466
+ item.awaitingStepId !== currentAwaitingStepId && !item.complete
467
+ )
468
+ .map(item => item.awaitingStepId)
469
+ }
470
+ );
471
+ return {
472
+ isComplete: false,
473
+ collectedReturnValueByAwaitingStepId: null,
474
+ collectedErrors: [],
475
+ returnValues: null,
476
+ additionalAttributes: defaultAttrs
477
+ };
478
+ }
479
+
480
+ // ── Atomic completion claim to prevent concurrent duplicate execution ─────
481
+ const primaryStep = awaitingStepItems[0];
482
+ try {
483
+ await dynamodbSharedLib.updateItem(
484
+ _izContext,
485
+ dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleStepByPending'),
486
+ {
487
+ pendingStepId,
488
+ awaitingStepId: primaryStep.awaitingStepId
489
+ },
490
+ { isFinalized: true },
491
+ {
492
+ conditionExpression: 'attribute_not_exists(isFinalized)'
493
+ },
494
+ {
495
+ errorOnConditionalExpNotPass: true
496
+ }
497
+ );
498
+ } catch (err) {
499
+ _izContext.logger.debug(
500
+ '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] Completion already claimed by another process',
501
+ {
502
+ pendingStepId,
503
+ error: err.message
504
+ }
505
+ );
411
506
  return {
412
507
  isComplete: false,
413
508
  collectedReturnValueByAwaitingStepId: null,
@@ -456,6 +551,14 @@ export async function checkAllAwaitingStepsFinishedWithReturnParams(
456
551
  );
457
552
  }
458
553
 
554
+ _izContext.logger.debug(
555
+ '[Lib:checkAllAwaitingStepsFinishedWithReturnParams] Completed. Returning result:',
556
+ {
557
+ pendingStepId,
558
+ result
559
+ }
560
+ );
561
+
459
562
  return result;
460
563
  }
461
564
 
@@ -526,7 +629,7 @@ export async function removeAwaitingMultipleStep(
526
629
  if (!awaitingStepId || !pendingStepId) {
527
630
  throw new NoRetryError(
528
631
  '[Lib:removeAwaitingMultipleStep]' +
529
- ' awaitingStepId or pendingStepId required'
632
+ ' awaitingStepId or pendingStepId required'
530
633
  );
531
634
  }
532
635
 
@@ -568,23 +671,19 @@ export async function completeAction(
568
671
  prefix = '',
569
672
  returnValue = {},
570
673
  errorsFound = []
571
- ){
572
- _izContext.logger.debug('[Lib:CompleteAction] Input parameters', {
573
- parentFlowId,
574
- prefix
674
+ ) {
675
+ _izContext.logger.debug('[Lib:CompleteAction] Input parameters', {
676
+ parentFlowId,
677
+ prefix
575
678
  });
576
679
 
577
680
  try {
578
-
579
681
  const { pendingStepId } = await findPendingStepAwaitingMultipleSteps(
580
682
  _izContext,
581
- createAwaitingStepId(
582
- parentFlowId,
583
- prefix
584
- )
683
+ createAwaitingStepId(parentFlowId, prefix)
585
684
  );
586
685
 
587
- if (!pendingStepId) {
686
+ if (!pendingStepId) {
588
687
  _izContext.logger.warn(
589
688
  `No pending step found for awaitingStepId: ${awaitingStepId}`
590
689
  );
@@ -600,29 +699,26 @@ export async function completeAction(
600
699
  } = await checkAllAwaitingStepsFinishedWithReturnParams(
601
700
  _izContext,
602
701
  pendingStepId,
603
- createAwaitingStepId(
604
- parentFlowId,
605
- prefix
606
- )
702
+ createAwaitingStepId(parentFlowId, prefix)
607
703
  );
608
704
 
609
705
  let status = true;
610
706
 
611
707
  if (!isComplete) {
612
- status = false
613
- };
708
+ status = false;
709
+ }
614
710
 
615
711
  if (collectedErrors.length > 0 || errorsFound.length > 0) {
616
- status =false
617
- };
712
+ status = false;
713
+ }
618
714
 
619
715
  if (status) {
620
- await Promise.all(
621
- (pendingStepId.listOfRecords ?? []).flatMap((records) =>
622
- Object.values(records).map(async (record) =>
623
- dynamodbSharedLib.putItem(
624
- _izContext,
625
- await dynamodbSharedLib.tableName(
716
+ await Promise.all(
717
+ (pendingStepId.listOfRecords ?? []).flatMap(records =>
718
+ Object.values(records).map(async record =>
719
+ dynamodbSharedLib.putItem(
720
+ _izContext,
721
+ await dynamodbSharedLib.tableName(
626
722
  _izContext,
627
723
  record.tableName,
628
724
  record.serviceTag
@@ -644,9 +740,8 @@ export async function completeAction(
644
740
  collectedErrors,
645
741
  returnValues,
646
742
  additionalAttributes
647
- }
648
-
743
+ };
649
744
  } catch (err) {
650
- _izContext.logger.error(err)
745
+ _izContext.logger.error(err);
651
746
  }
652
- }
747
+ }