@izara_project/izara-core-library-asynchronous-flow 1.0.30 → 1.0.32
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/index.js +85 -8
- package/package.json +5 -5
- package/src/asyncFlowSharedLib.js +16 -4
- package/src/awaitingMultipleSteps.js +84 -48
package/index.js
CHANGED
|
@@ -15,14 +15,91 @@ You should have received a copy of the GNU Affero General Public License
|
|
|
15
15
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
import {
|
|
19
|
+
createFieldNameUniqueRequestId,
|
|
20
|
+
createConcatenatedAwaitingStepId,
|
|
21
|
+
createConcatenatedPendingStepId,
|
|
22
|
+
createAwaitingStepId,
|
|
23
|
+
createPendingStepId,
|
|
24
|
+
createParentFlowId,
|
|
25
|
+
explodePendingStepId,
|
|
26
|
+
createFieldNameCacheComplete,
|
|
27
|
+
createFieldNameStatus,
|
|
28
|
+
checkUniqueRequestProcessing,
|
|
29
|
+
checkTimeCacheComplete,
|
|
30
|
+
checkAndGetTimeCacheComplete,
|
|
31
|
+
checkCacheUniqueRequestId,
|
|
32
|
+
validateStartKeyParam,
|
|
33
|
+
validateMultipleInvocations
|
|
34
|
+
} from './src/asyncFlowSharedLib.js';
|
|
35
|
+
|
|
36
|
+
import {
|
|
37
|
+
createAwaitingStep,
|
|
38
|
+
findPendingStepIdsAwaitingStep,
|
|
39
|
+
findPendingStepsAwaitingStep,
|
|
40
|
+
findPendingStepAwaitingStep,
|
|
41
|
+
findPendingStepAwaitingStepWithCallingFlow,
|
|
42
|
+
removeAwaitingStep,
|
|
43
|
+
removeAwaitingStepWithCheckUniqueRequestId
|
|
44
|
+
} from './src/awaitingStep.js';
|
|
45
|
+
|
|
46
|
+
import {
|
|
47
|
+
createAwaitingMultipleStepsWithAdditionalAttributes,
|
|
48
|
+
initAwaitingStepsWithAttrs,
|
|
49
|
+
createAwaitingMultipleSteps,
|
|
50
|
+
createNewAwaitingMultipleStep,
|
|
51
|
+
findPendingStepIdsAwaitingMultipleSteps,
|
|
52
|
+
findPendingStepsAwaitingMultipleSteps,
|
|
53
|
+
findPendingStepAwaitingMultipleSteps,
|
|
54
|
+
findAwaitingMultipleStepByPending,
|
|
55
|
+
checkAllAwaitingStepsFinishedShared,
|
|
56
|
+
checkAllAwaitingStepsFinished,
|
|
57
|
+
checkAllAwaitingStepsFinishedWithReturnParams,
|
|
58
|
+
clearAllAwaitingSteps,
|
|
59
|
+
removeAwaitingMultipleStep,
|
|
60
|
+
createAwaitingMultipleStepsWithAdditionalAttributesAndPublish
|
|
61
|
+
} from './src/awaitingMultipleSteps.js';
|
|
22
62
|
|
|
23
|
-
// Combine all functions from the imported modules into a single export object.
|
|
24
63
|
export default {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
64
|
+
// asyncFlowSharedLib
|
|
65
|
+
createFieldNameUniqueRequestId,
|
|
66
|
+
createConcatenatedAwaitingStepId,
|
|
67
|
+
createConcatenatedPendingStepId,
|
|
68
|
+
createAwaitingStepId,
|
|
69
|
+
createPendingStepId,
|
|
70
|
+
createParentFlowId,
|
|
71
|
+
explodePendingStepId,
|
|
72
|
+
createFieldNameCacheComplete,
|
|
73
|
+
createFieldNameStatus,
|
|
74
|
+
checkUniqueRequestProcessing,
|
|
75
|
+
checkTimeCacheComplete,
|
|
76
|
+
checkAndGetTimeCacheComplete,
|
|
77
|
+
checkCacheUniqueRequestId,
|
|
78
|
+
validateStartKeyParam,
|
|
79
|
+
validateMultipleInvocations,
|
|
80
|
+
|
|
81
|
+
// awaitingStep
|
|
82
|
+
createAwaitingStep,
|
|
83
|
+
findPendingStepIdsAwaitingStep,
|
|
84
|
+
findPendingStepsAwaitingStep,
|
|
85
|
+
findPendingStepAwaitingStep,
|
|
86
|
+
findPendingStepAwaitingStepWithCallingFlow,
|
|
87
|
+
removeAwaitingStep,
|
|
88
|
+
removeAwaitingStepWithCheckUniqueRequestId,
|
|
89
|
+
|
|
90
|
+
// awaitingMultipleSteps
|
|
91
|
+
createAwaitingMultipleStepsWithAdditionalAttributes,
|
|
92
|
+
initAwaitingStepsWithAttrs,
|
|
93
|
+
createAwaitingMultipleSteps,
|
|
94
|
+
createNewAwaitingMultipleStep,
|
|
95
|
+
findPendingStepIdsAwaitingMultipleSteps,
|
|
96
|
+
findPendingStepsAwaitingMultipleSteps,
|
|
97
|
+
findPendingStepAwaitingMultipleSteps,
|
|
98
|
+
findAwaitingMultipleStepByPending,
|
|
99
|
+
checkAllAwaitingStepsFinishedShared,
|
|
100
|
+
checkAllAwaitingStepsFinished,
|
|
101
|
+
checkAllAwaitingStepsFinishedWithReturnParams,
|
|
102
|
+
clearAllAwaitingSteps,
|
|
103
|
+
removeAwaitingMultipleStep,
|
|
104
|
+
createAwaitingMultipleStepsWithAdditionalAttributesAndPublish
|
|
28
105
|
};
|
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.32",
|
|
7
7
|
"description": "Shared asynchronous flow logic",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"main": "index.js",
|
|
@@ -28,10 +28,10 @@
|
|
|
28
28
|
"@izara_project/izara-core-library-dynamodb": "^1.0.19",
|
|
29
29
|
"@izara_project/izara-core-library-external-request": "^1.0.30",
|
|
30
30
|
"@izara_project/izara-core-library-logger": "^1.0.9",
|
|
31
|
-
"@izara_project/izara-core-library-sqs": "^1.0.7"
|
|
31
|
+
"@izara_project/izara-core-library-sqs": "^1.0.7",
|
|
32
|
+
"@izara_project/izara-core-library-sns": "^1.0.8",
|
|
33
|
+
"@izara_project/izara-shared-core": "^1.0.12"
|
|
32
34
|
},
|
|
33
35
|
"peerDependenciesMeta": {},
|
|
34
|
-
"dependencies": {
|
|
35
|
-
"@izara_project/izara-shared-core": "^1.0.12"
|
|
36
|
-
}
|
|
36
|
+
"dependencies": {}
|
|
37
37
|
}
|
|
@@ -26,6 +26,8 @@ import sqsSharedLib from '@izara_project/izara-core-library-sqs';
|
|
|
26
26
|
// External service interactions
|
|
27
27
|
import { sqs } from '@izara_project/izara-core-library-external-request';
|
|
28
28
|
|
|
29
|
+
import { identifierUuid } from '@izara_project/izara-shared-core';
|
|
30
|
+
|
|
29
31
|
/**
|
|
30
32
|
* Create a field name for storing the unique-request id, with optional prefix.
|
|
31
33
|
* @param {string} prefix
|
|
@@ -84,6 +86,16 @@ export function createPendingStepId(identifierId, prefix = '') {
|
|
|
84
86
|
return prefix + identifierId;
|
|
85
87
|
}
|
|
86
88
|
|
|
89
|
+
/**
|
|
90
|
+
* Create parent Flow Id.
|
|
91
|
+
* @async
|
|
92
|
+
* @param {string} [prefix=''] - The prefix to prepend to the parent Ids.
|
|
93
|
+
* @returns {string} The parent Flow Id created.
|
|
94
|
+
*/
|
|
95
|
+
export function createParentFlowId(prefix = '') {
|
|
96
|
+
return (prefix ? `${prefix}_` : '') + identifierUuid.generate();
|
|
97
|
+
}
|
|
98
|
+
|
|
87
99
|
/**
|
|
88
100
|
* Remove the known prefix from a pendingStepId and validate it is not equal to the prefix.
|
|
89
101
|
* If prefix is empty, the original ID is returned.
|
|
@@ -183,7 +195,7 @@ export async function checkUniqueRequestProcessing(
|
|
|
183
195
|
uniqueRequestIdFieldName
|
|
184
196
|
);
|
|
185
197
|
|
|
186
|
-
//loop 3 times
|
|
198
|
+
//loop 3 times incas status changes, on 3rd iteration throw error (so checks 2 times)
|
|
187
199
|
for (let i = 1; i <= 3; i++) {
|
|
188
200
|
if (i == 3) {
|
|
189
201
|
throw new NoRetryError(
|
|
@@ -202,7 +214,7 @@ export async function checkUniqueRequestProcessing(
|
|
|
202
214
|
let returnStatus = 'process';
|
|
203
215
|
|
|
204
216
|
if (!existingRecord) {
|
|
205
|
-
// return ["recordNotFound", null]; // cannot return null, js cannot found object and throw error and
|
|
217
|
+
// return ["recordNotFound", null]; // cannot return null, js cannot found object and throw error and don't know where it is?
|
|
206
218
|
return ['recordNotFound', {}];
|
|
207
219
|
} else if (!existingRecord[uniqueRequestIdFieldName]) {
|
|
208
220
|
// uniqueRequestId not yet exist
|
|
@@ -267,7 +279,7 @@ export async function checkUniqueRequestProcessing(
|
|
|
267
279
|
}
|
|
268
280
|
}
|
|
269
281
|
|
|
270
|
-
// ----- Helper
|
|
282
|
+
// ----- Helper function, common use case in triggerFlow ---------
|
|
271
283
|
/**
|
|
272
284
|
* Convenience wrapper around checkAndGetTimeCacheComplete.
|
|
273
285
|
* Returns [isSameOrUnset, uniqueRequestIdWhenComplete].
|
|
@@ -497,7 +509,7 @@ export async function validateMultipleInvocations(
|
|
|
497
509
|
QueueUrl: await sqsSharedLib.sqsQueueUrl(_izContext, queueName)
|
|
498
510
|
};
|
|
499
511
|
_izContext.logger.debug(
|
|
500
|
-
`Send
|
|
512
|
+
`Send message to Dsq:${queueName} `,
|
|
501
513
|
messageReInvokeFunction
|
|
502
514
|
);
|
|
503
515
|
await sqs.sendMessage(_izContext, messageReInvokeFunction);
|
|
@@ -17,8 +17,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
17
17
|
|
|
18
18
|
import { NoRetryError } from '@izara_project/izara-core-library-core';
|
|
19
19
|
import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
|
|
20
|
+
import { sns } from '@izara_project/izara-core-library-external-request';
|
|
21
|
+
import snsSharedLib from '@izara_project/izara-core-library-sns';
|
|
20
22
|
|
|
21
|
-
import {
|
|
23
|
+
import { createParentFlowId } from './asyncFlowSharedLib.js';
|
|
22
24
|
|
|
23
25
|
//====================================== AwaitingMultipleSteps
|
|
24
26
|
// AwaitingMultipleSteps is when a flow is awaiting multiple external flows before it can continue
|
|
@@ -199,73 +201,52 @@ export async function createAwaitingMultipleSteps(
|
|
|
199
201
|
* @async
|
|
200
202
|
* @param {IzContext} _izContext
|
|
201
203
|
* @param {string} pendingStepId
|
|
202
|
-
* @param {
|
|
204
|
+
* @param {string[]} parendIds
|
|
203
205
|
* @param {Object.<string, any>} [additionalAttributes={}] - Shared attributes stored for every step in AwaitingMultipleStepByPending.
|
|
204
206
|
* The same object is applied to all steps (caller cannot know the generated UUIDs beforehand).
|
|
205
|
-
* @returns {Promise<string
|
|
207
|
+
* @returns {Promise<string>} The awaiting step ID created.
|
|
206
208
|
*/
|
|
207
|
-
export async function
|
|
209
|
+
export async function createNewAwaitingMultipleStep(
|
|
208
210
|
_izContext,
|
|
209
211
|
pendingStepId,
|
|
210
|
-
countAwaitingMultipleSteps,
|
|
211
212
|
prefix = '',
|
|
212
213
|
additionalAttributes = {}
|
|
213
214
|
) {
|
|
214
215
|
_izContext.logger.debug(
|
|
215
|
-
'[Lib:AsyncFlow:
|
|
216
|
+
'[Lib:AsyncFlow:createNewAwaitingMultipleStep] Input: ',
|
|
216
217
|
{
|
|
217
218
|
pendingStepId,
|
|
218
|
-
countAwaitingMultipleSteps,
|
|
219
219
|
additionalAttributes
|
|
220
220
|
}
|
|
221
221
|
);
|
|
222
222
|
|
|
223
|
-
const
|
|
224
|
-
{ length: countAwaitingMultipleSteps },
|
|
225
|
-
() => (prefix ? `${prefix}_` : '') + identifierUuid.generate()
|
|
226
|
-
);
|
|
227
|
-
|
|
228
|
-
const promiseArray = [];
|
|
223
|
+
const parentFlowId = createParentFlowId(prefix);
|
|
229
224
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
};
|
|
237
|
-
promiseArray.push(
|
|
238
|
-
dynamodbSharedLib.putItem(
|
|
239
|
-
_izContext,
|
|
240
|
-
dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleSteps'),
|
|
241
|
-
attributesWhenCreate
|
|
242
|
-
)
|
|
243
|
-
);
|
|
244
|
-
|
|
245
|
-
const attributesForPending = {
|
|
246
|
-
...attributesWhenCreate,
|
|
247
|
-
additionalAttributes: additionalAttributes
|
|
248
|
-
};
|
|
225
|
+
const attributesWhenCreate = {
|
|
226
|
+
awaitingStepId: parentFlowId,
|
|
227
|
+
pendingStepId: pendingStepId,
|
|
228
|
+
complete: false,
|
|
229
|
+
errorsFound: []
|
|
230
|
+
};
|
|
249
231
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
'AwaitingMultipleStepByPending'
|
|
256
|
-
),
|
|
257
|
-
attributesForPending
|
|
258
|
-
)
|
|
259
|
-
);
|
|
232
|
+
await dynamodbSharedLib.putItem(
|
|
233
|
+
_izContext,
|
|
234
|
+
dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleSteps'),
|
|
235
|
+
attributesWhenCreate
|
|
236
|
+
);
|
|
260
237
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
}
|
|
238
|
+
const attributesForPending = {
|
|
239
|
+
...attributesWhenCreate,
|
|
240
|
+
additionalAttributes: additionalAttributes
|
|
241
|
+
};
|
|
265
242
|
|
|
266
|
-
await
|
|
243
|
+
await dynamodbSharedLib.putItem(
|
|
244
|
+
_izContext,
|
|
245
|
+
dynamodbSharedLib.tableName(_izContext, 'AwaitingMultipleStepByPending'),
|
|
246
|
+
attributesForPending
|
|
247
|
+
);
|
|
267
248
|
|
|
268
|
-
return
|
|
249
|
+
return parentFlowId;
|
|
269
250
|
}
|
|
270
251
|
|
|
271
252
|
/**
|
|
@@ -653,3 +634,58 @@ export async function removeAwaitingMultipleStep(
|
|
|
653
634
|
}
|
|
654
635
|
await Promise.all(promiseArray);
|
|
655
636
|
}
|
|
637
|
+
|
|
638
|
+
export async function createAwaitingMultipleStepsWithAdditionalAttributesAndPublish(
|
|
639
|
+
_izContext,
|
|
640
|
+
messages,
|
|
641
|
+
flowType = {},
|
|
642
|
+
additionalAttributes = {},
|
|
643
|
+
pendingStepId
|
|
644
|
+
) {
|
|
645
|
+
if (!Array.isArray(messages)) {
|
|
646
|
+
throw new Error('messages must be an array');
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
const flowTag = flowType.flowTag;
|
|
650
|
+
const serviceTag = flowType.serviceTag;
|
|
651
|
+
|
|
652
|
+
if (flowTag === undefined || serviceTag === undefined) {
|
|
653
|
+
throw new Error('flowType must have both flowTag and serviceTag');
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
_izContext.logger.debug(
|
|
657
|
+
'Lib:createAwaitingMultipleStepsWithAdditionalAttributesAndPublish',
|
|
658
|
+
{ count: messages.length, pendingStepId, flowType }
|
|
659
|
+
);
|
|
660
|
+
|
|
661
|
+
const topicArn = snsSharedLib.snsTopicArn(
|
|
662
|
+
_izContext,
|
|
663
|
+
flowType.flowTag,
|
|
664
|
+
flowType.serviceTag ?? null
|
|
665
|
+
);
|
|
666
|
+
|
|
667
|
+
const messagesWithParentId = await Promise.all(
|
|
668
|
+
messages.map(async message => {
|
|
669
|
+
const parentFlowId = await createNewAwaitingMultipleStep(
|
|
670
|
+
_izContext,
|
|
671
|
+
pendingStepId,
|
|
672
|
+
`${flowTag}${serviceTag}`,
|
|
673
|
+
additionalAttributes
|
|
674
|
+
);
|
|
675
|
+
return {
|
|
676
|
+
...message,
|
|
677
|
+
parentFlowId
|
|
678
|
+
};
|
|
679
|
+
})
|
|
680
|
+
);
|
|
681
|
+
|
|
682
|
+
await Promise.all(
|
|
683
|
+
messagesWithParentId.map(message =>
|
|
684
|
+
sns.publishAsync(_izContext, {
|
|
685
|
+
TopicArn: topicArn,
|
|
686
|
+
Message: JSON.stringify(message),
|
|
687
|
+
MessageAttributes: {}
|
|
688
|
+
})
|
|
689
|
+
)
|
|
690
|
+
);
|
|
691
|
+
}
|