@hotmeshio/hotmesh 0.1.15 → 0.1.16

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 (134) hide show
  1. package/README.md +623 -209
  2. package/build/index.d.ts +14 -3
  3. package/build/index.js +17 -4
  4. package/build/modules/enums.d.ts +12 -12
  5. package/build/modules/enums.js +15 -25
  6. package/build/modules/errors.d.ts +16 -16
  7. package/build/modules/errors.js +28 -28
  8. package/build/modules/key.d.ts +0 -37
  9. package/build/modules/key.js +4 -45
  10. package/build/modules/utils.d.ts +7 -15
  11. package/build/modules/utils.js +21 -44
  12. package/build/package.json +18 -15
  13. package/build/services/activities/activity.d.ts +0 -31
  14. package/build/services/activities/activity.js +1 -50
  15. package/build/services/activities/await.js +0 -4
  16. package/build/services/activities/cycle.d.ts +0 -7
  17. package/build/services/activities/cycle.js +1 -16
  18. package/build/services/activities/hook.d.ts +0 -6
  19. package/build/services/activities/hook.js +2 -12
  20. package/build/services/activities/interrupt.js +0 -8
  21. package/build/services/activities/signal.d.ts +0 -6
  22. package/build/services/activities/signal.js +0 -15
  23. package/build/services/activities/trigger.d.ts +4 -5
  24. package/build/services/activities/trigger.js +22 -16
  25. package/build/services/activities/worker.js +0 -4
  26. package/build/services/collator/index.d.ts +0 -70
  27. package/build/services/collator/index.js +1 -91
  28. package/build/services/compiler/deployer.js +6 -38
  29. package/build/services/compiler/index.d.ts +0 -15
  30. package/build/services/compiler/index.js +0 -20
  31. package/build/services/compiler/validator.d.ts +0 -3
  32. package/build/services/compiler/validator.js +0 -25
  33. package/build/services/connector/clients/ioredis.js +0 -2
  34. package/build/services/connector/clients/redis.js +0 -2
  35. package/build/services/connector/index.js +0 -2
  36. package/build/services/engine/index.d.ts +1 -10
  37. package/build/services/engine/index.js +1 -48
  38. package/build/services/exporter/index.d.ts +0 -27
  39. package/build/services/exporter/index.js +0 -33
  40. package/build/services/hotmesh/index.d.ts +8 -4
  41. package/build/services/hotmesh/index.js +20 -19
  42. package/build/services/logger/index.js +0 -2
  43. package/build/services/mapper/index.d.ts +0 -14
  44. package/build/services/mapper/index.js +0 -14
  45. package/build/services/meshcall/index.d.ts +21 -0
  46. package/build/services/meshcall/index.js +202 -0
  47. package/build/services/meshcall/schemas/factory.d.ts +2 -0
  48. package/build/services/meshcall/schemas/factory.js +179 -0
  49. package/build/services/meshdata/index.d.ts +75 -0
  50. package/build/services/meshdata/index.js +541 -0
  51. package/build/services/meshflow/client.d.ts +18 -0
  52. package/build/services/{durable → meshflow}/client.js +9 -40
  53. package/build/services/{durable → meshflow}/connection.d.ts +2 -1
  54. package/build/services/{durable → meshflow}/connection.js +1 -0
  55. package/build/services/meshflow/exporter.d.ts +29 -0
  56. package/build/services/{durable → meshflow}/exporter.js +0 -29
  57. package/build/services/meshflow/handle.d.ts +22 -0
  58. package/build/services/{durable → meshflow}/handle.js +0 -46
  59. package/build/services/meshflow/index.d.ts +17 -0
  60. package/build/services/meshflow/index.js +23 -0
  61. package/build/services/meshflow/schemas/factory.d.ts +4 -0
  62. package/build/services/{durable → meshflow}/schemas/factory.js +2 -30
  63. package/build/services/meshflow/search.d.ts +23 -0
  64. package/build/services/{durable → meshflow}/search.js +0 -99
  65. package/build/services/{durable → meshflow}/worker.d.ts +3 -2
  66. package/build/services/{durable → meshflow}/worker.js +23 -39
  67. package/build/services/meshflow/workflow.d.ts +27 -0
  68. package/build/services/{durable → meshflow}/workflow.js +27 -169
  69. package/build/services/pipe/functions/date.d.ts +0 -7
  70. package/build/services/pipe/functions/date.js +0 -7
  71. package/build/services/pipe/functions/math.js +0 -2
  72. package/build/services/pipe/index.d.ts +0 -15
  73. package/build/services/pipe/index.js +2 -23
  74. package/build/services/quorum/index.d.ts +1 -7
  75. package/build/services/quorum/index.js +0 -21
  76. package/build/services/reporter/index.d.ts +0 -5
  77. package/build/services/reporter/index.js +0 -9
  78. package/build/services/router/index.d.ts +0 -9
  79. package/build/services/router/index.js +2 -30
  80. package/build/services/serializer/index.js +6 -23
  81. package/build/services/store/cache.d.ts +0 -19
  82. package/build/services/store/cache.js +0 -19
  83. package/build/services/store/clients/ioredis.d.ts +0 -6
  84. package/build/services/store/clients/ioredis.js +0 -7
  85. package/build/services/store/clients/redis.d.ts +0 -6
  86. package/build/services/store/clients/redis.js +0 -6
  87. package/build/services/store/index.d.ts +0 -55
  88. package/build/services/store/index.js +14 -87
  89. package/build/services/stream/clients/ioredis.js +1 -4
  90. package/build/services/task/index.d.ts +0 -9
  91. package/build/services/task/index.js +0 -31
  92. package/build/services/telemetry/index.d.ts +0 -7
  93. package/build/services/telemetry/index.js +1 -13
  94. package/build/services/worker/index.d.ts +1 -4
  95. package/build/services/worker/index.js +0 -6
  96. package/build/types/activity.d.ts +0 -81
  97. package/build/types/error.d.ts +5 -5
  98. package/build/types/exporter.d.ts +1 -14
  99. package/build/types/hotmesh.d.ts +4 -12
  100. package/build/types/hotmesh.js +0 -3
  101. package/build/types/index.d.ts +5 -3
  102. package/build/types/index.js +1 -1
  103. package/build/types/job.d.ts +1 -95
  104. package/build/types/meshcall.d.ts +54 -0
  105. package/build/types/meshdata.d.ts +59 -0
  106. package/build/types/meshdata.js +2 -0
  107. package/build/types/meshflow.d.ts +202 -0
  108. package/build/types/meshflow.js +2 -0
  109. package/build/types/pipe.d.ts +0 -65
  110. package/build/types/quorum.d.ts +0 -12
  111. package/build/types/redis.d.ts +0 -6
  112. package/build/types/stream.d.ts +0 -59
  113. package/build/types/stream.js +0 -4
  114. package/index.ts +22 -3
  115. package/package.json +18 -15
  116. package/typedoc.json +38 -0
  117. package/types/error.ts +5 -5
  118. package/types/exporter.ts +1 -1
  119. package/types/hotmesh.ts +3 -2
  120. package/types/index.ts +25 -7
  121. package/types/job.ts +19 -1
  122. package/types/meshcall.ts +123 -0
  123. package/types/meshdata.ts +273 -0
  124. package/types/{durable.ts → meshflow.ts} +33 -9
  125. package/build/services/durable/client.d.ts +0 -49
  126. package/build/services/durable/exporter.d.ts +0 -51
  127. package/build/services/durable/handle.d.ts +0 -58
  128. package/build/services/durable/index.d.ts +0 -19
  129. package/build/services/durable/index.js +0 -25
  130. package/build/services/durable/schemas/factory.d.ts +0 -33
  131. package/build/services/durable/search.d.ts +0 -120
  132. package/build/services/durable/workflow.d.ts +0 -143
  133. package/build/types/durable.d.ts +0 -467
  134. /package/build/types/{durable.js → meshcall.js} +0 -0
@@ -15,6 +15,7 @@ const stream_1 = require("../../types/stream");
15
15
  const search_1 = require("./search");
16
16
  const factory_1 = require("./schemas/factory");
17
17
  class WorkerService {
18
+ constructor() { }
18
19
  static async activateWorkflow(hotMesh) {
19
20
  const app = await hotMesh.engine.store.getApp(hotMesh.engine.appId);
20
21
  const appVersion = app?.version;
@@ -63,7 +64,6 @@ class WorkerService {
63
64
  const baseTopic = `${config.taskQueue}-${workflowFunctionName}`;
64
65
  const activityTopic = `${baseTopic}-activity`;
65
66
  const workflowTopic = `${baseTopic}`;
66
- //initialize supporting workflows
67
67
  const worker = new WorkerService();
68
68
  worker.activityRunner = await worker.initActivityWorker(config, activityTopic);
69
69
  worker.workflowRunner = await worker.initWorkflowWorker(config, workflowTopic, workflowFunction);
@@ -95,7 +95,8 @@ class WorkerService {
95
95
  const targetNamespace = config?.namespace ?? factory_1.APP_ID;
96
96
  const optionsHash = (0, utils_1.hashOptions)(config?.connection?.options);
97
97
  const targetTopic = `${optionsHash}.${targetNamespace}.${activityTopic}`;
98
- const hotMeshWorker = await hotmesh_1.HotMeshService.init({
98
+ const hotMeshWorker = await hotmesh_1.HotMesh.init({
99
+ guid: config.guid ? `${config.guid}XA` : undefined,
99
100
  logLevel: config.options?.logLevel ?? enums_1.HMSH_LOGLEVEL,
100
101
  appId: targetNamespace,
101
102
  engine: { redis: redisConfig },
@@ -113,7 +114,6 @@ class WorkerService {
113
114
  wrapActivityFunctions() {
114
115
  return async (data) => {
115
116
  try {
116
- //always run the activity function when instructed; return the response
117
117
  const activityInput = data.data;
118
118
  const activityName = activityInput.activityName;
119
119
  const activityFunction = WorkerService.activityRegistry[activityName];
@@ -130,14 +130,12 @@ class WorkerService {
130
130
  message: err.message,
131
131
  stack: err.stack,
132
132
  });
133
- if (!(err instanceof errors_1.DurableTimeoutError) &&
134
- !(err instanceof errors_1.DurableMaxedError) &&
135
- !(err instanceof errors_1.DurableFatalError)) {
136
- //use code 599 as a proxy for all retryable errors
137
- // (basically anything not 596, 597, 598)
133
+ if (!(err instanceof errors_1.MeshFlowTimeoutError) &&
134
+ !(err instanceof errors_1.MeshFlowMaxedError) &&
135
+ !(err instanceof errors_1.MeshFlowFatalError)) {
138
136
  return {
139
137
  status: stream_1.StreamStatus.SUCCESS,
140
- code: enums_1.HMSH_CODE_DURABLE_RETRYABLE,
138
+ code: enums_1.HMSH_CODE_MESHFLOW_RETRYABLE,
141
139
  metadata: { ...data.metadata },
142
140
  data: {
143
141
  $error: {
@@ -149,8 +147,6 @@ class WorkerService {
149
147
  };
150
148
  }
151
149
  return {
152
- //always returrn success (the Durable module is just fine);
153
- // it's the user's function that has failed
154
150
  status: stream_1.StreamStatus.SUCCESS,
155
151
  code: err.code,
156
152
  stack: err.stack,
@@ -175,7 +171,8 @@ class WorkerService {
175
171
  const targetNamespace = config?.namespace ?? factory_1.APP_ID;
176
172
  const optionsHash = (0, utils_1.hashOptions)(config?.connection?.options);
177
173
  const targetTopic = `${optionsHash}.${targetNamespace}.${workflowTopic}`;
178
- const hotMeshWorker = await hotmesh_1.HotMeshService.init({
174
+ const hotMeshWorker = await hotmesh_1.HotMesh.init({
175
+ guid: config.guid,
179
176
  logLevel: config.options?.logLevel ?? enums_1.HMSH_LOGLEVEL,
180
177
  appId: config.namespace ?? factory_1.APP_ID,
181
178
  engine: { redis: redisConfig },
@@ -196,7 +193,6 @@ class WorkerService {
196
193
  const interruptionRegistry = [];
197
194
  let isProcessing = false;
198
195
  try {
199
- //incoming data payload has arguments and workflowId
200
196
  const workflowInput = data.data;
201
197
  const context = new Map();
202
198
  context.set('canRetry', workflowInput.canRetry);
@@ -207,20 +203,14 @@ class WorkerService {
207
203
  context.set('raw', data);
208
204
  context.set('workflowId', workflowInput.workflowId);
209
205
  if (workflowInput.originJobId) {
210
- //if present there is an origin job to which this job is subordinated;
211
- // garbage collect (expire) this job when originJobId is expired
212
206
  context.set('originJobId', workflowInput.originJobId);
213
207
  }
214
208
  let replayQuery = '';
215
209
  if (workflowInput.workflowDimension) {
216
- //every hook function runs in an isolated dimension controlled
217
- //by the index assigned when the signal was received; even if the
218
- //hook function re-runs, its scope will always remain constant
219
210
  context.set('workflowDimension', workflowInput.workflowDimension);
220
211
  replayQuery = `-*${workflowInput.workflowDimension}-*`;
221
212
  }
222
213
  else {
223
- //last letter of words like 'hook', 'sleep', 'wait', 'signal', 'search', 'start', 'proxy', 'child', 'collator'
224
214
  replayQuery = '-*[ehklptydr]-*';
225
215
  }
226
216
  context.set('workflowTopic', workflowTopic);
@@ -230,7 +220,7 @@ class WorkerService {
230
220
  const store = this.workflowRunner.engine.store;
231
221
  const [cursor, replay] = await store.findJobFields(workflowInput.workflowId, replayQuery, 50000, 5000);
232
222
  context.set('replay', replay);
233
- context.set('cursor', cursor); // if != 0, more remain
223
+ context.set('cursor', cursor);
234
224
  const workflowResponse = await storage_1.asyncLocalStorage.run(context, async () => {
235
225
  return await workflowFunction.apply(this, workflowInput.arguments);
236
226
  });
@@ -245,20 +235,19 @@ class WorkerService {
245
235
  if (isProcessing) {
246
236
  return;
247
237
  }
248
- if (err instanceof errors_1.DurableWaitForError ||
238
+ if (err instanceof errors_1.MeshFlowWaitForError ||
249
239
  interruptionRegistry.length > 1) {
250
240
  isProcessing = true;
251
- //NOTE: this type is spawned when `Promise.all` is used OR if the interruption is a `waitFor`
252
241
  const workflowInput = data.data;
253
242
  const execIndex = counter.counter - interruptionRegistry.length + 1;
254
243
  const { workflowId, workflowTopic, workflowDimension, originJobId } = workflowInput;
255
244
  const collatorFlowId = `${(0, utils_1.guid)()}$C`;
256
245
  return {
257
246
  status: stream_1.StreamStatus.SUCCESS,
258
- code: enums_1.HMSH_CODE_DURABLE_ALL,
247
+ code: enums_1.HMSH_CODE_MESHFLOW_ALL,
259
248
  metadata: { ...data.metadata },
260
249
  data: {
261
- code: enums_1.HMSH_CODE_DURABLE_ALL,
250
+ code: enums_1.HMSH_CODE_MESHFLOW_ALL,
262
251
  items: [...interruptionRegistry],
263
252
  size: interruptionRegistry.length,
264
253
  workflowDimension: workflowDimension || '',
@@ -270,8 +259,7 @@ class WorkerService {
270
259
  },
271
260
  };
272
261
  }
273
- else if (err instanceof errors_1.DurableSleepError) {
274
- //return the sleep interruption
262
+ else if (err instanceof errors_1.MeshFlowSleepError) {
275
263
  isProcessing = true;
276
264
  return {
277
265
  status: stream_1.StreamStatus.SUCCESS,
@@ -290,8 +278,7 @@ class WorkerService {
290
278
  },
291
279
  };
292
280
  }
293
- else if (err instanceof errors_1.DurableProxyError) {
294
- //return the proxyActivity interruption
281
+ else if (err instanceof errors_1.MeshFlowProxyError) {
295
282
  isProcessing = true;
296
283
  return {
297
284
  status: stream_1.StreamStatus.SUCCESS,
@@ -320,8 +307,7 @@ class WorkerService {
320
307
  },
321
308
  };
322
309
  }
323
- else if (err instanceof errors_1.DurableChildError) {
324
- //return the child interruption
310
+ else if (err instanceof errors_1.MeshFlowChildError) {
325
311
  isProcessing = true;
326
312
  const msg = {
327
313
  message: err.message,
@@ -335,12 +321,12 @@ class WorkerService {
335
321
  data: {
336
322
  arguments: err.arguments,
337
323
  await: err.await,
338
- backoffCoefficient: err.backoffCoefficient || enums_1.HMSH_DURABLE_EXP_BACKOFF,
324
+ backoffCoefficient: err.backoffCoefficient || enums_1.HMSH_MESHFLOW_EXP_BACKOFF,
339
325
  code: err.code,
340
326
  index: err.index,
341
327
  message: JSON.stringify(msg),
342
- maximumAttempts: err.maximumAttempts || enums_1.HMSH_DURABLE_MAX_ATTEMPTS,
343
- maximumInterval: err.maximumInterval || (0, ms_1.default)(enums_1.HMSH_DURABLE_MAX_INTERVAL) / 1000,
328
+ maximumAttempts: err.maximumAttempts || enums_1.HMSH_MESHFLOW_MAX_ATTEMPTS,
329
+ maximumInterval: err.maximumInterval || (0, ms_1.default)(enums_1.HMSH_MESHFLOW_MAX_INTERVAL) / 1000,
344
330
  originJobId: err.originJobId,
345
331
  parentWorkflowId: err.parentWorkflowId,
346
332
  expire: err.expire,
@@ -351,12 +337,10 @@ class WorkerService {
351
337
  },
352
338
  };
353
339
  }
354
- // ALL other errors are actual fatal errors (598, 597, 596)
355
- // OR will be retried (599)
356
340
  isProcessing = true;
357
341
  return {
358
342
  status: stream_1.StreamStatus.SUCCESS,
359
- code: err.code || new errors_1.DurableRetryError(err.message).code,
343
+ code: err.code || new errors_1.MeshFlowRetryError(err.message).code,
360
344
  metadata: { ...data.metadata },
361
345
  data: {
362
346
  $error: {
@@ -364,7 +348,7 @@ class WorkerService {
364
348
  type: err.name,
365
349
  name: err.name,
366
350
  stack: err.stack,
367
- code: err.code || new errors_1.DurableRetryError(err.message).code,
351
+ code: err.code || new errors_1.MeshFlowRetryError(err.message).code,
368
352
  },
369
353
  },
370
354
  };
@@ -378,7 +362,7 @@ class WorkerService {
378
362
  }
379
363
  }
380
364
  _a = WorkerService;
381
- WorkerService.activityRegistry = {}; //user's activities
365
+ WorkerService.activityRegistry = {};
382
366
  WorkerService.instances = new Map();
383
367
  WorkerService.getHotMesh = async (workflowTopic, config, options) => {
384
368
  const targetNamespace = config?.namespace ?? factory_1.APP_ID;
@@ -387,7 +371,7 @@ WorkerService.getHotMesh = async (workflowTopic, config, options) => {
387
371
  if (WorkerService.instances.has(targetTopic)) {
388
372
  return await WorkerService.instances.get(targetTopic);
389
373
  }
390
- const hotMeshClient = hotmesh_1.HotMeshService.init({
374
+ const hotMeshClient = hotmesh_1.HotMesh.init({
391
375
  logLevel: options?.logLevel ?? enums_1.HMSH_LOGLEVEL,
392
376
  appId: targetNamespace,
393
377
  engine: {
@@ -0,0 +1,27 @@
1
+ import { HotMesh } from '../hotmesh';
2
+ import { ActivityConfig, HookOptions, ProxyType, WorkflowContext, WorkflowOptions } from '../../types/meshflow';
3
+ import { JobInterruptOptions } from '../../types/job';
4
+ import { MeshFlowChildErrorType, MeshFlowProxyErrorType } from '../../types/error';
5
+ import { Search } from './search';
6
+ export declare class WorkflowService {
7
+ constructor();
8
+ static didRun(prefix: string): Promise<[boolean, number, any]>;
9
+ static isSideEffectAllowed(hotMeshClient: HotMesh, prefix: string): Promise<boolean>;
10
+ static getContext(): WorkflowContext;
11
+ static getHotMesh(): Promise<HotMesh>;
12
+ static execChild<T>(options: WorkflowOptions): Promise<T>;
13
+ static getChildInterruptPayload(context: WorkflowContext, options: WorkflowOptions, execIndex: number): MeshFlowChildErrorType;
14
+ static startChild(options: WorkflowOptions): Promise<string>;
15
+ static proxyActivities<ACT>(options?: ActivityConfig): ProxyType<ACT>;
16
+ static wrapActivity<T>(activityName: string, options?: ActivityConfig): T;
17
+ static getProxyInterruptPayload(context: WorkflowContext, activityName: string, execIndex: number, args: any[], options?: ActivityConfig): MeshFlowProxyErrorType;
18
+ static search(): Promise<Search>;
19
+ static random(): number;
20
+ static signal(signalId: string, data: Record<any, any>): Promise<string>;
21
+ static hook(options: HookOptions): Promise<string>;
22
+ static once<T>(fn: (...args: any[]) => Promise<T>, ...args: any[]): Promise<T>;
23
+ static interrupt(jobId: string, options?: JobInterruptOptions): Promise<string | void>;
24
+ static all<T>(...promises: Promise<T>[]): Promise<T[]>;
25
+ static sleepFor(duration: string): Promise<number>;
26
+ static waitFor<T>(signalId: string): Promise<T>;
27
+ }
@@ -15,13 +15,7 @@ const enums_1 = require("../../modules/enums");
15
15
  const worker_1 = require("./worker");
16
16
  const search_1 = require("./search");
17
17
  class WorkflowService {
18
- /**
19
- * Returns the synchronous output from the activity (replay)
20
- * if available locally, revealing whether or not the activity already
21
- * ran during a prior execution cycle
22
- * @param {string} prefix - one of: proxy, child, start, wait etc
23
- * @returns
24
- */
18
+ constructor() { }
25
19
  static async didRun(prefix) {
26
20
  const { COUNTER, replay, workflowDimension } = WorkflowService.getContext();
27
21
  const execIndex = COUNTER.counter = COUNTER.counter + 1;
@@ -32,12 +26,6 @@ class WorkflowService {
32
26
  }
33
27
  return [false, execIndex, null];
34
28
  }
35
- /**
36
- * Those methods that may only be called once must be protected by flagging
37
- * their execution with a unique key (the key is stored in the HASH alongside
38
- * process state and job state)
39
- * @private
40
- */
41
29
  static async isSideEffectAllowed(hotMeshClient, prefix) {
42
30
  const store = storage_1.asyncLocalStorage.getStore();
43
31
  const workflowId = store.get('workflowId');
@@ -57,10 +45,6 @@ class WorkflowService {
57
45
  const guidValue = Number((await hotMeshClient.engine.store.exec('HINCRBYFLOAT', workflowGuid, sessionId, '1')));
58
46
  return guidValue === 1;
59
47
  }
60
- /**
61
- * Returns the current workflow context restored
62
- * from Redis
63
- */
64
48
  static getContext() {
65
49
  const store = storage_1.asyncLocalStorage.getStore();
66
50
  const workflowId = store.get('workflowId');
@@ -95,10 +79,6 @@ class WorkflowService {
95
79
  workflowSpan,
96
80
  };
97
81
  }
98
- /**
99
- * Return a handle to the hotmesh client hosting the workflow execution
100
- * @returns {Promise<HotMesh>} - a hotmesh client
101
- */
102
82
  static async getHotMesh() {
103
83
  const store = storage_1.asyncLocalStorage.getStore();
104
84
  const workflowTopic = store.get('workflowTopic');
@@ -106,17 +86,7 @@ class WorkflowService {
106
86
  const namespace = store.get('namespace');
107
87
  return await worker_1.WorkerService.getHotMesh(workflowTopic, { connection, namespace });
108
88
  }
109
- /**
110
- * Spawns a child workflow and awaits the return.
111
- * @template T - the result type
112
- * @param {WorkflowOptions} options - the workflow options
113
- * @returns {Promise<T>} - the result of the child workflow
114
- * @example
115
- * const result = await Durable.workflow.execChild<typeof resultType>({ ...options });
116
- */
117
89
  static async execChild(options) {
118
- //SYNC
119
- //check if the activity already ran (check $error/done)
120
90
  const isStartChild = options.await === false;
121
91
  const prefix = isStartChild ? 'start' : 'child';
122
92
  const [didRun, execIndex, result] = await WorkflowService.didRun(prefix);
@@ -127,21 +97,20 @@ class WorkflowService {
127
97
  (!result.$error.is_stream_error ||
128
98
  result.$error.is_stream_error && !canRetry)) {
129
99
  if (options?.config?.throwOnError !== false) {
130
- //rethrow remote execution error (simulates local failure)
131
100
  const code = result.$error.code;
132
101
  const message = result.$error.message;
133
102
  const stack = result.$error.stack;
134
- if (code === enums_1.HMSH_CODE_DURABLE_FATAL) {
135
- throw new errors_1.DurableFatalError(message, stack);
103
+ if (code === enums_1.HMSH_CODE_MESHFLOW_FATAL) {
104
+ throw new errors_1.MeshFlowFatalError(message, stack);
136
105
  }
137
- else if (code == enums_1.HMSH_CODE_DURABLE_MAXED) {
138
- throw new errors_1.DurableMaxedError(message, stack);
106
+ else if (code == enums_1.HMSH_CODE_MESHFLOW_MAXED) {
107
+ throw new errors_1.MeshFlowMaxedError(message, stack);
139
108
  }
140
- else if (code == enums_1.HMSH_CODE_DURABLE_TIMEOUT) {
141
- throw new errors_1.DurableTimeoutError(message, stack);
109
+ else if (code == enums_1.HMSH_CODE_MESHFLOW_TIMEOUT) {
110
+ throw new errors_1.MeshFlowTimeoutError(message, stack);
142
111
  }
143
112
  else {
144
- throw new errors_1.DurableRetryError(message, stack);
113
+ throw new errors_1.MeshFlowRetryError(message, stack);
145
114
  }
146
115
  }
147
116
  return result.$error;
@@ -151,20 +120,13 @@ class WorkflowService {
151
120
  }
152
121
  }
153
122
  const interruptionMessage = WorkflowService.getChildInterruptPayload(context, options, execIndex);
154
- //push the packaged inputs to the registry
155
123
  interruptionRegistry.push({
156
- code: enums_1.HMSH_CODE_DURABLE_CHILD,
124
+ code: enums_1.HMSH_CODE_MESHFLOW_CHILD,
157
125
  ...interruptionMessage,
158
126
  });
159
- //ASYNC
160
- //sleep (allow others to be packaged / registered) and throw the error
161
127
  await (0, utils_1.sleepImmediate)();
162
- throw new errors_1.DurableChildError(interruptionMessage);
128
+ throw new errors_1.MeshFlowChildError(interruptionMessage);
163
129
  }
164
- /**
165
- * constructs the payload necessary to spawn a child job
166
- * @private
167
- */
168
130
  static getChildInterruptPayload(context, options, execIndex) {
169
131
  const { workflowId, originJobId, workflowDimension } = context;
170
132
  let childJobId;
@@ -184,10 +146,10 @@ class WorkflowService {
184
146
  return {
185
147
  arguments: [...(options.args || [])],
186
148
  await: options?.await ?? true,
187
- backoffCoefficient: options?.config?.backoffCoefficient ?? enums_1.HMSH_DURABLE_EXP_BACKOFF,
149
+ backoffCoefficient: options?.config?.backoffCoefficient ?? enums_1.HMSH_MESHFLOW_EXP_BACKOFF,
188
150
  index: execIndex,
189
- maximumAttempts: options?.config?.maximumAttempts ?? enums_1.HMSH_DURABLE_MAX_ATTEMPTS,
190
- maximumInterval: (0, ms_1.default)(options?.config?.maximumInterval ?? enums_1.HMSH_DURABLE_MAX_INTERVAL) /
151
+ maximumAttempts: options?.config?.maximumAttempts ?? enums_1.HMSH_MESHFLOW_MAX_ATTEMPTS,
152
+ maximumInterval: (0, ms_1.default)(options?.config?.maximumInterval ?? enums_1.HMSH_MESHFLOW_MAX_INTERVAL) /
191
153
  1000,
192
154
  originJobId: originJobId ?? workflowId,
193
155
  expire: options.expire,
@@ -198,37 +160,9 @@ class WorkflowService {
198
160
  workflowTopic,
199
161
  };
200
162
  }
201
- /**
202
- * Spawns a child workflow and returns the child Job ID.
203
- * This method guarantees the spawned child has reserved the Job ID,
204
- * returning a 'DuplicateJobError' error if not. Otherwise,
205
- * this is a fire-and-forget method.
206
- *
207
- * @param {WorkflowOptions} options - the workflow options
208
- * @returns {Promise<string>} - the childJobId
209
- * @example
210
- * const childJobId = await Durable.workflow.startChild({ ...options });
211
- */
212
163
  static async startChild(options) {
213
164
  return WorkflowService.execChild({ ...options, await: false });
214
165
  }
215
- /**
216
- * Wraps activities in a proxy that durably runs/re-runs them to completion.
217
- * TODO: verify that activities do not collide if named same on same server but bound to different workflows
218
- *
219
- * @param {ActivityConfig} options - the activity configuration
220
- * that will be used to wrap the activities.
221
- * @returns {ProxyType<ACT>} - a proxy object with the same keys as the
222
- * activities object, but with the values replaced by a wrapped function
223
- *
224
- * @example
225
- * // import the activities
226
- * import * as activities from './activities';
227
- * const proxy = WorkflowService.proxyActivities<typeof activities>({ activities });
228
- *
229
- * //or destructure the proxy object, as the function names are the keys
230
- * const { activity1, activity2 } = WorkflowService.proxyActivities<typeof activities>({ activities });
231
- */
232
166
  static proxyActivities(options) {
233
167
  if (options.activities) {
234
168
  worker_1.WorkerService.registerActivities(options.activities);
@@ -245,49 +179,38 @@ class WorkflowService {
245
179
  }
246
180
  static wrapActivity(activityName, options) {
247
181
  return async function () {
248
- //SYNC
249
- //check if the activity already ran
250
182
  const [didRun, execIndex, result] = await WorkflowService.didRun('proxy');
251
183
  if (didRun) {
252
184
  if (result?.$error) {
253
185
  if (options?.retryPolicy?.throwOnError !== false) {
254
- //rethrow remote execution error (simulates throw)
255
186
  const code = result.$error.code;
256
187
  const message = result.$error.message;
257
188
  const stack = result.$error.stack;
258
- if (code === enums_1.HMSH_CODE_DURABLE_FATAL) {
259
- throw new errors_1.DurableFatalError(message, stack);
189
+ if (code === enums_1.HMSH_CODE_MESHFLOW_FATAL) {
190
+ throw new errors_1.MeshFlowFatalError(message, stack);
260
191
  }
261
- else if (code == enums_1.HMSH_CODE_DURABLE_MAXED) {
262
- throw new errors_1.DurableMaxedError(message, stack);
192
+ else if (code == enums_1.HMSH_CODE_MESHFLOW_MAXED) {
193
+ throw new errors_1.MeshFlowMaxedError(message, stack);
263
194
  }
264
- else if (code == enums_1.HMSH_CODE_DURABLE_TIMEOUT) {
265
- throw new errors_1.DurableTimeoutError(message, stack);
195
+ else if (code == enums_1.HMSH_CODE_MESHFLOW_TIMEOUT) {
196
+ throw new errors_1.MeshFlowTimeoutError(message, stack);
266
197
  }
267
198
  }
268
199
  return result.$error;
269
200
  }
270
201
  return result.data;
271
202
  }
272
- //package the interruption inputs
273
203
  const context = WorkflowService.getContext();
274
204
  const { interruptionRegistry } = context;
275
205
  const interruptionMessage = WorkflowService.getProxyInterruptPayload(context, activityName, execIndex, Array.from(arguments), options);
276
- //push the packaged inputs to the registry
277
206
  interruptionRegistry.push({
278
- code: enums_1.HMSH_CODE_DURABLE_PROXY,
207
+ code: enums_1.HMSH_CODE_MESHFLOW_PROXY,
279
208
  ...interruptionMessage,
280
209
  });
281
- //ASYNC
282
- //sleep (allow others to be packaged / registered) and throw the error
283
210
  await (0, utils_1.sleepImmediate)();
284
- throw new errors_1.DurableProxyError(interruptionMessage);
211
+ throw new errors_1.MeshFlowProxyError(interruptionMessage);
285
212
  };
286
213
  }
287
- /**
288
- * constructs the payload necessary to spawn a proxyActivity job
289
- * @private
290
- */
291
214
  static getProxyInterruptPayload(context, activityName, execIndex, args, options) {
292
215
  const { workflowDimension, workflowId, originJobId, workflowTopic } = context;
293
216
  const activityTopic = `${workflowTopic}-activity`;
@@ -311,11 +234,6 @@ class WorkflowService {
311
234
  maximumInterval: maximumInterval ?? undefined,
312
235
  };
313
236
  }
314
- /**
315
- * Returns a search session for use when reading/writing to the workflow HASH.
316
- * The search session provides access to methods like `get`, `mget`, `set`, `del`, and `incr`.
317
- * @returns {Promise<Search>} - a search session
318
- */
319
237
  static async search() {
320
238
  const store = storage_1.asyncLocalStorage.getStore();
321
239
  const workflowId = store.get('workflowId');
@@ -329,29 +247,15 @@ class WorkflowService {
329
247
  connection,
330
248
  namespace,
331
249
  });
332
- //this ID is used as a item key with a hash (dash prefix ensures no collision)
333
250
  const searchSessionId = `-search${workflowDimension}-${execIndex}`;
334
251
  return new search_1.Search(workflowId, hotMeshClient, searchSessionId);
335
252
  }
336
- /**
337
- * Returns a random number between 0 and 1. This number is deterministic
338
- * and will never vary for a given seed. This is useful for randomizing
339
- * pathways in a workflow that can be safely replayed.
340
- * @returns {number} - a random number between 0 and 1
341
- */
342
253
  static random() {
343
254
  const store = storage_1.asyncLocalStorage.getStore();
344
255
  const COUNTER = store.get('counter');
345
256
  const seed = COUNTER.counter = COUNTER.counter + 1;
346
257
  return (0, utils_1.deterministicRandom)(seed);
347
258
  }
348
- /**
349
- * Sends signal data into any other paused thread (which is currently
350
- * awaiting the signal)
351
- * @param {string} signalId - the signal id
352
- * @param {Record<any, any>} data - the signal data
353
- * @returns {Promise<string>} - the stream id
354
- */
355
259
  static async signal(signalId, data) {
356
260
  const store = storage_1.asyncLocalStorage.getStore();
357
261
  const workflowTopic = store.get('workflowTopic');
@@ -368,12 +272,6 @@ class WorkflowService {
368
272
  });
369
273
  }
370
274
  }
371
- /**
372
- * Spawns a hook from either the main thread or a hook thread with
373
- * the provided options; worflowId/TaskQueue/Name are optional and will
374
- * default to the current workflowId/WorkflowTopic if not provided
375
- * @param {HookOptions} options - the hook options
376
- */
377
275
  static async hook(options) {
378
276
  const { workflowId, connection, namespace, workflowTopic } = WorkflowService.getContext();
379
277
  const hotMeshClient = await worker_1.WorkerService.getHotMesh(workflowTopic, {
@@ -393,18 +291,11 @@ class WorkflowService {
393
291
  arguments: [...options.args],
394
292
  id: targetWorkflowId,
395
293
  workflowTopic,
396
- backoffCoefficient: options.config?.backoffCoefficient || enums_1.HMSH_DURABLE_EXP_BACKOFF,
294
+ backoffCoefficient: options.config?.backoffCoefficient || enums_1.HMSH_MESHFLOW_EXP_BACKOFF,
397
295
  };
398
296
  return await hotMeshClient.hook(`${namespace}.flow.signal`, payload, stream_1.StreamStatus.PENDING, 202);
399
297
  }
400
298
  }
401
- /**
402
- * Executes a function once and caches the result. If the function is called
403
- * again, the cached result is returned. This is useful for wrapping
404
- * expensive activity calls that should only be run once, but which might
405
- * not require the cost and safety provided by proxyActivities.
406
- * @template T - the result type
407
- */
408
299
  static async once(fn, ...args) {
409
300
  const { COUNTER, connection, namespace, workflowId, workflowTopic, workflowDimension, replay, } = WorkflowService.getContext();
410
301
  const execIndex = COUNTER.counter = COUNTER.counter + 1;
@@ -432,9 +323,6 @@ class WorkflowService {
432
323
  await hotMeshClient.engine.store.exec('HSET', workflowGuid, sessionId, serializer_1.SerializerService.toString(payload));
433
324
  return response;
434
325
  }
435
- /**
436
- * Interrupts a running job
437
- */
438
326
  static async interrupt(jobId, options = {}) {
439
327
  const { workflowTopic, connection, namespace, } = WorkflowService.getContext();
440
328
  const hotMeshClient = await worker_1.WorkerService.getHotMesh(workflowTopic, {
@@ -445,28 +333,15 @@ class WorkflowService {
445
333
  return await hotMeshClient.interrupt(`${hotMeshClient.appId}.execute`, jobId, options);
446
334
  }
447
335
  }
448
- /**
449
- * Promise.all (limited to 25 total concurrent workflow)
450
- */
451
336
  static async all(...promises) {
452
337
  await new Promise((resolve) => setTimeout(resolve, 1));
453
338
  return await Promise.all(promises);
454
339
  }
455
- /**
456
- * Sleeps the workflow for a duration. As the function is reentrant,
457
- * upon reentry, the function will traverse prior execution paths up
458
- * until the sleep command and then resume execution thereafter.
459
- * @param {string} duration - See the `ms` package for syntax examples: '1 minute', '2 hours', '3 days'
460
- * @returns {Promise<number>} - resolved duration in seconds
461
- */
462
340
  static async sleepFor(duration) {
463
- //SYNC
464
- //return early if this sleep command has already run
465
341
  const [didRun, execIndex, result] = await WorkflowService.didRun('sleep');
466
342
  if (didRun) {
467
- return result.duration; //in seconds
343
+ return result.duration;
468
344
  }
469
- //package the interruption inputs
470
345
  const store = storage_1.asyncLocalStorage.getStore();
471
346
  const interruptionRegistry = store.get('interruptionRegistry');
472
347
  const workflowId = store.get('workflowId');
@@ -478,31 +353,17 @@ class WorkflowService {
478
353
  workflowDimension,
479
354
  };
480
355
  interruptionRegistry.push({
481
- code: enums_1.HMSH_CODE_DURABLE_SLEEP,
356
+ code: enums_1.HMSH_CODE_MESHFLOW_SLEEP,
482
357
  ...interruptionMessage,
483
358
  });
484
- //ASYNC
485
- //sleep to allow other interruptions to be packaged and registered
486
359
  await (0, utils_1.sleepImmediate)();
487
- // NOTE: If you are reading this in the stack trace, await `sleepFor`
488
- throw new errors_1.DurableSleepError(interruptionMessage);
360
+ throw new errors_1.MeshFlowSleepError(interruptionMessage);
489
361
  }
490
- /**
491
- * Pauses the workflow until `signalId` is received.
492
- * @template T - the result type
493
- * @param {string} signalId - a unique, shareable guid (e.g, 'abc123')
494
- * @returns {Promise<T>}
495
- * @example
496
- * const result = await Durable.workflow.waitFor<typeof resultType>('abc123');
497
- */
498
362
  static async waitFor(signalId) {
499
- //SYNC
500
- //return early if this waitFor command has already run
501
363
  const [didRun, execIndex, result] = await WorkflowService.didRun('wait');
502
364
  if (didRun) {
503
365
  return result.data.data;
504
366
  }
505
- //package the interruption inputs
506
367
  const store = storage_1.asyncLocalStorage.getStore();
507
368
  const interruptionRegistry = store.get('interruptionRegistry');
508
369
  const workflowId = store.get('workflowId');
@@ -514,14 +375,11 @@ class WorkflowService {
514
375
  workflowDimension,
515
376
  };
516
377
  interruptionRegistry.push({
517
- code: enums_1.HMSH_CODE_DURABLE_WAIT,
378
+ code: enums_1.HMSH_CODE_MESHFLOW_WAIT,
518
379
  ...interruptionMessage,
519
380
  });
520
- //ASYNC
521
- //sleep to allow other interruptions to be packaged and registered
522
381
  await (0, utils_1.sleepImmediate)();
523
- // NOTE: If you are reading this in the stack trace, await `waitFor`
524
- throw new errors_1.DurableWaitForError(interruptionMessage);
382
+ throw new errors_1.MeshFlowWaitForError(interruptionMessage);
525
383
  }
526
384
  }
527
385
  exports.WorkflowService = WorkflowService;
@@ -1,12 +1,5 @@
1
1
  type DateInput = Date | string | number;
2
2
  declare class DateHandler {
3
- /**
4
- * It is so common in mapping operations to use a string (ISO) date as input. This helper
5
- * method allows for a more-concise mapping ruleset by avoiding date initialization boilerplate
6
- * code and instead handles the ISO, Milliseconds, and ECMAScript Date input types.
7
- * @param input
8
- * @returns
9
- */
10
3
  static getDateInstance(input: DateInput): Date;
11
4
  fromISOString(isoString: string): Date;
12
5
  now(): number;
@@ -3,13 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DateHandler = void 0;
4
4
  const utils_1 = require("../../../modules/utils");
5
5
  class DateHandler {
6
- /**
7
- * It is so common in mapping operations to use a string (ISO) date as input. This helper
8
- * method allows for a more-concise mapping ruleset by avoiding date initialization boilerplate
9
- * code and instead handles the ISO, Milliseconds, and ECMAScript Date input types.
10
- * @param input
11
- * @returns
12
- */
13
6
  static getDateInstance(input) {
14
7
  const ISO_REGEX = /^\d{4}-\d{2}-\d{2}(?:T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z)?$/;
15
8
  if (typeof input === 'string') {