@izara_project/izara-core-library-asynchronous-flow 1.0.40 → 1.0.42
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/src/asyncFlowSharedLib.js +40 -3
- package/src/awaitingMultipleSteps.js +48 -52
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.42",
|
|
7
7
|
"description": "Shared asynchronous flow logic",
|
|
8
8
|
"type": "module",
|
|
9
9
|
"main": "index.js",
|
|
@@ -28,11 +28,48 @@ import { sqs } from '@izara_project/izara-core-library-external-request';
|
|
|
28
28
|
|
|
29
29
|
import { identifierUuid } from '@izara_project/izara-shared-core';
|
|
30
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Helper to safely join a prefix and an ID with a single underscore.
|
|
33
|
+
* Ensures no duplicate underscores between them.
|
|
34
|
+
* @param {string} id
|
|
35
|
+
* @param {string} [prefix='']
|
|
36
|
+
* @returns {string}
|
|
37
|
+
*/
|
|
38
|
+
function _joinPrefixAndId(id, prefix = '') {
|
|
39
|
+
if (!prefix) return id;
|
|
40
|
+
|
|
41
|
+
const cleanPrefix = prefix.endsWith('_') ? prefix.slice(0, -1) : prefix;
|
|
42
|
+
const cleanId = id.startsWith('_') ? id.slice(1) : id;
|
|
43
|
+
|
|
44
|
+
return `${cleanPrefix}_${cleanId}`;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Create awaitingStepId by concatenating prefix and partitionKey.
|
|
49
|
+
* If prefix ends with an underscore, it's removed before concatenation.
|
|
50
|
+
* If partitionKey starts with an underscore, it's removed before concatenation.
|
|
51
|
+
* This ensures a clean "PREFIX_PARTITIONKEY" format without double underscores.
|
|
52
|
+
*
|
|
53
|
+
* @param {string} partitionKey
|
|
54
|
+
* @param {string} [prefix='']
|
|
55
|
+
* @returns {string}
|
|
56
|
+
*/
|
|
31
57
|
function createAwaitingStepId(partitionKey, prefix = '') {
|
|
32
|
-
return prefix
|
|
58
|
+
return _joinPrefixAndId(partitionKey, prefix);
|
|
33
59
|
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Create pendingStepId by concatenating prefix and identifierId.
|
|
63
|
+
* If prefix ends with an underscore, it's removed before concatenation.
|
|
64
|
+
* If identifierId starts with an underscore, it's removed before concatenation.
|
|
65
|
+
* This ensures a clean "PREFIX_IDENTIFIER" format without double underscores.
|
|
66
|
+
*
|
|
67
|
+
* @param {string} identifierId
|
|
68
|
+
* @param {string} [prefix='']
|
|
69
|
+
* @returns {string}
|
|
70
|
+
*/
|
|
34
71
|
function createPendingStepId(identifierId, prefix = '') {
|
|
35
|
-
return prefix
|
|
72
|
+
return _joinPrefixAndId(identifierId, prefix);
|
|
36
73
|
}
|
|
37
74
|
|
|
38
75
|
/**
|
|
@@ -76,7 +113,7 @@ function createConcatenatedPendingStepId(parentId, childId) {
|
|
|
76
113
|
* @returns {string} The parent Flow Id created.
|
|
77
114
|
*/
|
|
78
115
|
function createParentFlowId(prefix = '') {
|
|
79
|
-
return (
|
|
116
|
+
return _joinPrefixAndId(identifierUuid(), prefix);
|
|
80
117
|
}
|
|
81
118
|
|
|
82
119
|
/**
|
|
@@ -19,7 +19,10 @@ import dynamodbSharedLib from '@izara_project/izara-core-library-dynamodb';
|
|
|
19
19
|
import { sns } from '@izara_project/izara-core-library-external-request';
|
|
20
20
|
import snsSharedLib from '@izara_project/izara-core-library-sns';
|
|
21
21
|
|
|
22
|
-
import {
|
|
22
|
+
import {
|
|
23
|
+
createParentFlowId,
|
|
24
|
+
createPendingStepId
|
|
25
|
+
} from './asyncFlowSharedLib.js';
|
|
23
26
|
|
|
24
27
|
function _assertPendingStepId(pendingStepId) {
|
|
25
28
|
if (!pendingStepId) {
|
|
@@ -97,15 +100,18 @@ async function _queryAwaitingStepsByPendingStepId(_izContext, pendingStepId) {
|
|
|
97
100
|
* @async
|
|
98
101
|
* @param {IzContext} _izContext - The Izara context.
|
|
99
102
|
* @param {string} pendingStepId - The ID of the pending step that is waiting.
|
|
100
|
-
* @param {Array<object>} [records=[]] - Array of step items
|
|
103
|
+
* @param {Array<object>} [records=[]] - Array of step items.
|
|
104
|
+
* @param {string} [records[].awaitingStepId] - Optional ID of the awaiting step. If not provided, a random UUID will be generated.
|
|
105
|
+
* @param {object} [records[].message] - Optional message payload to publish if flowType is provided.
|
|
106
|
+
* @param {object} [records[].flowType] - Optional flowType override for this specific step record.
|
|
107
|
+
* @param {string} records[].flowType.flowTag - Tag identifying the flow.
|
|
108
|
+
* @param {string} records[].flowType.serviceTag - Tag identifying the service.
|
|
101
109
|
* @param {object} [options={}] - Optional configurations.
|
|
102
110
|
* @param {string} [options.prefix=''] - Prefix to prepend to pendingStepId.
|
|
103
|
-
* @param {object} [options.additionalAttributes={}] -
|
|
104
|
-
* @param {object} [options.
|
|
105
|
-
* @param {
|
|
106
|
-
* @param {
|
|
107
|
-
* @param {string} options.publishConfig.flowType.flowTag - Tag identifying the flow.
|
|
108
|
-
* @param {string} options.publishConfig.flowType.serviceTag - Tag identifying the service.
|
|
111
|
+
* @param {object} [options.additionalAttributes={}] - Default additional attributes to associate with each pending step record.
|
|
112
|
+
* @param {object|null} [options.flowType=null] - Default flow schema/service metadata if starting external tasks.
|
|
113
|
+
* @param {string} [options.flowType.flowTag] - Tag identifying the default flow.
|
|
114
|
+
* @param {string} [options.flowType.serviceTag] - Tag identifying the default service.
|
|
109
115
|
* @returns {Promise<string|undefined>} The awaitingStepId of the first mapped record.
|
|
110
116
|
*/
|
|
111
117
|
export async function createAwaitingMultipleSteps(
|
|
@@ -114,30 +120,20 @@ export async function createAwaitingMultipleSteps(
|
|
|
114
120
|
records = [],
|
|
115
121
|
options = {}
|
|
116
122
|
) {
|
|
117
|
-
const {
|
|
118
|
-
prefix = '',
|
|
119
|
-
additionalAttributes = {},
|
|
120
|
-
publishConfig = null
|
|
121
|
-
} = options;
|
|
123
|
+
const { prefix = '', additionalAttributes = {}, flowType = null } = options;
|
|
122
124
|
|
|
123
125
|
_izContext.logger.debug('[Lib:AsyncFlow:createAwaitingMultipleSteps] Input', {
|
|
124
126
|
pendingStepId,
|
|
125
127
|
options
|
|
126
128
|
});
|
|
127
129
|
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
: `${prefix}_`
|
|
132
|
-
: '';
|
|
133
|
-
const finalPendingStepId =
|
|
134
|
-
formattedPrefix && !pendingStepId.startsWith(formattedPrefix)
|
|
135
|
-
? formattedPrefix + pendingStepId
|
|
136
|
-
: pendingStepId;
|
|
130
|
+
const finalPendingStepId = createPendingStepId(pendingStepId, prefix);
|
|
131
|
+
|
|
132
|
+
const hasFlowPublish = flowType || records.some(r => r.flowType);
|
|
137
133
|
|
|
138
134
|
let finalRecords = records;
|
|
139
135
|
|
|
140
|
-
if (finalRecords.length === 0 && !
|
|
136
|
+
if (finalRecords.length === 0 && !hasFlowPublish) {
|
|
141
137
|
finalRecords = [
|
|
142
138
|
{
|
|
143
139
|
awaitingStepId: createParentFlowId(prefix),
|
|
@@ -146,28 +142,34 @@ export async function createAwaitingMultipleSteps(
|
|
|
146
142
|
];
|
|
147
143
|
}
|
|
148
144
|
|
|
149
|
-
if (
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
const parentFlowId = createParentFlowId(prefix);
|
|
145
|
+
if (hasFlowPublish) {
|
|
146
|
+
finalRecords = records.map(record => {
|
|
147
|
+
const recordFlowType = record.flowType || flowType;
|
|
148
|
+
|
|
149
|
+
if (
|
|
150
|
+
!recordFlowType ||
|
|
151
|
+
!recordFlowType.flowTag ||
|
|
152
|
+
!recordFlowType.serviceTag
|
|
153
|
+
) {
|
|
154
|
+
throw new NoRetryError(
|
|
155
|
+
'record.flowType must have both flowTag and serviceTag'
|
|
156
|
+
);
|
|
157
|
+
}
|
|
163
158
|
|
|
159
|
+
const awaitingStepId =
|
|
160
|
+
record.awaitingStepId || createParentFlowId(prefix);
|
|
164
161
|
return {
|
|
165
|
-
awaitingStepId
|
|
162
|
+
awaitingStepId,
|
|
166
163
|
additionalAttributes,
|
|
167
164
|
message: {
|
|
168
|
-
...message,
|
|
169
|
-
parentFlowId
|
|
170
|
-
}
|
|
165
|
+
...record.message,
|
|
166
|
+
parentFlowId: awaitingStepId
|
|
167
|
+
},
|
|
168
|
+
topicArn: snsSharedLib.snsTopicArnByFlowSchema(
|
|
169
|
+
_izContext,
|
|
170
|
+
recordFlowType.flowTag,
|
|
171
|
+
recordFlowType.serviceTag
|
|
172
|
+
)
|
|
171
173
|
};
|
|
172
174
|
});
|
|
173
175
|
}
|
|
@@ -194,19 +196,12 @@ export async function createAwaitingMultipleSteps(
|
|
|
194
196
|
}
|
|
195
197
|
);
|
|
196
198
|
|
|
197
|
-
if (
|
|
198
|
-
const topicArn = snsSharedLib.snsTopicArnByFlowSchema(
|
|
199
|
-
_izContext,
|
|
200
|
-
publishConfig.flowType.flowTag,
|
|
201
|
-
publishConfig.flowType.serviceTag
|
|
202
|
-
);
|
|
203
|
-
|
|
199
|
+
if (hasFlowPublish) {
|
|
204
200
|
await Promise.all(
|
|
205
|
-
finalRecords.map(({ message }) =>
|
|
201
|
+
finalRecords.map(({ message, topicArn }) =>
|
|
206
202
|
sns.publishAsync(_izContext, {
|
|
207
203
|
TopicArn: `${topicArn}_In`,
|
|
208
|
-
Message: JSON.stringify(message)
|
|
209
|
-
MessageAttributes: {}
|
|
204
|
+
Message: JSON.stringify(message)
|
|
210
205
|
})
|
|
211
206
|
)
|
|
212
207
|
);
|
|
@@ -387,7 +382,8 @@ export async function checkAllAwaitingStepsFinishedWithReturnParams(
|
|
|
387
382
|
isComplete: false,
|
|
388
383
|
collectedAttributes: null,
|
|
389
384
|
collectedErrors: [],
|
|
390
|
-
returnValues: null
|
|
385
|
+
returnValues: null,
|
|
386
|
+
additionalAttributes: awaitingStepItems[0]?.additionalAttributes || null
|
|
391
387
|
};
|
|
392
388
|
}
|
|
393
389
|
|