@hotmeshio/hotmesh 0.0.55 → 0.0.57

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 (182) hide show
  1. package/README.md +1 -1
  2. package/build/modules/enums.js +1 -10
  3. package/build/modules/key.d.ts +0 -38
  4. package/build/modules/key.js +4 -46
  5. package/build/modules/utils.d.ts +0 -8
  6. package/build/modules/utils.js +0 -14
  7. package/build/package.json +11 -4
  8. package/build/services/activities/activity.d.ts +0 -28
  9. package/build/services/activities/activity.js +1 -46
  10. package/build/services/activities/await.js +0 -4
  11. package/build/services/activities/cycle.d.ts +0 -7
  12. package/build/services/activities/cycle.js +1 -16
  13. package/build/services/activities/hook.d.ts +0 -6
  14. package/build/services/activities/hook.js +2 -12
  15. package/build/services/activities/interrupt.js +0 -8
  16. package/build/services/activities/signal.d.ts +0 -6
  17. package/build/services/activities/signal.js +0 -15
  18. package/build/services/activities/trigger.d.ts +0 -4
  19. package/build/services/activities/trigger.js +1 -7
  20. package/build/services/activities/worker.js +0 -4
  21. package/build/services/collator/index.d.ts +0 -70
  22. package/build/services/collator/index.js +1 -91
  23. package/build/services/compiler/deployer.js +6 -38
  24. package/build/services/compiler/index.d.ts +0 -15
  25. package/build/services/compiler/index.js +0 -20
  26. package/build/services/compiler/validator.d.ts +0 -3
  27. package/build/services/compiler/validator.js +0 -25
  28. package/build/services/connector/clients/ioredis.d.ts +2 -2
  29. package/build/services/connector/clients/ioredis.js +0 -2
  30. package/build/services/connector/clients/redis.d.ts +4 -4
  31. package/build/services/connector/clients/redis.js +1 -3
  32. package/build/services/connector/index.d.ts +1 -1
  33. package/build/services/connector/index.js +0 -2
  34. package/build/services/durable/client.d.ts +1 -26
  35. package/build/services/durable/client.js +0 -56
  36. package/build/services/durable/exporter.d.ts +0 -22
  37. package/build/services/durable/exporter.js +1 -30
  38. package/build/services/durable/handle.d.ts +0 -36
  39. package/build/services/durable/handle.js +0 -46
  40. package/build/services/durable/index.d.ts +0 -4
  41. package/build/services/durable/index.js +0 -4
  42. package/build/services/durable/schemas/factory.d.ts +0 -29
  43. package/build/services/durable/schemas/factory.js +0 -29
  44. package/build/services/durable/search.d.ts +1 -36
  45. package/build/services/durable/search.js +56 -56
  46. package/build/services/durable/worker.js +2 -22
  47. package/build/services/durable/workflow.d.ts +0 -114
  48. package/build/services/durable/workflow.js +1 -141
  49. package/build/services/engine/index.d.ts +1 -6
  50. package/build/services/engine/index.js +1 -43
  51. package/build/services/exporter/index.d.ts +0 -27
  52. package/build/services/exporter/index.js +0 -33
  53. package/build/services/hotmesh/index.d.ts +2 -2
  54. package/build/services/hotmesh/index.js +1 -9
  55. package/build/services/logger/index.js +0 -2
  56. package/build/services/mapper/index.d.ts +0 -14
  57. package/build/services/mapper/index.js +0 -14
  58. package/build/services/pipe/functions/date.d.ts +0 -7
  59. package/build/services/pipe/functions/date.js +0 -7
  60. package/build/services/pipe/functions/math.js +0 -2
  61. package/build/services/pipe/index.d.ts +0 -15
  62. package/build/services/pipe/index.js +2 -23
  63. package/build/services/quorum/index.d.ts +0 -7
  64. package/build/services/quorum/index.js +0 -21
  65. package/build/services/reporter/index.d.ts +0 -5
  66. package/build/services/reporter/index.js +0 -9
  67. package/build/services/router/index.d.ts +0 -9
  68. package/build/services/router/index.js +2 -38
  69. package/build/services/serializer/index.js +7 -26
  70. package/build/services/store/cache.d.ts +0 -18
  71. package/build/services/store/cache.js +0 -18
  72. package/build/services/store/clients/ioredis.d.ts +1 -1
  73. package/build/services/store/clients/ioredis.js +0 -1
  74. package/build/services/store/clients/redis.d.ts +1 -1
  75. package/build/services/store/index.d.ts +0 -55
  76. package/build/services/store/index.js +5 -81
  77. package/build/services/stream/clients/ioredis.d.ts +1 -1
  78. package/build/services/stream/clients/ioredis.js +1 -4
  79. package/build/services/stream/clients/redis.d.ts +1 -1
  80. package/build/services/sub/clients/ioredis.d.ts +1 -1
  81. package/build/services/sub/clients/redis.d.ts +1 -1
  82. package/build/services/task/index.d.ts +0 -9
  83. package/build/services/task/index.js +0 -31
  84. package/build/services/telemetry/index.d.ts +0 -7
  85. package/build/services/telemetry/index.js +1 -13
  86. package/build/services/worker/index.d.ts +0 -4
  87. package/build/services/worker/index.js +2 -6
  88. package/build/types/activity.d.ts +0 -81
  89. package/build/types/durable.d.ts +26 -177
  90. package/build/types/exporter.d.ts +0 -13
  91. package/build/types/hotmesh.d.ts +4 -16
  92. package/build/types/hotmesh.js +0 -3
  93. package/build/types/index.d.ts +4 -6
  94. package/build/types/index.js +4 -3
  95. package/build/types/job.d.ts +1 -86
  96. package/build/types/pipe.d.ts +0 -65
  97. package/build/types/quorum.d.ts +15 -10
  98. package/build/types/redis.d.ts +225 -7
  99. package/build/types/redis.js +9 -0
  100. package/build/types/stream.d.ts +0 -58
  101. package/build/types/stream.js +0 -4
  102. package/package.json +11 -4
  103. package/types/durable.ts +131 -4
  104. package/types/hotmesh.ts +3 -6
  105. package/types/index.ts +23 -10
  106. package/types/job.ts +1 -1
  107. package/types/quorum.ts +22 -0
  108. package/types/redis.ts +267 -18
  109. package/build/types/ioredisclient.d.ts +0 -5
  110. package/build/types/ioredisclient.js +0 -5
  111. package/build/types/redisclient.d.ts +0 -26
  112. package/build/types/redisclient.js +0 -2
  113. package/modules/enums.ts +0 -62
  114. package/modules/errors.ts +0 -280
  115. package/modules/key.ts +0 -101
  116. package/modules/storage.ts +0 -3
  117. package/modules/utils.ts +0 -242
  118. package/services/activities/activity.ts +0 -589
  119. package/services/activities/await.ts +0 -113
  120. package/services/activities/cycle.ts +0 -115
  121. package/services/activities/hook.ts +0 -197
  122. package/services/activities/index.ts +0 -19
  123. package/services/activities/interrupt.ts +0 -172
  124. package/services/activities/signal.ts +0 -148
  125. package/services/activities/trigger.ts +0 -295
  126. package/services/activities/worker.ts +0 -107
  127. package/services/collator/README.md +0 -102
  128. package/services/collator/index.ts +0 -291
  129. package/services/compiler/deployer.ts +0 -504
  130. package/services/compiler/index.ts +0 -98
  131. package/services/compiler/validator.ts +0 -158
  132. package/services/connector/clients/ioredis.ts +0 -57
  133. package/services/connector/clients/redis.ts +0 -72
  134. package/services/connector/index.ts +0 -42
  135. package/services/durable/client.ts +0 -266
  136. package/services/durable/connection.ts +0 -10
  137. package/services/durable/exporter.ts +0 -232
  138. package/services/durable/handle.ts +0 -160
  139. package/services/durable/index.ts +0 -27
  140. package/services/durable/schemas/factory.ts +0 -2358
  141. package/services/durable/search.ts +0 -196
  142. package/services/durable/worker.ts +0 -401
  143. package/services/durable/workflow.ts +0 -557
  144. package/services/engine/index.ts +0 -761
  145. package/services/exporter/index.ts +0 -146
  146. package/services/hotmesh/index.ts +0 -237
  147. package/services/logger/index.ts +0 -79
  148. package/services/mapper/index.ts +0 -89
  149. package/services/pipe/functions/array.ts +0 -78
  150. package/services/pipe/functions/bitwise.ts +0 -27
  151. package/services/pipe/functions/conditional.ts +0 -35
  152. package/services/pipe/functions/date.ts +0 -220
  153. package/services/pipe/functions/index.ts +0 -27
  154. package/services/pipe/functions/json.ts +0 -11
  155. package/services/pipe/functions/logical.ts +0 -11
  156. package/services/pipe/functions/math.ts +0 -217
  157. package/services/pipe/functions/number.ts +0 -75
  158. package/services/pipe/functions/object.ts +0 -98
  159. package/services/pipe/functions/string.ts +0 -86
  160. package/services/pipe/functions/symbol.ts +0 -39
  161. package/services/pipe/functions/unary.ts +0 -19
  162. package/services/pipe/index.ts +0 -216
  163. package/services/quorum/index.ts +0 -319
  164. package/services/reporter/index.ts +0 -387
  165. package/services/router/index.ts +0 -426
  166. package/services/serializer/README.md +0 -10
  167. package/services/serializer/index.ts +0 -285
  168. package/services/store/cache.ts +0 -172
  169. package/services/store/clients/ioredis.ts +0 -145
  170. package/services/store/clients/redis.ts +0 -191
  171. package/services/store/index.ts +0 -1091
  172. package/services/stream/clients/ioredis.ts +0 -157
  173. package/services/stream/clients/redis.ts +0 -158
  174. package/services/stream/index.ts +0 -58
  175. package/services/sub/clients/ioredis.ts +0 -83
  176. package/services/sub/clients/redis.ts +0 -74
  177. package/services/sub/index.ts +0 -25
  178. package/services/task/index.ts +0 -250
  179. package/services/telemetry/index.ts +0 -273
  180. package/services/worker/index.ts +0 -248
  181. package/types/ioredisclient.ts +0 -10
  182. package/types/redisclient.ts +0 -30
@@ -61,7 +61,6 @@ class WorkerService {
61
61
  const baseTopic = `${config.taskQueue}-${workflowFunctionName}`;
62
62
  const activityTopic = `${baseTopic}-activity`;
63
63
  const workflowTopic = `${baseTopic}`;
64
- //initialize supporting workflows
65
64
  const worker = new WorkerService();
66
65
  worker.activityRunner = await worker.initActivityWorker(config, activityTopic);
67
66
  worker.workflowRunner = await worker.initWorkflowWorker(config, workflowTopic, workflowFunction);
@@ -104,11 +103,9 @@ class WorkerService {
104
103
  WorkerService.instances.set(activityTopic, hotMeshWorker);
105
104
  return hotMeshWorker;
106
105
  }
107
- //this is the linked worker function in the reentrant workflow test
108
106
  wrapActivityFunctions() {
109
107
  return async (data) => {
110
108
  try {
111
- //always run the activity function when instructed; return the response
112
109
  const activityInput = data.data;
113
110
  const activityName = activityInput.activityName;
114
111
  const activityFunction = WorkerService.activityRegistry[activityName];
@@ -124,8 +121,6 @@ class WorkerService {
124
121
  if (!(err instanceof errors_1.DurableTimeoutError) &&
125
122
  !(err instanceof errors_1.DurableMaxedError) &&
126
123
  !(err instanceof errors_1.DurableFatalError)) {
127
- //use code 599 as a proxy for all retryable errors
128
- // (basically anything not 596, 597, 598)
129
124
  return {
130
125
  status: stream_1.StreamStatus.SUCCESS,
131
126
  code: enums_1.HMSH_CODE_DURABLE_RETRYABLE,
@@ -140,8 +135,6 @@ class WorkerService {
140
135
  };
141
136
  }
142
137
  return {
143
- //always returrn success (the Durable module is just fine);
144
- // it's the user's function that has failed
145
138
  status: stream_1.StreamStatus.SUCCESS,
146
139
  code: err.code,
147
140
  stack: err.stack,
@@ -181,7 +174,6 @@ class WorkerService {
181
174
  const counter = { counter: 0 };
182
175
  const interruptionRegistry = [];
183
176
  try {
184
- //incoming data payload has arguments and workflowId
185
177
  const workflowInput = data.data;
186
178
  const context = new Map();
187
179
  context.set('canRetry', workflowInput.canRetry);
@@ -191,20 +183,14 @@ class WorkerService {
191
183
  context.set('raw', data);
192
184
  context.set('workflowId', workflowInput.workflowId);
193
185
  if (workflowInput.originJobId) {
194
- //if present there is an origin job to which this job is subordinated;
195
- // garbage collect (expire) this job when originJobId is expired
196
186
  context.set('originJobId', workflowInput.originJobId);
197
187
  }
198
188
  let replayQuery = '';
199
189
  if (workflowInput.workflowDimension) {
200
- //every hook function runs in an isolated dimension controlled
201
- //by the index assigned when the signal was received; even if the
202
- //hook function re-runs, its scope will always remain constant
203
190
  context.set('workflowDimension', workflowInput.workflowDimension);
204
191
  replayQuery = `-*${workflowInput.workflowDimension}-*`;
205
192
  }
206
193
  else {
207
- //last letter of words like 'hook', 'sleep', 'wait', 'signal', 'search', 'start', 'proxy', 'child', 'collator'
208
194
  replayQuery = '-*[ehklptydr]-*';
209
195
  }
210
196
  context.set('workflowTopic', workflowTopic);
@@ -214,7 +200,7 @@ class WorkerService {
214
200
  const store = this.workflowRunner.engine.store;
215
201
  const [cursor, replay] = await store.findJobFields(workflowInput.workflowId, replayQuery, 50000, 5000);
216
202
  context.set('replay', replay);
217
- context.set('cursor', cursor); // if != 0, more remain
203
+ context.set('cursor', cursor);
218
204
  const workflowResponse = await storage_1.asyncLocalStorage.run(context, async () => {
219
205
  return await workflowFunction.apply(this, workflowInput.arguments);
220
206
  });
@@ -227,7 +213,6 @@ class WorkerService {
227
213
  }
228
214
  catch (err) {
229
215
  if (err instanceof errors_1.DurableWaitForError || interruptionRegistry.length > 1) {
230
- //NOTE: this type is spawned when `Promise.all` is used OR if the interruption is a `waitFor`
231
216
  const workflowInput = data.data;
232
217
  const execIndex = counter.counter - interruptionRegistry.length + 1;
233
218
  const { workflowId, workflowTopic, workflowDimension, originJobId } = workflowInput;
@@ -250,7 +235,6 @@ class WorkerService {
250
235
  };
251
236
  }
252
237
  else if (err instanceof errors_1.DurableSleepError) {
253
- //return the sleep interruption
254
238
  return {
255
239
  status: stream_1.StreamStatus.SUCCESS,
256
240
  code: err.code,
@@ -265,7 +249,6 @@ class WorkerService {
265
249
  };
266
250
  }
267
251
  else if (err instanceof errors_1.DurableProxyError) {
268
- //return the proxyActivity interruption
269
252
  return {
270
253
  status: stream_1.StreamStatus.SUCCESS,
271
254
  code: err.code,
@@ -288,7 +271,6 @@ class WorkerService {
288
271
  };
289
272
  }
290
273
  else if (err instanceof errors_1.DurableChildError) {
291
- //return the child interruption
292
274
  const msg = {
293
275
  message: err.message,
294
276
  workflowId: err.workflowId,
@@ -315,8 +297,6 @@ class WorkerService {
315
297
  }
316
298
  };
317
299
  }
318
- // ALL other errors are actual fatal errors (598, 597, 596)
319
- // OR will be retried (599)
320
300
  return {
321
301
  status: stream_1.StreamStatus.SUCCESS,
322
302
  code: err.code || new errors_1.DurableRetryError(err.message).code,
@@ -341,7 +321,7 @@ class WorkerService {
341
321
  }
342
322
  }
343
323
  _a = WorkerService;
344
- WorkerService.activityRegistry = {}; //user's activities
324
+ WorkerService.activityRegistry = {};
345
325
  WorkerService.instances = new Map();
346
326
  WorkerService.getHotMesh = async (workflowTopic, config, options) => {
347
327
  if (WorkerService.instances.has(workflowTopic)) {
@@ -4,136 +4,22 @@ import { ActivityConfig, HookOptions, ProxyType, WorkflowContext, WorkflowOption
4
4
  import { JobInterruptOptions } from '../../types/job';
5
5
  import { DurableChildErrorType, DurableProxyErrorType } from '../../types/error';
6
6
  export declare class WorkflowService {
7
- /**
8
- * Returns the synchronous output from the activity (replay)
9
- * if available locally, revealing whether or not the activity already
10
- * ran during a prior execution cycle
11
- * @param {string} prefix - one of: proxy, child, start, wait etc
12
- * @returns
13
- */
14
7
  static didRun(prefix: string): Promise<[boolean, number, any]>;
15
- /**
16
- * Those methods that may only be called once must be protected by flagging
17
- * their execution with a unique key (the key is stored in the HASH alongside
18
- * process state and job state)
19
- * @private
20
- */
21
8
  static isSideEffectAllowed(hotMeshClient: HotMesh, prefix: string): Promise<boolean>;
22
- /**
23
- * Returns the current workflow context restored
24
- * from Redis
25
- */
26
9
  static getContext(): WorkflowContext;
27
- /**
28
- * Return a handle to the hotmesh client hosting the workflow execution
29
- * @returns {Promise<HotMesh>} - a hotmesh client
30
- */
31
10
  static getHotMesh(): Promise<HotMesh>;
32
- /**
33
- * Spawns a child workflow and awaits the return.
34
- * @template T - the result type
35
- * @param {WorkflowOptions} options - the workflow options
36
- * @returns {Promise<T>} - the result of the child workflow
37
- * @example
38
- * const result = await Durable.workflow.execChild<typeof resultType>({ ...options });
39
- */
40
11
  static execChild<T>(options: WorkflowOptions): Promise<T>;
41
- /**
42
- * constructs the payload necessary to spawn a child job
43
- * @private
44
- */
45
12
  static getChildInterruptPayload(context: WorkflowContext, options: WorkflowOptions, execIndex: number): DurableChildErrorType;
46
- /**
47
- * Spawns a child workflow and returns the child Job ID.
48
- * This method guarantees the spawned child has reserved the Job ID,
49
- * returning a 'DuplicateJobError' error if not. Otherwise,
50
- * this is a fire-and-forget method.
51
- *
52
- * @param {WorkflowOptions} options - the workflow options
53
- * @returns {Promise<string>} - the childJobId
54
- * @example
55
- * const childJobId = await Durable.workflow.startChild({ ...options });
56
- */
57
13
  static startChild(options: WorkflowOptions): Promise<string>;
58
- /**
59
- * Wraps activities in a proxy that durably runs/re-runs them to completion.
60
- * TODO: verify that activities do not collide if named same on same server but bound to different workflows
61
- *
62
- * @param {ActivityConfig} options - the activity configuration
63
- * that will be used to wrap the activities.
64
- * @returns {ProxyType<ACT>} - a proxy object with the same keys as the
65
- * activities object, but with the values replaced by a wrapped function
66
- *
67
- * @example
68
- * // import the activities
69
- * import * as activities from './activities';
70
- * const proxy = WorkflowService.proxyActivities<typeof activities>({ activities });
71
- *
72
- * //or destructure the proxy object, as the function names are the keys
73
- * const { activity1, activity2 } = WorkflowService.proxyActivities<typeof activities>({ activities });
74
- */
75
14
  static proxyActivities<ACT>(options?: ActivityConfig): ProxyType<ACT>;
76
15
  static wrapActivity<T>(activityName: string, options?: ActivityConfig): T;
77
- /**
78
- * constructs the payload necessary to spawn a proxyActivity job
79
- * @private
80
- */
81
16
  static getProxyInterruptPayload(context: WorkflowContext, activityName: string, execIndex: number, args: any[], options?: ActivityConfig): DurableProxyErrorType;
82
- /**
83
- * Returns a search session for use when reading/writing to the workflow HASH.
84
- * The search session provides access to methods like `get`, `mget`, `set`, `del`, and `incr`.
85
- * @returns {Promise<Search>} - a search session
86
- */
87
17
  static search(): Promise<Search>;
88
- /**
89
- * Returns a random number between 0 and 1. This number is deterministic
90
- * and will never vary for a given seed. This is useful for randomizing
91
- * pathways in a workflow that can be safely replayed.
92
- * @returns {number} - a random number between 0 and 1
93
- */
94
18
  static random(): number;
95
- /**
96
- * Sends signal data into any other paused thread (which is currently
97
- * awaiting the signal)
98
- * @param {string} signalId - the signal id
99
- * @param {Record<any, any>} data - the signal data
100
- * @returns {Promise<string>} - the stream id
101
- */
102
19
  static signal(signalId: string, data: Record<any, any>): Promise<string>;
103
- /**
104
- * Spawns a hook from either the main thread or a hook thread with
105
- * the provided options; worflowId/TaskQueue/Name are optional and will
106
- * default to the current workflowId/WorkflowTopic if not provided
107
- * @param {HookOptions} options - the hook options
108
- */
109
20
  static hook(options: HookOptions): Promise<string>;
110
- /**
111
- * Executes a function once and caches the result. If the function is called
112
- * again, the cached result is returned. This is useful for wrapping
113
- * expensive activity calls that should only be run once, but which might
114
- * not require the cost and safety provided by proxyActivities.
115
- * @template T - the result type
116
- */
117
21
  static once<T>(fn: (...args: any[]) => Promise<T>, ...args: any[]): Promise<T>;
118
- /**
119
- * Interrupts a running job
120
- */
121
22
  static interrupt(jobId: string, options?: JobInterruptOptions): Promise<string | void>;
122
- /**
123
- * Sleeps the workflow for a duration. As the function is reentrant,
124
- * upon reentry, the function will traverse prior execution paths up
125
- * until the sleep command and then resume execution thereafter.
126
- * @param {string} duration - See the `ms` package for syntax examples: '1 minute', '2 hours', '3 days'
127
- * @returns {Promise<number>} - resolved duration in seconds
128
- */
129
23
  static sleepFor(duration: string): Promise<number>;
130
- /**
131
- * Pauses the workflow until `signalId` is received.
132
- * @template T - the result type
133
- * @param {string} signalId - a unique, shareable guid (e.g, 'abc123')
134
- * @returns {Promise<T>}
135
- * @example
136
- * const result = await Durable.workflow.waitFor<typeof resultType>('abc123');
137
- */
138
24
  static waitFor<T>(signalId: string): Promise<T>;
139
25
  }
@@ -15,13 +15,6 @@ const serializer_1 = require("../serializer");
15
15
  const stream_1 = require("../../types/stream");
16
16
  const enums_1 = require("../../modules/enums");
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
- */
25
18
  static async didRun(prefix) {
26
19
  const { COUNTER, replay, workflowDimension, } = WorkflowService.getContext();
27
20
  const execIndex = COUNTER.counter = COUNTER.counter + 1;
@@ -32,12 +25,6 @@ class WorkflowService {
32
25
  }
33
26
  return [false, execIndex, null];
34
27
  }
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
28
  static async isSideEffectAllowed(hotMeshClient, prefix) {
42
29
  const store = storage_1.asyncLocalStorage.getStore();
43
30
  const workflowId = store.get('workflowId');
@@ -57,10 +44,6 @@ class WorkflowService {
57
44
  const guidValue = Number(await hotMeshClient.engine.store.exec('HINCRBYFLOAT', workflowGuid, sessionId, '1'));
58
45
  return guidValue === 1;
59
46
  }
60
- /**
61
- * Returns the current workflow context restored
62
- * from Redis
63
- */
64
47
  static getContext() {
65
48
  const store = storage_1.asyncLocalStorage.getStore();
66
49
  const workflowId = store.get('workflowId');
@@ -93,27 +76,13 @@ class WorkflowService {
93
76
  workflowSpan,
94
77
  };
95
78
  }
96
- /**
97
- * Return a handle to the hotmesh client hosting the workflow execution
98
- * @returns {Promise<HotMesh>} - a hotmesh client
99
- */
100
79
  static async getHotMesh() {
101
80
  const store = storage_1.asyncLocalStorage.getStore();
102
81
  const workflowTopic = store.get('workflowTopic');
103
82
  const namespace = store.get('namespace');
104
83
  return await worker_1.WorkerService.getHotMesh(workflowTopic, { namespace });
105
84
  }
106
- /**
107
- * Spawns a child workflow and awaits the return.
108
- * @template T - the result type
109
- * @param {WorkflowOptions} options - the workflow options
110
- * @returns {Promise<T>} - the result of the child workflow
111
- * @example
112
- * const result = await Durable.workflow.execChild<typeof resultType>({ ...options });
113
- */
114
85
  static async execChild(options) {
115
- //SYNC
116
- //check if the activity already ran (check $error/done)
117
86
  const isStartChild = options.await === false;
118
87
  const prefix = isStartChild ? 'start' : 'child';
119
88
  const [didRun, execIndex, result] = await WorkflowService.didRun(prefix);
@@ -122,7 +91,6 @@ class WorkflowService {
122
91
  if (didRun) {
123
92
  if (result?.$error && (!result.$error.is_stream_error || (result.$error.is_stream_error && !canRetry))) {
124
93
  if (options?.config?.throwOnError !== false) {
125
- //rethrow remote execution error (simulates local failure)
126
94
  const code = result.$error.code;
127
95
  const message = result.$error.message;
128
96
  const stack = result.$error.stack;
@@ -146,20 +114,13 @@ class WorkflowService {
146
114
  }
147
115
  }
148
116
  const interruptionMessage = WorkflowService.getChildInterruptPayload(context, options, execIndex);
149
- //push the packaged inputs to the registry
150
117
  interruptionRegistry.push({
151
118
  code: enums_1.HMSH_CODE_DURABLE_CHILD,
152
119
  ...interruptionMessage,
153
120
  });
154
- //ASYNC
155
- //sleep (allow others to be packaged / registered) and throw the error
156
121
  await (0, utils_1.sleepFor)(0);
157
122
  throw new errors_1.DurableChildError(interruptionMessage);
158
123
  }
159
- /**
160
- * constructs the payload necessary to spawn a child job
161
- * @private
162
- */
163
124
  static getChildInterruptPayload(context, options, execIndex) {
164
125
  const { workflowId, originJobId, workflowDimension } = context;
165
126
  let childJobId;
@@ -190,37 +151,9 @@ class WorkflowService {
190
151
  workflowTopic,
191
152
  };
192
153
  }
193
- /**
194
- * Spawns a child workflow and returns the child Job ID.
195
- * This method guarantees the spawned child has reserved the Job ID,
196
- * returning a 'DuplicateJobError' error if not. Otherwise,
197
- * this is a fire-and-forget method.
198
- *
199
- * @param {WorkflowOptions} options - the workflow options
200
- * @returns {Promise<string>} - the childJobId
201
- * @example
202
- * const childJobId = await Durable.workflow.startChild({ ...options });
203
- */
204
154
  static async startChild(options) {
205
155
  return WorkflowService.execChild({ ...options, await: false });
206
156
  }
207
- /**
208
- * Wraps activities in a proxy that durably runs/re-runs them to completion.
209
- * TODO: verify that activities do not collide if named same on same server but bound to different workflows
210
- *
211
- * @param {ActivityConfig} options - the activity configuration
212
- * that will be used to wrap the activities.
213
- * @returns {ProxyType<ACT>} - a proxy object with the same keys as the
214
- * activities object, but with the values replaced by a wrapped function
215
- *
216
- * @example
217
- * // import the activities
218
- * import * as activities from './activities';
219
- * const proxy = WorkflowService.proxyActivities<typeof activities>({ activities });
220
- *
221
- * //or destructure the proxy object, as the function names are the keys
222
- * const { activity1, activity2 } = WorkflowService.proxyActivities<typeof activities>({ activities });
223
- */
224
157
  static proxyActivities(options) {
225
158
  if (options.activities) {
226
159
  worker_1.WorkerService.registerActivities(options.activities);
@@ -237,13 +170,10 @@ class WorkflowService {
237
170
  }
238
171
  static wrapActivity(activityName, options) {
239
172
  return async function () {
240
- //SYNC
241
- //check if the activity already ran
242
173
  const [didRun, execIndex, result] = await WorkflowService.didRun('proxy');
243
174
  if (didRun) {
244
175
  if (result?.$error) {
245
176
  if (options?.retryPolicy?.throwOnError !== false) {
246
- //rethrow remote execution error (simulates throw)
247
177
  const code = result.$error.code;
248
178
  const message = result.$error.message;
249
179
  const stack = result.$error.stack;
@@ -261,25 +191,17 @@ class WorkflowService {
261
191
  }
262
192
  return result.data;
263
193
  }
264
- //package the interruption inputs
265
194
  const context = WorkflowService.getContext();
266
195
  const { interruptionRegistry } = context;
267
196
  const interruptionMessage = WorkflowService.getProxyInterruptPayload(context, activityName, execIndex, Array.from(arguments), options);
268
- //push the packaged inputs to the registry
269
197
  interruptionRegistry.push({
270
198
  code: enums_1.HMSH_CODE_DURABLE_PROXY,
271
199
  ...interruptionMessage,
272
200
  });
273
- //ASYNC
274
- //sleep (allow others to be packaged / registered) and throw the error
275
201
  await (0, utils_1.sleepFor)(0);
276
202
  throw new errors_1.DurableProxyError(interruptionMessage);
277
203
  };
278
204
  }
279
- /**
280
- * constructs the payload necessary to spawn a proxyActivity job
281
- * @private
282
- */
283
205
  static getProxyInterruptPayload(context, activityName, execIndex, args, options) {
284
206
  const { workflowDimension, workflowId, originJobId, workflowTopic } = context;
285
207
  const activityTopic = `${workflowTopic}-activity`;
@@ -302,11 +224,6 @@ class WorkflowService {
302
224
  maximumInterval: maximumInterval ?? undefined,
303
225
  };
304
226
  }
305
- /**
306
- * Returns a search session for use when reading/writing to the workflow HASH.
307
- * The search session provides access to methods like `get`, `mget`, `set`, `del`, and `incr`.
308
- * @returns {Promise<Search>} - a search session
309
- */
310
227
  static async search() {
311
228
  const store = storage_1.asyncLocalStorage.getStore();
312
229
  const workflowId = store.get('workflowId');
@@ -316,29 +233,15 @@ class WorkflowService {
316
233
  const COUNTER = store.get('counter');
317
234
  const execIndex = COUNTER.counter = COUNTER.counter + 1;
318
235
  const hotMeshClient = await worker_1.WorkerService.getHotMesh(workflowTopic, { namespace });
319
- //this ID is used as a item key with a hash (dash prefix ensures no collision)
320
236
  const searchSessionId = `-search${workflowDimension}-${execIndex}`;
321
237
  return new search_1.Search(workflowId, hotMeshClient, searchSessionId);
322
238
  }
323
- /**
324
- * Returns a random number between 0 and 1. This number is deterministic
325
- * and will never vary for a given seed. This is useful for randomizing
326
- * pathways in a workflow that can be safely replayed.
327
- * @returns {number} - a random number between 0 and 1
328
- */
329
239
  static random() {
330
240
  const store = storage_1.asyncLocalStorage.getStore();
331
241
  const COUNTER = store.get('counter');
332
242
  const seed = COUNTER.counter = COUNTER.counter + 1;
333
243
  return (0, utils_1.deterministicRandom)(seed);
334
244
  }
335
- /**
336
- * Sends signal data into any other paused thread (which is currently
337
- * awaiting the signal)
338
- * @param {string} signalId - the signal id
339
- * @param {Record<any, any>} data - the signal data
340
- * @returns {Promise<string>} - the stream id
341
- */
342
245
  static async signal(signalId, data) {
343
246
  const store = storage_1.asyncLocalStorage.getStore();
344
247
  const workflowTopic = store.get('workflowTopic');
@@ -348,12 +251,6 @@ class WorkflowService {
348
251
  return await hotMeshClient.hook(`${namespace}.wfs.signal`, { id: signalId, data });
349
252
  }
350
253
  }
351
- /**
352
- * Spawns a hook from either the main thread or a hook thread with
353
- * the provided options; worflowId/TaskQueue/Name are optional and will
354
- * default to the current workflowId/WorkflowTopic if not provided
355
- * @param {HookOptions} options - the hook options
356
- */
357
254
  static async hook(options) {
358
255
  const { workflowId, namespace, workflowTopic, } = WorkflowService.getContext();
359
256
  const hotMeshClient = await worker_1.WorkerService.getHotMesh(workflowTopic, { namespace });
@@ -375,13 +272,6 @@ class WorkflowService {
375
272
  return await hotMeshClient.hook(`${namespace}.flow.signal`, payload, stream_1.StreamStatus.PENDING, 202);
376
273
  }
377
274
  }
378
- /**
379
- * Executes a function once and caches the result. If the function is called
380
- * again, the cached result is returned. This is useful for wrapping
381
- * expensive activity calls that should only be run once, but which might
382
- * not require the cost and safety provided by proxyActivities.
383
- * @template T - the result type
384
- */
385
275
  static async once(fn, ...args) {
386
276
  const { COUNTER, namespace, workflowId, workflowTopic, workflowDimension, replay, } = WorkflowService.getContext();
387
277
  const execIndex = COUNTER.counter = COUNTER.counter + 1;
@@ -406,9 +296,6 @@ class WorkflowService {
406
296
  await hotMeshClient.engine.store.exec('HSET', workflowGuid, sessionId, serializer_1.SerializerService.toString(payload));
407
297
  return response;
408
298
  }
409
- /**
410
- * Interrupts a running job
411
- */
412
299
  static async interrupt(jobId, options = {}) {
413
300
  const { workflowTopic, namespace } = WorkflowService.getContext();
414
301
  const hotMeshClient = await worker_1.WorkerService.getHotMesh(workflowTopic, { namespace });
@@ -416,21 +303,11 @@ class WorkflowService {
416
303
  return await hotMeshClient.interrupt(`${hotMeshClient.appId}.execute`, jobId, options);
417
304
  }
418
305
  }
419
- /**
420
- * Sleeps the workflow for a duration. As the function is reentrant,
421
- * upon reentry, the function will traverse prior execution paths up
422
- * until the sleep command and then resume execution thereafter.
423
- * @param {string} duration - See the `ms` package for syntax examples: '1 minute', '2 hours', '3 days'
424
- * @returns {Promise<number>} - resolved duration in seconds
425
- */
426
306
  static async sleepFor(duration) {
427
- //SYNC
428
- //return early if this sleep command has already run
429
307
  const [didRun, execIndex, result] = await WorkflowService.didRun('sleep');
430
308
  if (didRun) {
431
- return result.duration; //in seconds
309
+ return result.duration;
432
310
  }
433
- //package the interruption inputs
434
311
  const store = storage_1.asyncLocalStorage.getStore();
435
312
  const interruptionRegistry = store.get('interruptionRegistry');
436
313
  const workflowId = store.get('workflowId');
@@ -445,28 +322,14 @@ class WorkflowService {
445
322
  code: enums_1.HMSH_CODE_DURABLE_SLEEP,
446
323
  ...interruptionMessage,
447
324
  });
448
- //ASYNC
449
- //sleep to allow other interruptions to be packaged and registered
450
325
  await (0, utils_1.sleepFor)(0);
451
- // NOTE: If you are reading this in the stack trace, await `sleepFor`
452
326
  throw new errors_1.DurableSleepError(interruptionMessage);
453
327
  }
454
- /**
455
- * Pauses the workflow until `signalId` is received.
456
- * @template T - the result type
457
- * @param {string} signalId - a unique, shareable guid (e.g, 'abc123')
458
- * @returns {Promise<T>}
459
- * @example
460
- * const result = await Durable.workflow.waitFor<typeof resultType>('abc123');
461
- */
462
328
  static async waitFor(signalId) {
463
- //SYNC
464
- //return early if this waitFor command has already run
465
329
  const [didRun, execIndex, result] = await WorkflowService.didRun('wait');
466
330
  if (didRun) {
467
331
  return result.data.data;
468
332
  }
469
- //package the interruption inputs
470
333
  const store = storage_1.asyncLocalStorage.getStore();
471
334
  const interruptionRegistry = store.get('interruptionRegistry');
472
335
  const workflowId = store.get('workflowId');
@@ -481,10 +344,7 @@ class WorkflowService {
481
344
  code: enums_1.HMSH_CODE_DURABLE_WAIT,
482
345
  ...interruptionMessage,
483
346
  });
484
- //ASYNC
485
- //sleep to allow other interruptions to be packaged and registered
486
347
  await (0, utils_1.sleepFor)(0);
487
- // NOTE: If you are reading this in the stack trace, await `waitFor`
488
348
  throw new errors_1.DurableWaitForError(interruptionMessage);
489
349
  }
490
350
  }
@@ -15,6 +15,7 @@ import { TaskService } from '../task';
15
15
  import { AppVID } from '../../types/app';
16
16
  import { ActivityType } from '../../types/activity';
17
17
  import { CacheMode } from '../../types/cache';
18
+ import { JobExport } from '../../types/exporter';
18
19
  import { JobState, JobData, JobMetadata, JobOutput, JobStatus, JobInterruptOptions, JobCompletionOptions, ExtensionType } from '../../types/job';
19
20
  import { HotMeshApps, HotMeshConfig, HotMeshManifest, HotMeshSettings } from '../../types/hotmesh';
20
21
  import { JobMessageCallback } from '../../types/quorum';
@@ -23,7 +24,6 @@ import { StringAnyType, StringStringType } from '../../types/serializer';
23
24
  import { GetStatsOptions, IdsResponse, JobStatsInput, StatsResponse } from '../../types/stats';
24
25
  import { StreamCode, StreamData, StreamDataResponse, StreamError, StreamStatus } from '../../types/stream';
25
26
  import { WorkListTaskType } from '../../types/task';
26
- import { JobExport } from '../../types/exporter';
27
27
  declare class EngineService {
28
28
  namespace: string;
29
29
  apps: HotMeshApps | null;
@@ -86,11 +86,6 @@ declare class EngineService {
86
86
  delistJobCallback(jobId: string): void;
87
87
  hasOneTimeSubscription(context: JobState): boolean;
88
88
  runJobCompletionTasks(context: JobState, options?: JobCompletionOptions): Promise<string | void>;
89
- /**
90
- * Job hash expiration is typically reliant on the metadata field
91
- * if the activity concludes normally. However, if the job is `interrupted`,
92
- * it will be expired immediately.
93
- */
94
89
  resolveExpires(context: JobState, options: JobCompletionOptions): number;
95
90
  export(jobId: string): Promise<JobExport>;
96
91
  getRaw(jobId: string): Promise<StringStringType>;