@medusajs/workflow-engine-redis 3.0.0-preview-20250410180148 → 3.0.0-preview-20251201152819
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/dist/loaders/redis.d.ts.map +1 -1
- package/dist/loaders/redis.js +10 -10
- package/dist/loaders/redis.js.map +1 -1
- package/dist/loaders/utils.d.ts.map +1 -1
- package/dist/loaders/utils.js +1 -1
- package/dist/loaders/utils.js.map +1 -1
- package/dist/migrations/Migration20231228143900.d.ts +1 -1
- package/dist/migrations/Migration20231228143900.d.ts.map +1 -1
- package/dist/migrations/Migration20231228143900.js +1 -1
- package/dist/migrations/Migration20231228143900.js.map +1 -1
- package/dist/migrations/Migration20241206123341.d.ts +1 -1
- package/dist/migrations/Migration20241206123341.d.ts.map +1 -1
- package/dist/migrations/Migration20241206123341.js +1 -1
- package/dist/migrations/Migration20241206123341.js.map +1 -1
- package/dist/migrations/Migration20250120111059.d.ts +1 -1
- package/dist/migrations/Migration20250120111059.d.ts.map +1 -1
- package/dist/migrations/Migration20250120111059.js +1 -1
- package/dist/migrations/Migration20250120111059.js.map +1 -1
- package/dist/migrations/Migration20250128174354.d.ts +1 -1
- package/dist/migrations/Migration20250128174354.d.ts.map +1 -1
- package/dist/migrations/Migration20250128174354.js +1 -1
- package/dist/migrations/Migration20250128174354.js.map +1 -1
- package/dist/migrations/Migration20250505101505.d.ts +6 -0
- package/dist/migrations/Migration20250505101505.d.ts.map +1 -0
- package/dist/migrations/Migration20250505101505.js +40 -0
- package/dist/migrations/Migration20250505101505.js.map +1 -0
- package/dist/migrations/Migration20250819110923.d.ts +6 -0
- package/dist/migrations/Migration20250819110923.d.ts.map +1 -0
- package/dist/migrations/Migration20250819110923.js +14 -0
- package/dist/migrations/Migration20250819110923.js.map +1 -0
- package/dist/migrations/Migration20250819110924.d.ts +6 -0
- package/dist/migrations/Migration20250819110924.d.ts.map +1 -0
- package/dist/migrations/Migration20250819110924.js +16 -0
- package/dist/migrations/Migration20250819110924.js.map +1 -0
- package/dist/migrations/Migration20250908080326.d.ts +6 -0
- package/dist/migrations/Migration20250908080326.d.ts.map +1 -0
- package/dist/migrations/Migration20250908080326.js +20 -0
- package/dist/migrations/Migration20250908080326.js.map +1 -0
- package/dist/models/workflow-execution.d.ts +1 -0
- package/dist/models/workflow-execution.d.ts.map +1 -1
- package/dist/models/workflow-execution.js +22 -1
- package/dist/models/workflow-execution.js.map +1 -1
- package/dist/services/workflow-orchestrator.d.ts +16 -3
- package/dist/services/workflow-orchestrator.d.ts.map +1 -1
- package/dist/services/workflow-orchestrator.js +247 -118
- package/dist/services/workflow-orchestrator.js.map +1 -1
- package/dist/services/workflows-module.d.ts +114 -9
- package/dist/services/workflows-module.d.ts.map +1 -1
- package/dist/services/workflows-module.js +113 -50
- package/dist/services/workflows-module.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utils/workflow-orchestrator-storage.d.ts +10 -3
- package/dist/utils/workflow-orchestrator-storage.d.ts.map +1 -1
- package/dist/utils/workflow-orchestrator-storage.js +343 -143
- package/dist/utils/workflow-orchestrator-storage.js.map +1 -1
- package/package.json +14 -28
|
@@ -16,14 +16,11 @@ exports.WorkflowOrchestratorService = void 0;
|
|
|
16
16
|
const orchestration_1 = require("@medusajs/framework/orchestration");
|
|
17
17
|
const utils_1 = require("@medusajs/framework/utils");
|
|
18
18
|
const workflows_sdk_1 = require("@medusajs/framework/workflows-sdk");
|
|
19
|
-
const timers_1 = require("timers");
|
|
20
19
|
const ulid_1 = require("ulid");
|
|
21
20
|
const AnySubscriber = "any";
|
|
22
21
|
class WorkflowOrchestratorService {
|
|
23
22
|
constructor({ dataLoaderOnly, redisDistributedTransactionStorage, redisPublisher, redisSubscriber, sharedContainer, }) {
|
|
24
23
|
this.instanceId = (0, ulid_1.ulid)();
|
|
25
|
-
this.subscribers = new Map();
|
|
26
|
-
this.activeStepsCount = 0;
|
|
27
24
|
_WorkflowOrchestratorService_logger.set(this, void 0);
|
|
28
25
|
this.container_ = sharedContainer;
|
|
29
26
|
this.redisPublisher = redisPublisher;
|
|
@@ -36,9 +33,17 @@ class WorkflowOrchestratorService {
|
|
|
36
33
|
}
|
|
37
34
|
this.redisDistributedTransactionStorage_ =
|
|
38
35
|
redisDistributedTransactionStorage;
|
|
39
|
-
this.redisSubscriber.on("message", async (
|
|
40
|
-
const
|
|
41
|
-
|
|
36
|
+
this.redisSubscriber.on("message", async (channel, message) => {
|
|
37
|
+
const workflowId = channel.split(":")[1];
|
|
38
|
+
if (!WorkflowOrchestratorService.subscribers.has(workflowId))
|
|
39
|
+
return;
|
|
40
|
+
try {
|
|
41
|
+
const { instanceId, data } = JSON.parse(message);
|
|
42
|
+
await this.notify(data, false, instanceId);
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
__classPrivateFieldGet(this, _WorkflowOrchestratorService_logger, "f").error(`Failed to process Redis message: ${error}`);
|
|
46
|
+
}
|
|
42
47
|
});
|
|
43
48
|
}
|
|
44
49
|
async onApplicationShutdown() {
|
|
@@ -47,16 +52,20 @@ class WorkflowOrchestratorService {
|
|
|
47
52
|
async onApplicationPrepareShutdown() {
|
|
48
53
|
// eslint-disable-next-line max-len
|
|
49
54
|
await this.redisDistributedTransactionStorage_.onApplicationPrepareShutdown();
|
|
50
|
-
while (this.activeStepsCount > 0) {
|
|
51
|
-
await new Promise((resolve) => (0, timers_1.setTimeout)(resolve, 1000));
|
|
52
|
-
}
|
|
53
55
|
}
|
|
54
56
|
async onApplicationStart() {
|
|
55
57
|
await this.redisDistributedTransactionStorage_.onApplicationStart();
|
|
56
58
|
}
|
|
57
|
-
async triggerParentStep(transaction, result) {
|
|
59
|
+
async triggerParentStep(transaction, result, errors) {
|
|
58
60
|
const metadata = transaction.flow.metadata;
|
|
59
|
-
const { parentStepIdempotencyKey } = metadata ?? {};
|
|
61
|
+
const { parentStepIdempotencyKey, cancelingFromParentStep } = metadata ?? {};
|
|
62
|
+
if (cancelingFromParentStep) {
|
|
63
|
+
/**
|
|
64
|
+
* If the sub workflow is cancelling from a parent step, we don't want to trigger the parent
|
|
65
|
+
* step.
|
|
66
|
+
*/
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
60
69
|
if (parentStepIdempotencyKey) {
|
|
61
70
|
const hasFailed = [
|
|
62
71
|
utils_1.TransactionState.REVERTED,
|
|
@@ -65,7 +74,7 @@ class WorkflowOrchestratorService {
|
|
|
65
74
|
if (hasFailed) {
|
|
66
75
|
await this.setStepFailure({
|
|
67
76
|
idempotencyKey: parentStepIdempotencyKey,
|
|
68
|
-
stepResponse:
|
|
77
|
+
stepResponse: errors,
|
|
69
78
|
options: {
|
|
70
79
|
logOnError: true,
|
|
71
80
|
},
|
|
@@ -87,12 +96,12 @@ class WorkflowOrchestratorService {
|
|
|
87
96
|
let { throwOnError, context } = options ?? {};
|
|
88
97
|
throwOnError ??= true;
|
|
89
98
|
context ??= {};
|
|
90
|
-
context.transactionId = transactionId ?? (0, ulid_1.ulid)();
|
|
99
|
+
context.transactionId = transactionId ?? "auto-" + (0, ulid_1.ulid)();
|
|
91
100
|
const workflowId = (0, utils_1.isString)(workflowIdOrWorkflow)
|
|
92
101
|
? workflowIdOrWorkflow
|
|
93
102
|
: workflowIdOrWorkflow.getName();
|
|
94
103
|
if (!workflowId) {
|
|
95
|
-
throw new
|
|
104
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_FOUND, `Workflow ID is required`);
|
|
96
105
|
}
|
|
97
106
|
const events = this.buildWorkflowEvents({
|
|
98
107
|
customEventHandlers: eventHandlers,
|
|
@@ -101,17 +110,17 @@ class WorkflowOrchestratorService {
|
|
|
101
110
|
});
|
|
102
111
|
const exportedWorkflow = workflows_sdk_1.MedusaWorkflow.getWorkflow(workflowId);
|
|
103
112
|
if (!exportedWorkflow) {
|
|
104
|
-
throw new
|
|
113
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_FOUND, `Workflow with id "${workflowId}" not found.`);
|
|
105
114
|
}
|
|
115
|
+
const { onFinish, ...restEvents } = events;
|
|
106
116
|
const originalOnFinishHandler = events.onFinish;
|
|
107
|
-
delete events.onFinish;
|
|
108
117
|
const ret = await exportedWorkflow.run({
|
|
109
118
|
input,
|
|
110
119
|
throwOnError: false,
|
|
111
120
|
logOnError,
|
|
112
121
|
resultFrom,
|
|
113
122
|
context,
|
|
114
|
-
events,
|
|
123
|
+
events: restEvents,
|
|
115
124
|
container: container ?? this.container_,
|
|
116
125
|
});
|
|
117
126
|
const hasFinished = ret.transaction.hasFinished();
|
|
@@ -135,10 +144,13 @@ class WorkflowOrchestratorService {
|
|
|
135
144
|
result,
|
|
136
145
|
errors,
|
|
137
146
|
});
|
|
138
|
-
await this.triggerParentStep(ret.transaction, result);
|
|
147
|
+
await this.triggerParentStep(ret.transaction, result, errors);
|
|
139
148
|
}
|
|
140
|
-
if (throwOnError && ret.thrownError) {
|
|
141
|
-
|
|
149
|
+
if (throwOnError && (ret.thrownError || ret.errors?.length)) {
|
|
150
|
+
if (ret.thrownError) {
|
|
151
|
+
throw ret.thrownError;
|
|
152
|
+
}
|
|
153
|
+
throw ret.errors[0].error;
|
|
142
154
|
}
|
|
143
155
|
return { acknowledgement, ...ret };
|
|
144
156
|
}
|
|
@@ -156,18 +168,11 @@ class WorkflowOrchestratorService {
|
|
|
156
168
|
if (!transactionId) {
|
|
157
169
|
throw new Error("Transaction ID is required");
|
|
158
170
|
}
|
|
159
|
-
const events = this.buildWorkflowEvents({
|
|
160
|
-
customEventHandlers: eventHandlers,
|
|
161
|
-
workflowId,
|
|
162
|
-
transactionId: transactionId,
|
|
163
|
-
});
|
|
164
171
|
const exportedWorkflow = workflows_sdk_1.MedusaWorkflow.getWorkflow(workflowId);
|
|
165
172
|
if (!exportedWorkflow) {
|
|
166
|
-
throw new
|
|
173
|
+
throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_FOUND, `Workflow with id "${workflowId}" not found.`);
|
|
167
174
|
}
|
|
168
|
-
const
|
|
169
|
-
delete events.onFinish;
|
|
170
|
-
const transaction = await this.getRunningTransaction(workflowId, transactionId, options);
|
|
175
|
+
const transaction = await this.getRunningTransaction(workflowId, transactionId, { ...options, isCancelling: true });
|
|
171
176
|
if (!transaction) {
|
|
172
177
|
if (!throwOnError) {
|
|
173
178
|
return {
|
|
@@ -180,20 +185,28 @@ class WorkflowOrchestratorService {
|
|
|
180
185
|
}
|
|
181
186
|
throw new Error("Transaction not found");
|
|
182
187
|
}
|
|
188
|
+
const events = this.buildWorkflowEvents({
|
|
189
|
+
customEventHandlers: eventHandlers,
|
|
190
|
+
workflowId,
|
|
191
|
+
transactionId: transactionId,
|
|
192
|
+
});
|
|
193
|
+
const { onFinish, ...restEvents } = events;
|
|
194
|
+
const originalOnFinishHandler = events.onFinish;
|
|
183
195
|
const ret = await exportedWorkflow.cancel({
|
|
184
196
|
transaction,
|
|
185
197
|
throwOnError: false,
|
|
186
198
|
logOnError,
|
|
187
199
|
context,
|
|
188
|
-
events,
|
|
200
|
+
events: restEvents,
|
|
189
201
|
container: container ?? this.container_,
|
|
190
202
|
});
|
|
191
203
|
const hasFinished = ret.transaction.hasFinished();
|
|
192
204
|
const metadata = ret.transaction.getFlow().metadata;
|
|
193
205
|
const { parentStepIdempotencyKey } = metadata ?? {};
|
|
194
|
-
const
|
|
206
|
+
const transactionState = ret.transaction.getFlow().state;
|
|
207
|
+
const hasFailed = [utils_1.TransactionState.FAILED].includes(transactionState);
|
|
195
208
|
const acknowledgement = {
|
|
196
|
-
transactionId:
|
|
209
|
+
transactionId: transaction.transactionId,
|
|
197
210
|
workflowId: workflowId,
|
|
198
211
|
parentStepIdempotencyKey,
|
|
199
212
|
hasFinished,
|
|
@@ -207,10 +220,13 @@ class WorkflowOrchestratorService {
|
|
|
207
220
|
result,
|
|
208
221
|
errors,
|
|
209
222
|
});
|
|
210
|
-
await this.triggerParentStep(ret.transaction, result);
|
|
223
|
+
await this.triggerParentStep(ret.transaction, result, errors);
|
|
211
224
|
}
|
|
212
|
-
if (throwOnError && ret.thrownError) {
|
|
213
|
-
|
|
225
|
+
if (throwOnError && (ret.thrownError || ret.errors?.length)) {
|
|
226
|
+
if (ret.thrownError) {
|
|
227
|
+
throw ret.thrownError;
|
|
228
|
+
}
|
|
229
|
+
throw ret.errors[0].error;
|
|
214
230
|
}
|
|
215
231
|
return { acknowledgement, ...ret };
|
|
216
232
|
}
|
|
@@ -230,6 +246,47 @@ class WorkflowOrchestratorService {
|
|
|
230
246
|
const transaction = await flow.getRunningTransaction(transactionId, context);
|
|
231
247
|
return transaction;
|
|
232
248
|
}
|
|
249
|
+
async retryStep({ idempotencyKey, options, }) {
|
|
250
|
+
const { context, logOnError, container, events: eventHandlers, } = options ?? {};
|
|
251
|
+
let { throwOnError } = options ?? {};
|
|
252
|
+
throwOnError ??= true;
|
|
253
|
+
const [idempotencyKey_, { workflowId, transactionId }] = this.buildIdempotencyKeyAndParts(idempotencyKey);
|
|
254
|
+
const exportedWorkflow = workflows_sdk_1.MedusaWorkflow.getWorkflow(workflowId);
|
|
255
|
+
if (!exportedWorkflow) {
|
|
256
|
+
throw new Error(`Workflow with id "${workflowId}" not found.`);
|
|
257
|
+
}
|
|
258
|
+
const events = this.buildWorkflowEvents({
|
|
259
|
+
customEventHandlers: eventHandlers,
|
|
260
|
+
transactionId,
|
|
261
|
+
workflowId,
|
|
262
|
+
});
|
|
263
|
+
const { onFinish, ...restEvents } = events;
|
|
264
|
+
const originalOnFinishHandler = events.onFinish;
|
|
265
|
+
const ret = await exportedWorkflow.retryStep({
|
|
266
|
+
idempotencyKey: idempotencyKey_,
|
|
267
|
+
context,
|
|
268
|
+
throwOnError: false,
|
|
269
|
+
logOnError,
|
|
270
|
+
events: restEvents,
|
|
271
|
+
container: container ?? this.container_,
|
|
272
|
+
});
|
|
273
|
+
if (ret.transaction.hasFinished()) {
|
|
274
|
+
const { result, errors } = ret;
|
|
275
|
+
await originalOnFinishHandler({
|
|
276
|
+
transaction: ret.transaction,
|
|
277
|
+
result,
|
|
278
|
+
errors,
|
|
279
|
+
});
|
|
280
|
+
await this.triggerParentStep(ret.transaction, result, errors);
|
|
281
|
+
}
|
|
282
|
+
if (throwOnError && (ret.thrownError || ret.errors?.length)) {
|
|
283
|
+
if (ret.thrownError) {
|
|
284
|
+
throw ret.thrownError;
|
|
285
|
+
}
|
|
286
|
+
throw ret.errors[0].error;
|
|
287
|
+
}
|
|
288
|
+
return ret;
|
|
289
|
+
}
|
|
233
290
|
async setStepSuccess({ idempotencyKey, stepResponse, options, }) {
|
|
234
291
|
const { context, logOnError, resultFrom, container, events: eventHandlers, } = options ?? {};
|
|
235
292
|
let { throwOnError } = options ?? {};
|
|
@@ -244,15 +301,15 @@ class WorkflowOrchestratorService {
|
|
|
244
301
|
transactionId,
|
|
245
302
|
workflowId,
|
|
246
303
|
});
|
|
304
|
+
const { onFinish, ...restEvents } = events;
|
|
247
305
|
const originalOnFinishHandler = events.onFinish;
|
|
248
|
-
delete events.onFinish;
|
|
249
306
|
const ret = await exportedWorkflow.registerStepSuccess({
|
|
250
307
|
idempotencyKey: idempotencyKey_,
|
|
251
308
|
context,
|
|
252
309
|
resultFrom,
|
|
253
310
|
throwOnError: false,
|
|
254
311
|
logOnError,
|
|
255
|
-
events,
|
|
312
|
+
events: restEvents,
|
|
256
313
|
response: stepResponse,
|
|
257
314
|
container: container ?? this.container_,
|
|
258
315
|
});
|
|
@@ -263,15 +320,18 @@ class WorkflowOrchestratorService {
|
|
|
263
320
|
result,
|
|
264
321
|
errors,
|
|
265
322
|
});
|
|
266
|
-
await this.triggerParentStep(ret.transaction, result);
|
|
323
|
+
await this.triggerParentStep(ret.transaction, result, errors);
|
|
267
324
|
}
|
|
268
|
-
if (throwOnError && ret.thrownError) {
|
|
269
|
-
|
|
325
|
+
if (throwOnError && (ret.thrownError || ret.errors?.length)) {
|
|
326
|
+
if (ret.thrownError) {
|
|
327
|
+
throw ret.thrownError;
|
|
328
|
+
}
|
|
329
|
+
throw ret.errors[0].error;
|
|
270
330
|
}
|
|
271
331
|
return ret;
|
|
272
332
|
}
|
|
273
333
|
async setStepFailure({ idempotencyKey, stepResponse, options, }) {
|
|
274
|
-
const { context, logOnError, resultFrom, container, events: eventHandlers, } = options ?? {};
|
|
334
|
+
const { context, logOnError, resultFrom, container, events: eventHandlers, forcePermanentFailure, } = options ?? {};
|
|
275
335
|
let { throwOnError } = options ?? {};
|
|
276
336
|
throwOnError ??= true;
|
|
277
337
|
const [idempotencyKey_, { workflowId, transactionId }] = this.buildIdempotencyKeyAndParts(idempotencyKey);
|
|
@@ -284,17 +344,18 @@ class WorkflowOrchestratorService {
|
|
|
284
344
|
transactionId,
|
|
285
345
|
workflowId,
|
|
286
346
|
});
|
|
347
|
+
const { onFinish, ...restEvents } = events;
|
|
287
348
|
const originalOnFinishHandler = events.onFinish;
|
|
288
|
-
delete events.onFinish;
|
|
289
349
|
const ret = await exportedWorkflow.registerStepFailure({
|
|
290
350
|
idempotencyKey: idempotencyKey_,
|
|
291
351
|
context,
|
|
292
352
|
resultFrom,
|
|
293
353
|
throwOnError: false,
|
|
294
354
|
logOnError,
|
|
295
|
-
events,
|
|
355
|
+
events: restEvents,
|
|
296
356
|
response: stepResponse,
|
|
297
357
|
container: container ?? this.container_,
|
|
358
|
+
forcePermanentFailure,
|
|
298
359
|
});
|
|
299
360
|
if (ret.transaction.hasFinished()) {
|
|
300
361
|
const { result, errors } = ret;
|
|
@@ -303,45 +364,51 @@ class WorkflowOrchestratorService {
|
|
|
303
364
|
result,
|
|
304
365
|
errors,
|
|
305
366
|
});
|
|
306
|
-
await this.triggerParentStep(ret.transaction, result);
|
|
367
|
+
await this.triggerParentStep(ret.transaction, result, errors);
|
|
307
368
|
}
|
|
308
|
-
if (throwOnError && ret.thrownError) {
|
|
309
|
-
|
|
369
|
+
if (throwOnError && (ret.thrownError || ret.errors?.length)) {
|
|
370
|
+
if (ret.thrownError) {
|
|
371
|
+
throw ret.thrownError;
|
|
372
|
+
}
|
|
373
|
+
throw ret.errors[0].error;
|
|
310
374
|
}
|
|
311
375
|
return ret;
|
|
312
376
|
}
|
|
313
377
|
subscribe({ workflowId, transactionId, subscriber, subscriberId, }) {
|
|
314
378
|
subscriber._id = subscriberId;
|
|
315
|
-
const subscribers =
|
|
379
|
+
const subscribers = WorkflowOrchestratorService.subscribers.get(workflowId) ?? new Map();
|
|
316
380
|
// Subscribe instance to redis
|
|
317
|
-
if (!
|
|
381
|
+
if (!WorkflowOrchestratorService.subscribers.has(workflowId)) {
|
|
318
382
|
void this.redisSubscriber.subscribe(this.getChannelName(workflowId));
|
|
319
383
|
}
|
|
320
384
|
const handlerIndex = (handlers) => {
|
|
321
|
-
return handlers.
|
|
385
|
+
return handlers.findIndex((s) => s === subscriber || s._id === subscriberId);
|
|
322
386
|
};
|
|
323
387
|
if (transactionId) {
|
|
324
388
|
const transactionSubscribers = subscribers.get(transactionId) ?? [];
|
|
325
389
|
const subscriberIndex = handlerIndex(transactionSubscribers);
|
|
326
390
|
if (subscriberIndex !== -1) {
|
|
327
|
-
transactionSubscribers.
|
|
391
|
+
transactionSubscribers.splice(subscriberIndex, 1);
|
|
328
392
|
}
|
|
329
393
|
transactionSubscribers.push(subscriber);
|
|
330
394
|
subscribers.set(transactionId, transactionSubscribers);
|
|
331
|
-
|
|
395
|
+
WorkflowOrchestratorService.subscribers.set(workflowId, subscribers);
|
|
332
396
|
return;
|
|
333
397
|
}
|
|
334
398
|
const workflowSubscribers = subscribers.get(AnySubscriber) ?? [];
|
|
335
399
|
const subscriberIndex = handlerIndex(workflowSubscribers);
|
|
336
400
|
if (subscriberIndex !== -1) {
|
|
337
|
-
workflowSubscribers.
|
|
401
|
+
workflowSubscribers.splice(subscriberIndex, 1);
|
|
338
402
|
}
|
|
339
403
|
workflowSubscribers.push(subscriber);
|
|
340
404
|
subscribers.set(AnySubscriber, workflowSubscribers);
|
|
341
|
-
|
|
405
|
+
WorkflowOrchestratorService.subscribers.set(workflowId, subscribers);
|
|
342
406
|
}
|
|
343
407
|
unsubscribe({ workflowId, transactionId, subscriberOrId, }) {
|
|
344
|
-
const subscribers =
|
|
408
|
+
const subscribers = WorkflowOrchestratorService.subscribers.get(workflowId);
|
|
409
|
+
if (!subscribers) {
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
345
412
|
const filterSubscribers = (handlers) => {
|
|
346
413
|
return handlers.filter((handler) => {
|
|
347
414
|
return handler._id
|
|
@@ -349,81 +416,99 @@ class WorkflowOrchestratorService {
|
|
|
349
416
|
: handler !== subscriberOrId;
|
|
350
417
|
});
|
|
351
418
|
};
|
|
352
|
-
// Unsubscribe instance
|
|
353
|
-
if (!this.subscribers.has(workflowId)) {
|
|
354
|
-
void this.redisSubscriber.unsubscribe(this.getChannelName(workflowId));
|
|
355
|
-
}
|
|
356
419
|
if (transactionId) {
|
|
357
|
-
const transactionSubscribers = subscribers.get(transactionId)
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
420
|
+
const transactionSubscribers = subscribers.get(transactionId);
|
|
421
|
+
if (transactionSubscribers) {
|
|
422
|
+
const newTransactionSubscribers = filterSubscribers(transactionSubscribers);
|
|
423
|
+
if (newTransactionSubscribers.length) {
|
|
424
|
+
subscribers.set(transactionId, newTransactionSubscribers);
|
|
425
|
+
}
|
|
426
|
+
else {
|
|
427
|
+
subscribers.delete(transactionId);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
else {
|
|
432
|
+
const workflowSubscribers = subscribers.get(AnySubscriber);
|
|
433
|
+
if (workflowSubscribers) {
|
|
434
|
+
const newWorkflowSubscribers = filterSubscribers(workflowSubscribers);
|
|
435
|
+
if (newWorkflowSubscribers.length) {
|
|
436
|
+
subscribers.set(AnySubscriber, newWorkflowSubscribers);
|
|
437
|
+
}
|
|
438
|
+
else {
|
|
439
|
+
subscribers.delete(AnySubscriber);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
if (subscribers.size === 0) {
|
|
444
|
+
WorkflowOrchestratorService.subscribers.delete(workflowId);
|
|
445
|
+
void this.redisSubscriber.unsubscribe(this.getChannelName(workflowId));
|
|
362
446
|
}
|
|
363
|
-
const workflowSubscribers = subscribers.get(AnySubscriber) ?? [];
|
|
364
|
-
const newWorkflowSubscribers = filterSubscribers(workflowSubscribers);
|
|
365
|
-
subscribers.set(AnySubscriber, newWorkflowSubscribers);
|
|
366
|
-
this.subscribers.set(workflowId, subscribers);
|
|
367
447
|
}
|
|
368
448
|
async notify(options, publish = true, instanceId = this.instanceId) {
|
|
369
449
|
if (!publish && instanceId === this.instanceId) {
|
|
370
450
|
return;
|
|
371
451
|
}
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
const subscribers = this.subscribers.get(workflowId) ?? new Map();
|
|
382
|
-
const notifySubscribers = (handlers) => {
|
|
383
|
-
handlers.forEach((handler) => {
|
|
384
|
-
const args = {
|
|
385
|
-
eventType,
|
|
386
|
-
workflowId,
|
|
387
|
-
transactionId,
|
|
388
|
-
step,
|
|
389
|
-
response,
|
|
390
|
-
result,
|
|
391
|
-
errors,
|
|
392
|
-
};
|
|
393
|
-
const isPromise = "then" in handler;
|
|
394
|
-
if (isPromise) {
|
|
395
|
-
;
|
|
396
|
-
handler(args).catch((e) => {
|
|
397
|
-
__classPrivateFieldGet(this, _WorkflowOrchestratorService_logger, "f").error(e);
|
|
452
|
+
const { workflowId, isFlowAsync } = options;
|
|
453
|
+
// Non-blocking Redis publishing
|
|
454
|
+
if (publish && isFlowAsync) {
|
|
455
|
+
setImmediate(async () => {
|
|
456
|
+
try {
|
|
457
|
+
const channel = this.getChannelName(workflowId);
|
|
458
|
+
const message = JSON.stringify({
|
|
459
|
+
instanceId: this.instanceId,
|
|
460
|
+
data: options,
|
|
398
461
|
});
|
|
462
|
+
await this.redisPublisher.publish(channel, message);
|
|
399
463
|
}
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
464
|
+
catch (error) {
|
|
465
|
+
__classPrivateFieldGet(this, _WorkflowOrchestratorService_logger, "f").error(`Failed to publish to Redis: ${error}`);
|
|
466
|
+
}
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
// Process subscribers asynchronously
|
|
470
|
+
setImmediate(() => this.processSubscriberNotifications(options));
|
|
471
|
+
}
|
|
472
|
+
async processSubscriberNotifications(options) {
|
|
473
|
+
const { workflowId, transactionId, eventType } = options;
|
|
474
|
+
const subscribers = WorkflowOrchestratorService.subscribers.get(workflowId) ?? new Map();
|
|
475
|
+
const notifySubscribersAsync = async (handlers) => {
|
|
476
|
+
const promises = handlers.map(async (handler) => {
|
|
477
|
+
try {
|
|
478
|
+
const result = handler(options);
|
|
479
|
+
if (result && typeof result === "object" && "then" in result) {
|
|
480
|
+
await result;
|
|
406
481
|
}
|
|
407
482
|
}
|
|
483
|
+
catch (error) {
|
|
484
|
+
__classPrivateFieldGet(this, _WorkflowOrchestratorService_logger, "f").error(`Subscriber error: ${error}`);
|
|
485
|
+
}
|
|
408
486
|
});
|
|
487
|
+
await (0, utils_1.promiseAll)(promises);
|
|
409
488
|
};
|
|
489
|
+
const tasks = [];
|
|
410
490
|
if (transactionId) {
|
|
411
491
|
const transactionSubscribers = subscribers.get(transactionId) ?? [];
|
|
412
|
-
|
|
413
|
-
|
|
492
|
+
if (transactionSubscribers.length > 0) {
|
|
493
|
+
tasks.push(notifySubscribersAsync(transactionSubscribers));
|
|
494
|
+
}
|
|
414
495
|
if (eventType === "onFinish") {
|
|
415
496
|
subscribers.delete(transactionId);
|
|
416
497
|
}
|
|
417
498
|
}
|
|
418
499
|
const workflowSubscribers = subscribers.get(AnySubscriber) ?? [];
|
|
419
|
-
|
|
500
|
+
if (workflowSubscribers.length > 0) {
|
|
501
|
+
tasks.push(notifySubscribersAsync(workflowSubscribers));
|
|
502
|
+
}
|
|
503
|
+
await (0, utils_1.promiseAll)(tasks);
|
|
420
504
|
}
|
|
421
505
|
getChannelName(workflowId) {
|
|
422
506
|
return `orchestrator:${workflowId}`;
|
|
423
507
|
}
|
|
424
508
|
buildWorkflowEvents({ customEventHandlers, workflowId, transactionId, }) {
|
|
425
|
-
const notify = async ({ eventType, step, result, response, errors, }) => {
|
|
509
|
+
const notify = async ({ isFlowAsync, eventType, step, result, response, errors, state, }) => {
|
|
426
510
|
await this.notify({
|
|
511
|
+
isFlowAsync,
|
|
427
512
|
workflowId,
|
|
428
513
|
transactionId,
|
|
429
514
|
eventType,
|
|
@@ -431,40 +516,66 @@ class WorkflowOrchestratorService {
|
|
|
431
516
|
step,
|
|
432
517
|
result,
|
|
433
518
|
errors,
|
|
519
|
+
state,
|
|
434
520
|
});
|
|
435
521
|
};
|
|
436
522
|
return {
|
|
437
523
|
onTimeout: async ({ transaction }) => {
|
|
438
524
|
customEventHandlers?.onTimeout?.({ transaction });
|
|
439
|
-
await notify({
|
|
525
|
+
await notify({
|
|
526
|
+
eventType: "onTimeout",
|
|
527
|
+
isFlowAsync: transaction.getFlow().hasAsyncSteps,
|
|
528
|
+
});
|
|
440
529
|
},
|
|
441
530
|
onBegin: async ({ transaction }) => {
|
|
442
531
|
customEventHandlers?.onBegin?.({ transaction });
|
|
443
|
-
await notify({
|
|
532
|
+
await notify({
|
|
533
|
+
eventType: "onBegin",
|
|
534
|
+
isFlowAsync: transaction.getFlow().hasAsyncSteps,
|
|
535
|
+
});
|
|
444
536
|
},
|
|
445
537
|
onResume: async ({ transaction }) => {
|
|
446
538
|
customEventHandlers?.onResume?.({ transaction });
|
|
447
|
-
await notify({
|
|
539
|
+
await notify({
|
|
540
|
+
eventType: "onResume",
|
|
541
|
+
isFlowAsync: transaction.getFlow().hasAsyncSteps,
|
|
542
|
+
});
|
|
448
543
|
},
|
|
449
544
|
onCompensateBegin: async ({ transaction }) => {
|
|
450
545
|
customEventHandlers?.onCompensateBegin?.({ transaction });
|
|
451
|
-
await notify({
|
|
546
|
+
await notify({
|
|
547
|
+
eventType: "onCompensateBegin",
|
|
548
|
+
isFlowAsync: transaction.getFlow().hasAsyncSteps,
|
|
549
|
+
});
|
|
452
550
|
},
|
|
453
551
|
onFinish: async ({ transaction, result, errors }) => {
|
|
454
552
|
customEventHandlers?.onFinish?.({ transaction, result, errors });
|
|
455
|
-
await notify({
|
|
553
|
+
await notify({
|
|
554
|
+
eventType: "onFinish",
|
|
555
|
+
isFlowAsync: transaction.getFlow().hasAsyncSteps,
|
|
556
|
+
result,
|
|
557
|
+
errors,
|
|
558
|
+
state: transaction.getFlow().state,
|
|
559
|
+
});
|
|
456
560
|
},
|
|
457
561
|
onStepBegin: async ({ step, transaction }) => {
|
|
458
562
|
customEventHandlers?.onStepBegin?.({ step, transaction });
|
|
459
|
-
|
|
460
|
-
|
|
563
|
+
await notify({
|
|
564
|
+
eventType: "onStepBegin",
|
|
565
|
+
step,
|
|
566
|
+
isFlowAsync: transaction.getFlow().hasAsyncSteps,
|
|
567
|
+
});
|
|
461
568
|
},
|
|
462
569
|
onStepSuccess: async ({ step, transaction }) => {
|
|
463
570
|
const stepName = step.definition.action;
|
|
464
571
|
const response = await (0, workflows_sdk_1.resolveValue)(transaction.getContext().invoke[stepName], transaction);
|
|
465
572
|
customEventHandlers?.onStepSuccess?.({ step, transaction, response });
|
|
466
|
-
await notify({
|
|
467
|
-
|
|
573
|
+
await notify({
|
|
574
|
+
eventType: "onStepSuccess",
|
|
575
|
+
step,
|
|
576
|
+
response,
|
|
577
|
+
isFlowAsync: transaction.getFlow().hasAsyncSteps,
|
|
578
|
+
});
|
|
468
579
|
},
|
|
469
580
|
onStepFailure: async ({ step, transaction }) => {
|
|
470
581
|
const stepName = step.definition.action;
|
|
@@ -472,13 +583,20 @@ class WorkflowOrchestratorService {
|
|
|
472
583
|
.getErrors(orchestration_1.TransactionHandlerType.INVOKE)
|
|
473
584
|
.filter((err) => err.action === stepName);
|
|
474
585
|
customEventHandlers?.onStepFailure?.({ step, transaction, errors });
|
|
475
|
-
await notify({
|
|
476
|
-
|
|
586
|
+
await notify({
|
|
587
|
+
eventType: "onStepFailure",
|
|
588
|
+
step,
|
|
589
|
+
errors,
|
|
590
|
+
isFlowAsync: transaction.getFlow().hasAsyncSteps,
|
|
591
|
+
});
|
|
477
592
|
},
|
|
478
593
|
onStepAwaiting: async ({ step, transaction }) => {
|
|
479
594
|
customEventHandlers?.onStepAwaiting?.({ step, transaction });
|
|
480
|
-
await notify({
|
|
481
|
-
|
|
595
|
+
await notify({
|
|
596
|
+
eventType: "onStepAwaiting",
|
|
597
|
+
step,
|
|
598
|
+
isFlowAsync: transaction.getFlow().hasAsyncSteps,
|
|
599
|
+
});
|
|
482
600
|
},
|
|
483
601
|
onCompensateStepSuccess: async ({ step, transaction }) => {
|
|
484
602
|
const stepName = step.definition.action;
|
|
@@ -488,7 +606,12 @@ class WorkflowOrchestratorService {
|
|
|
488
606
|
transaction,
|
|
489
607
|
response,
|
|
490
608
|
});
|
|
491
|
-
await notify({
|
|
609
|
+
await notify({
|
|
610
|
+
eventType: "onCompensateStepSuccess",
|
|
611
|
+
step,
|
|
612
|
+
response,
|
|
613
|
+
isFlowAsync: transaction.getFlow().hasAsyncSteps,
|
|
614
|
+
});
|
|
492
615
|
},
|
|
493
616
|
onCompensateStepFailure: async ({ step, transaction }) => {
|
|
494
617
|
const stepName = step.definition.action;
|
|
@@ -496,7 +619,12 @@ class WorkflowOrchestratorService {
|
|
|
496
619
|
.getErrors(orchestration_1.TransactionHandlerType.COMPENSATE)
|
|
497
620
|
.filter((err) => err.action === stepName);
|
|
498
621
|
customEventHandlers?.onStepFailure?.({ step, transaction, errors });
|
|
499
|
-
await notify({
|
|
622
|
+
await notify({
|
|
623
|
+
eventType: "onCompensateStepFailure",
|
|
624
|
+
step,
|
|
625
|
+
errors,
|
|
626
|
+
isFlowAsync: transaction.getFlow().hasAsyncSteps,
|
|
627
|
+
});
|
|
500
628
|
},
|
|
501
629
|
};
|
|
502
630
|
}
|
|
@@ -528,4 +656,5 @@ class WorkflowOrchestratorService {
|
|
|
528
656
|
}
|
|
529
657
|
exports.WorkflowOrchestratorService = WorkflowOrchestratorService;
|
|
530
658
|
_WorkflowOrchestratorService_logger = new WeakMap();
|
|
659
|
+
WorkflowOrchestratorService.subscribers = new Map();
|
|
531
660
|
//# sourceMappingURL=workflow-orchestrator.js.map
|