@medusajs/workflow-engine-redis 3.0.0-preview-20250410210150 → 3.0.0-preview-20251202120138

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.
Files changed (56) hide show
  1. package/dist/loaders/redis.d.ts.map +1 -1
  2. package/dist/loaders/redis.js +10 -10
  3. package/dist/loaders/redis.js.map +1 -1
  4. package/dist/loaders/utils.d.ts.map +1 -1
  5. package/dist/loaders/utils.js +1 -1
  6. package/dist/loaders/utils.js.map +1 -1
  7. package/dist/migrations/Migration20231228143900.d.ts +1 -1
  8. package/dist/migrations/Migration20231228143900.d.ts.map +1 -1
  9. package/dist/migrations/Migration20231228143900.js +1 -1
  10. package/dist/migrations/Migration20231228143900.js.map +1 -1
  11. package/dist/migrations/Migration20241206123341.d.ts +1 -1
  12. package/dist/migrations/Migration20241206123341.d.ts.map +1 -1
  13. package/dist/migrations/Migration20241206123341.js +1 -1
  14. package/dist/migrations/Migration20241206123341.js.map +1 -1
  15. package/dist/migrations/Migration20250120111059.d.ts +1 -1
  16. package/dist/migrations/Migration20250120111059.d.ts.map +1 -1
  17. package/dist/migrations/Migration20250120111059.js +1 -1
  18. package/dist/migrations/Migration20250120111059.js.map +1 -1
  19. package/dist/migrations/Migration20250128174354.d.ts +1 -1
  20. package/dist/migrations/Migration20250128174354.d.ts.map +1 -1
  21. package/dist/migrations/Migration20250128174354.js +1 -1
  22. package/dist/migrations/Migration20250128174354.js.map +1 -1
  23. package/dist/migrations/Migration20250505101505.d.ts +6 -0
  24. package/dist/migrations/Migration20250505101505.d.ts.map +1 -0
  25. package/dist/migrations/Migration20250505101505.js +40 -0
  26. package/dist/migrations/Migration20250505101505.js.map +1 -0
  27. package/dist/migrations/Migration20250819110923.d.ts +6 -0
  28. package/dist/migrations/Migration20250819110923.d.ts.map +1 -0
  29. package/dist/migrations/Migration20250819110923.js +14 -0
  30. package/dist/migrations/Migration20250819110923.js.map +1 -0
  31. package/dist/migrations/Migration20250819110924.d.ts +6 -0
  32. package/dist/migrations/Migration20250819110924.d.ts.map +1 -0
  33. package/dist/migrations/Migration20250819110924.js +16 -0
  34. package/dist/migrations/Migration20250819110924.js.map +1 -0
  35. package/dist/migrations/Migration20250908080326.d.ts +6 -0
  36. package/dist/migrations/Migration20250908080326.d.ts.map +1 -0
  37. package/dist/migrations/Migration20250908080326.js +20 -0
  38. package/dist/migrations/Migration20250908080326.js.map +1 -0
  39. package/dist/models/workflow-execution.d.ts +1 -0
  40. package/dist/models/workflow-execution.d.ts.map +1 -1
  41. package/dist/models/workflow-execution.js +22 -1
  42. package/dist/models/workflow-execution.js.map +1 -1
  43. package/dist/services/workflow-orchestrator.d.ts +16 -3
  44. package/dist/services/workflow-orchestrator.d.ts.map +1 -1
  45. package/dist/services/workflow-orchestrator.js +247 -118
  46. package/dist/services/workflow-orchestrator.js.map +1 -1
  47. package/dist/services/workflows-module.d.ts +114 -9
  48. package/dist/services/workflows-module.d.ts.map +1 -1
  49. package/dist/services/workflows-module.js +113 -50
  50. package/dist/services/workflows-module.js.map +1 -1
  51. package/dist/tsconfig.tsbuildinfo +1 -1
  52. package/dist/utils/workflow-orchestrator-storage.d.ts +10 -3
  53. package/dist/utils/workflow-orchestrator-storage.d.ts.map +1 -1
  54. package/dist/utils/workflow-orchestrator-storage.js +343 -143
  55. package/dist/utils/workflow-orchestrator-storage.js.map +1 -1
  56. 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 (_, message) => {
40
- const { instanceId, data } = JSON.parse(message);
41
- await this.notify(data, false, instanceId);
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: result,
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 Error("Workflow ID is required");
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 Error(`Workflow with id "${workflowId}" not found.`);
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
- throw ret.thrownError;
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 Error(`Workflow with id "${workflowId}" not found.`);
173
+ throw new utils_1.MedusaError(utils_1.MedusaError.Types.NOT_FOUND, `Workflow with id "${workflowId}" not found.`);
167
174
  }
168
- const originalOnFinishHandler = events.onFinish;
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 hasFailed = [utils_1.TransactionState.FAILED].includes(ret.transaction.getFlow().state);
206
+ const transactionState = ret.transaction.getFlow().state;
207
+ const hasFailed = [utils_1.TransactionState.FAILED].includes(transactionState);
195
208
  const acknowledgement = {
196
- transactionId: context.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
- throw ret.thrownError;
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
- throw ret.thrownError;
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
- throw ret.thrownError;
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 = this.subscribers.get(workflowId) ?? new Map();
379
+ const subscribers = WorkflowOrchestratorService.subscribers.get(workflowId) ?? new Map();
316
380
  // Subscribe instance to redis
317
- if (!this.subscribers.has(workflowId)) {
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.indexOf((s) => s === subscriber || s._id === subscriberId);
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.slice(subscriberIndex, 1);
391
+ transactionSubscribers.splice(subscriberIndex, 1);
328
392
  }
329
393
  transactionSubscribers.push(subscriber);
330
394
  subscribers.set(transactionId, transactionSubscribers);
331
- this.subscribers.set(workflowId, subscribers);
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.slice(subscriberIndex, 1);
401
+ workflowSubscribers.splice(subscriberIndex, 1);
338
402
  }
339
403
  workflowSubscribers.push(subscriber);
340
404
  subscribers.set(AnySubscriber, workflowSubscribers);
341
- this.subscribers.set(workflowId, subscribers);
405
+ WorkflowOrchestratorService.subscribers.set(workflowId, subscribers);
342
406
  }
343
407
  unsubscribe({ workflowId, transactionId, subscriberOrId, }) {
344
- const subscribers = this.subscribers.get(workflowId) ?? new Map();
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
- const newTransactionSubscribers = filterSubscribers(transactionSubscribers);
359
- subscribers.set(transactionId, newTransactionSubscribers);
360
- this.subscribers.set(workflowId, subscribers);
361
- return;
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
- if (publish) {
373
- const channel = this.getChannelName(options.workflowId);
374
- const message = JSON.stringify({
375
- instanceId: this.instanceId,
376
- data: options,
377
- });
378
- await this.redisPublisher.publish(channel, message);
379
- }
380
- const { eventType, workflowId, transactionId, errors, result, step, response, } = options;
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
- else {
401
- try {
402
- handler(args);
403
- }
404
- catch (e) {
405
- __classPrivateFieldGet(this, _WorkflowOrchestratorService_logger, "f").error(e);
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
- notifySubscribers(transactionSubscribers);
413
- // removes transaction id subscribers on finish
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
- notifySubscribers(workflowSubscribers);
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({ eventType: "onTimeout" });
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({ eventType: "onBegin" });
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({ eventType: "onResume" });
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({ eventType: "onCompensateBegin" });
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({ eventType: "onFinish" });
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
- this.activeStepsCount++;
460
- await notify({ eventType: "onStepBegin", step });
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({ eventType: "onStepSuccess", step, response });
467
- this.activeStepsCount--;
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({ eventType: "onStepFailure", step, errors });
476
- this.activeStepsCount--;
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({ eventType: "onStepAwaiting", step });
481
- this.activeStepsCount--;
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({ eventType: "onCompensateStepSuccess", step, response });
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({ eventType: "onCompensateStepFailure", step, errors });
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