@hotmeshio/hotmesh 0.0.51 → 0.0.53

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 (126) hide show
  1. package/README.md +13 -9
  2. package/build/index.d.ts +1 -2
  3. package/build/index.js +1 -3
  4. package/build/modules/enums.d.ts +8 -3
  5. package/build/modules/enums.js +16 -8
  6. package/build/modules/errors.d.ts +98 -18
  7. package/build/modules/errors.js +90 -33
  8. package/build/package.json +7 -2
  9. package/build/services/activities/activity.d.ts +8 -0
  10. package/build/services/activities/activity.js +65 -16
  11. package/build/services/activities/await.js +6 -6
  12. package/build/services/activities/cycle.d.ts +2 -2
  13. package/build/services/activities/cycle.js +5 -5
  14. package/build/services/activities/hook.js +4 -4
  15. package/build/services/activities/interrupt.d.ts +3 -3
  16. package/build/services/activities/interrupt.js +15 -6
  17. package/build/services/activities/signal.d.ts +2 -2
  18. package/build/services/activities/signal.js +4 -4
  19. package/build/services/activities/trigger.js +12 -3
  20. package/build/services/activities/worker.js +6 -6
  21. package/build/services/compiler/deployer.js +33 -5
  22. package/build/services/compiler/validator.d.ts +2 -0
  23. package/build/services/compiler/validator.js +5 -1
  24. package/build/services/durable/client.d.ts +7 -1
  25. package/build/services/durable/client.js +56 -30
  26. package/build/services/durable/exporter.d.ts +7 -72
  27. package/build/services/durable/exporter.js +105 -295
  28. package/build/services/durable/handle.d.ts +11 -6
  29. package/build/services/durable/handle.js +59 -46
  30. package/build/services/durable/index.d.ts +0 -2
  31. package/build/services/durable/index.js +0 -2
  32. package/build/services/durable/schemas/factory.d.ts +33 -0
  33. package/build/services/durable/schemas/factory.js +2356 -0
  34. package/build/services/durable/search.js +8 -8
  35. package/build/services/durable/worker.js +117 -25
  36. package/build/services/durable/workflow.d.ts +46 -43
  37. package/build/services/durable/workflow.js +273 -277
  38. package/build/services/engine/index.js +3 -0
  39. package/build/services/exporter/index.d.ts +2 -4
  40. package/build/services/exporter/index.js +4 -5
  41. package/build/services/mapper/index.d.ts +6 -2
  42. package/build/services/mapper/index.js +6 -2
  43. package/build/services/pipe/functions/array.d.ts +2 -10
  44. package/build/services/pipe/functions/array.js +30 -28
  45. package/build/services/pipe/functions/conditional.d.ts +1 -0
  46. package/build/services/pipe/functions/conditional.js +3 -0
  47. package/build/services/pipe/functions/date.d.ts +1 -0
  48. package/build/services/pipe/functions/date.js +4 -0
  49. package/build/services/pipe/functions/index.d.ts +2 -0
  50. package/build/services/pipe/functions/index.js +2 -0
  51. package/build/services/pipe/functions/logical.d.ts +5 -0
  52. package/build/services/pipe/functions/logical.js +12 -0
  53. package/build/services/pipe/functions/object.d.ts +3 -0
  54. package/build/services/pipe/functions/object.js +25 -7
  55. package/build/services/pipe/index.d.ts +20 -3
  56. package/build/services/pipe/index.js +82 -16
  57. package/build/services/router/index.js +14 -3
  58. package/build/services/serializer/index.d.ts +3 -2
  59. package/build/services/serializer/index.js +11 -4
  60. package/build/services/store/clients/ioredis.js +6 -6
  61. package/build/services/store/clients/redis.js +7 -7
  62. package/build/services/store/index.d.ts +2 -0
  63. package/build/services/store/index.js +4 -1
  64. package/build/services/stream/clients/ioredis.js +8 -8
  65. package/build/services/stream/clients/redis.js +1 -1
  66. package/build/types/activity.d.ts +60 -5
  67. package/build/types/durable.d.ts +168 -33
  68. package/build/types/exporter.d.ts +26 -4
  69. package/build/types/index.d.ts +2 -2
  70. package/build/types/job.d.ts +69 -5
  71. package/build/types/pipe.d.ts +81 -3
  72. package/build/types/stream.d.ts +61 -1
  73. package/build/types/stream.js +4 -0
  74. package/index.ts +1 -2
  75. package/modules/enums.ts +16 -8
  76. package/modules/errors.ts +174 -32
  77. package/package.json +7 -2
  78. package/services/activities/activity.ts +67 -18
  79. package/services/activities/await.ts +6 -6
  80. package/services/activities/cycle.ts +7 -6
  81. package/services/activities/hook.ts +4 -4
  82. package/services/activities/interrupt.ts +19 -9
  83. package/services/activities/signal.ts +6 -5
  84. package/services/activities/trigger.ts +16 -4
  85. package/services/activities/worker.ts +7 -7
  86. package/services/compiler/deployer.ts +33 -6
  87. package/services/compiler/validator.ts +7 -3
  88. package/services/durable/client.ts +47 -14
  89. package/services/durable/exporter.ts +110 -318
  90. package/services/durable/handle.ts +63 -50
  91. package/services/durable/index.ts +0 -2
  92. package/services/durable/schemas/factory.ts +2358 -0
  93. package/services/durable/search.ts +8 -8
  94. package/services/durable/worker.ts +128 -29
  95. package/services/durable/workflow.ts +304 -288
  96. package/services/engine/index.ts +4 -0
  97. package/services/exporter/index.ts +10 -12
  98. package/services/mapper/index.ts +6 -2
  99. package/services/pipe/functions/array.ts +24 -37
  100. package/services/pipe/functions/conditional.ts +4 -0
  101. package/services/pipe/functions/date.ts +6 -0
  102. package/services/pipe/functions/index.ts +7 -5
  103. package/services/pipe/functions/logical.ts +11 -0
  104. package/services/pipe/functions/object.ts +26 -7
  105. package/services/pipe/index.ts +99 -21
  106. package/services/quorum/index.ts +1 -3
  107. package/services/router/index.ts +14 -3
  108. package/services/serializer/index.ts +12 -5
  109. package/services/store/clients/ioredis.ts +6 -6
  110. package/services/store/clients/redis.ts +7 -7
  111. package/services/store/index.ts +4 -1
  112. package/services/stream/clients/ioredis.ts +8 -8
  113. package/services/stream/clients/redis.ts +1 -1
  114. package/types/activity.ts +87 -15
  115. package/types/durable.ts +246 -73
  116. package/types/exporter.ts +31 -5
  117. package/types/index.ts +6 -7
  118. package/types/job.ts +130 -36
  119. package/types/pipe.ts +84 -3
  120. package/types/stream.ts +82 -23
  121. package/build/services/durable/factory.d.ts +0 -17
  122. package/build/services/durable/factory.js +0 -817
  123. package/build/services/durable/meshos.d.ts +0 -127
  124. package/build/services/durable/meshos.js +0 -380
  125. package/services/durable/factory.ts +0 -818
  126. package/services/durable/meshos.ts +0 -441
@@ -46,8 +46,8 @@ class Search {
46
46
  const prefixes = search.prefix.map((prefix) => `${hotMeshPrefix}${prefix}`);
47
47
  await store.exec('FT.CREATE', `${search.index}`, 'ON', 'HASH', 'PREFIX', prefixes.length.toString(), ...prefixes, 'SCHEMA', ...schema);
48
48
  }
49
- catch (err) {
50
- hotMeshClient.engine.logger.info('durable-client-search-err', { err });
49
+ catch (error) {
50
+ hotMeshClient.engine.logger.info('durable-client-search-err', { ...error });
51
51
  }
52
52
  }
53
53
  }
@@ -63,8 +63,8 @@ class Search {
63
63
  const searchIndexes = await store.exec('FT._LIST');
64
64
  return searchIndexes;
65
65
  }
66
- catch (err) {
67
- hotMeshClient.engine.logger.info('durable-client-search-list-err', { err });
66
+ catch (error) {
67
+ hotMeshClient.engine.logger.info('durable-client-search-list-err', { ...error });
68
68
  return [];
69
69
  }
70
70
  }
@@ -103,8 +103,8 @@ class Search {
103
103
  try {
104
104
  return await this.store.exec('HGET', this.jobId, this.safeKey(key));
105
105
  }
106
- catch (err) {
107
- this.hotMeshClient.logger.error('durable-search-get-error', { err });
106
+ catch (error) {
107
+ this.hotMeshClient.logger.error('durable-search-get-error', { ...error });
108
108
  return '';
109
109
  }
110
110
  }
@@ -116,8 +116,8 @@ class Search {
116
116
  try {
117
117
  return await this.store.exec('HMGET', this.jobId, ...safeArgs);
118
118
  }
119
- catch (err) {
120
- this.hotMeshClient.logger.error('durable-search-mget-error', { err });
119
+ catch (error) {
120
+ this.hotMeshClient.logger.error('durable-search-mget-error', { ...error });
121
121
  return [];
122
122
  }
123
123
  }
@@ -1,14 +1,19 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  var _a;
3
6
  Object.defineProperty(exports, "__esModule", { value: true });
4
7
  exports.WorkerService = void 0;
8
+ const ms_1 = __importDefault(require("ms"));
9
+ const enums_1 = require("../../modules/enums");
5
10
  const errors_1 = require("../../modules/errors");
6
11
  const storage_1 = require("../../modules/storage");
7
- const factory_1 = require("./factory");
12
+ const factory_1 = require("./schemas/factory");
8
13
  const hotmesh_1 = require("../hotmesh");
9
14
  const search_1 = require("./search");
10
15
  const stream_1 = require("../../types/stream");
11
- const enums_1 = require("../../modules/enums");
16
+ const utils_1 = require("../../modules/utils");
12
17
  class WorkerService {
13
18
  static async activateWorkflow(hotMesh) {
14
19
  const app = await hotMesh.engine.store.getApp(hotMesh.engine.appId);
@@ -99,6 +104,7 @@ class WorkerService {
99
104
  WorkerService.instances.set(activityTopic, hotMeshWorker);
100
105
  return hotMeshWorker;
101
106
  }
107
+ //this is the linked worker function in the reentrant workflow test
102
108
  wrapActivityFunctions() {
103
109
  return async (data) => {
104
110
  try {
@@ -114,17 +120,40 @@ class WorkerService {
114
120
  };
115
121
  }
116
122
  catch (err) {
117
- this.activityRunner.engine.logger.error('durable-worker-activity-err', err);
123
+ this.activityRunner.engine.logger.error('durable-worker-activity-err', { name: err.name, message: err.message, stack: err.stack });
118
124
  if (!(err instanceof errors_1.DurableTimeoutError) &&
119
125
  !(err instanceof errors_1.DurableMaxedError) &&
120
126
  !(err instanceof errors_1.DurableFatalError)) {
121
- err = new errors_1.DurableRetryError(err.message);
127
+ //use code 599 as a proxy for all retryable errors
128
+ // (basically anything not 596, 597, 598)
129
+ return {
130
+ status: stream_1.StreamStatus.SUCCESS,
131
+ code: enums_1.HMSH_CODE_DURABLE_RETRYABLE,
132
+ metadata: { ...data.metadata },
133
+ data: {
134
+ $error: {
135
+ message: err.message,
136
+ stack: err.stack,
137
+ timestamp: (0, utils_1.formatISODate)(new Date()),
138
+ }
139
+ },
140
+ };
122
141
  }
123
142
  return {
124
- status: stream_1.StreamStatus.ERROR,
143
+ //always returrn success (the Durable module is just fine);
144
+ // it's the user's function that has failed
145
+ status: stream_1.StreamStatus.SUCCESS,
125
146
  code: err.code,
147
+ stack: err.stack,
126
148
  metadata: { ...data.metadata },
127
- data: { message: err.message }
149
+ data: {
150
+ $error: {
151
+ message: err.message,
152
+ stack: err.stack,
153
+ timestamp: (0, utils_1.formatISODate)(new Date()),
154
+ code: err.code,
155
+ }
156
+ },
128
157
  };
129
158
  }
130
159
  };
@@ -150,14 +179,16 @@ class WorkerService {
150
179
  wrapWorkflowFunction(workflowFunction, workflowTopic, config) {
151
180
  return async (data) => {
152
181
  const counter = { counter: 0 };
182
+ const interruptionRegistry = [];
153
183
  try {
154
184
  //incoming data payload has arguments and workflowId
155
185
  const workflowInput = data.data;
156
186
  const context = new Map();
157
- context.set('raw', data);
158
- context.set('namespace', config.namespace ?? factory_1.APP_ID);
187
+ context.set('canRetry', workflowInput.canRetry);
159
188
  context.set('counter', counter);
160
- context.set('workflowId', workflowInput.workflowId);
189
+ context.set('interruptionRegistry', interruptionRegistry);
190
+ context.set('namespace', config.namespace ?? factory_1.APP_ID);
191
+ context.set('raw', data);
161
192
  context.set('workflowId', workflowInput.workflowId);
162
193
  if (workflowInput.originJobId) {
163
194
  //if present there is an origin job to which this job is subordinated;
@@ -173,8 +204,8 @@ class WorkerService {
173
204
  replayQuery = `-*${workflowInput.workflowDimension}-*`;
174
205
  }
175
206
  else {
176
- //last letter of words like 'hook', 'sleep', 'wait', 'signal', 'search', 'start'
177
- replayQuery = '-*[ehklpt]-*';
207
+ //last letter of words like 'hook', 'sleep', 'wait', 'signal', 'search', 'start', 'proxy', 'child', 'collator'
208
+ replayQuery = '-*[ehklptydr]-*';
178
209
  }
179
210
  context.set('workflowTopic', workflowTopic);
180
211
  context.set('workflowName', workflowTopic.split('-').pop());
@@ -195,49 +226,110 @@ class WorkerService {
195
226
  };
196
227
  }
197
228
  catch (err) {
198
- //not an error...just a trigger to sleep
199
- if (err instanceof errors_1.DurableSleepForError) {
229
+ 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
+ const workflowInput = data.data;
232
+ const execIndex = counter.counter - interruptionRegistry.length + 1;
233
+ const { workflowId, workflowTopic, workflowDimension, originJobId } = workflowInput;
234
+ const collatorFlowId = `-${workflowId}-$COLLATOR${workflowDimension || ''}-${execIndex}`;
235
+ return {
236
+ status: stream_1.StreamStatus.SUCCESS,
237
+ code: enums_1.HMSH_CODE_DURABLE_ALL,
238
+ metadata: { ...data.metadata },
239
+ data: {
240
+ code: enums_1.HMSH_CODE_DURABLE_ALL,
241
+ items: [...interruptionRegistry],
242
+ size: interruptionRegistry.length,
243
+ workflowDimension: workflowDimension || '',
244
+ index: execIndex,
245
+ originJobId: originJobId || workflowId,
246
+ parentWorkflowId: workflowId,
247
+ workflowId: collatorFlowId,
248
+ workflowTopic: workflowTopic,
249
+ },
250
+ };
251
+ }
252
+ else if (err instanceof errors_1.DurableSleepError) {
253
+ //return the sleep interruption
200
254
  return {
201
255
  status: stream_1.StreamStatus.SUCCESS,
202
256
  code: err.code,
203
257
  metadata: { ...data.metadata },
204
258
  data: {
205
259
  code: err.code,
206
- message: JSON.stringify({ duration: err.duration, index: err.index, dimension: err.dimension }),
260
+ message: JSON.stringify({ duration: err.duration, index: err.index, workflowDimension: err.workflowDimension }),
207
261
  duration: err.duration,
208
262
  index: err.index,
209
- dimension: err.dimension
263
+ workflowDimension: err.workflowDimension,
210
264
  }
211
265
  };
212
- //not an error...just a trigger to wait for a signal
213
266
  }
214
- else if (err instanceof errors_1.DurableWaitForSignalError) {
267
+ else if (err instanceof errors_1.DurableProxyError) {
268
+ //return the proxyActivity interruption
215
269
  return {
216
270
  status: stream_1.StreamStatus.SUCCESS,
217
271
  code: err.code,
218
272
  metadata: { ...data.metadata },
219
273
  data: {
220
274
  code: err.code,
221
- signals: err.signals,
222
- index: err.signals[0].index
275
+ message: JSON.stringify({ message: err.message, workflowId: err.workflowId, activityName: err.activityName, dimension: err.workflowDimension }),
276
+ arguments: err.arguments,
277
+ workflowDimension: err.workflowDimension,
278
+ index: err.index,
279
+ originJobId: err.originJobId,
280
+ parentWorkflowId: err.parentWorkflowId,
281
+ workflowId: err.workflowId,
282
+ workflowTopic: err.workflowTopic,
283
+ activityName: err.activityName,
284
+ backoffCoefficient: err.backoffCoefficient,
285
+ maximumAttempts: err.maximumAttempts,
286
+ maximumInterval: err.maximumInterval,
223
287
  }
224
288
  };
225
- //not an error...still waiting for all the signals to arrive
226
289
  }
227
- else if (err instanceof errors_1.DurableIncompleteSignalError) {
290
+ else if (err instanceof errors_1.DurableChildError) {
291
+ //return the child interruption
292
+ const msg = {
293
+ message: err.message,
294
+ workflowId: err.workflowId,
295
+ dimension: err.workflowDimension
296
+ };
228
297
  return {
229
298
  status: stream_1.StreamStatus.SUCCESS,
230
299
  code: err.code,
231
300
  metadata: { ...data.metadata },
232
- data: { code: err.code }
301
+ data: {
302
+ arguments: err.arguments,
303
+ await: err.await,
304
+ backoffCoefficient: err.backoffCoefficient || enums_1.HMSH_DURABLE_EXP_BACKOFF,
305
+ code: err.code,
306
+ index: err.index,
307
+ message: JSON.stringify(msg),
308
+ maximumAttempts: err.maximumAttempts || enums_1.HMSH_DURABLE_MAX_ATTEMPTS,
309
+ maximumInterval: err.maximumInterval || (0, ms_1.default)(enums_1.HMSH_DURABLE_MAX_INTERVAL) / 1000,
310
+ originJobId: err.originJobId,
311
+ parentWorkflowId: err.parentWorkflowId,
312
+ workflowDimension: err.workflowDimension,
313
+ workflowId: err.workflowId,
314
+ workflowTopic: err.workflowTopic,
315
+ }
233
316
  };
234
317
  }
235
- // all other errors are fatal (598, 597, 596) or will be retried (599)
318
+ // ALL other errors are actual fatal errors (598, 597, 596)
319
+ // OR will be retried (599)
236
320
  return {
237
- status: stream_1.StreamStatus.ERROR,
321
+ status: stream_1.StreamStatus.SUCCESS,
238
322
  code: err.code || new errors_1.DurableRetryError(err.message).code,
239
323
  metadata: { ...data.metadata },
240
- data: { message: err.message, type: err.name }
324
+ data: {
325
+ $error: {
326
+ message: err.message,
327
+ type: err.name,
328
+ name: err.name,
329
+ stack: err.stack,
330
+ code: err.code || new errors_1.DurableRetryError(err.message).code,
331
+ }
332
+ }
241
333
  };
242
334
  }
243
335
  };
@@ -4,29 +4,45 @@ import { ActivityConfig, HookOptions, ProxyType, WorkflowContext, WorkflowOption
4
4
  import { JobInterruptOptions } from '../../types/job';
5
5
  export declare class WorkflowService {
6
6
  /**
7
- * Spawns a child workflow. await and return the result.
7
+ * Return a handle to the hotmesh client currently running the workflow
8
+ * @returns {Promise<HotMesh>} - a hotmesh client
9
+ */
10
+ static getHotMesh(): Promise<HotMesh>;
11
+ /**
12
+ * Returns the current workflow context restored
13
+ * from Redis
14
+ */
15
+ static getContext(): WorkflowContext;
16
+ /**
17
+ * Spawns a child workflow and awaits the return.
8
18
  * @template T - the result type
9
19
  * @param {WorkflowOptions} options - the workflow options
10
20
  * @returns {Promise<T>} - the result of the child workflow
21
+ * @example
22
+ * const result = await Durable.workflow.execChild<typeof resultType>({ ...options });
11
23
  */
12
- static executeChild<T>(options: WorkflowOptions): Promise<T>;
24
+ static execChild<T>(options: WorkflowOptions): Promise<T>;
13
25
  /**
14
- * Spawns a child workflow. return the childJobId.
15
- * This method is used when the result of the child workflow is not needed.
26
+ * Spawns a child workflow and returns the child Job ID.
27
+ * This method guarantees the spawned child has reserved the Job ID,
28
+ * returning a 'DuplicateJobError' error if not. Otherwise,
29
+ * this is a fire-and-forget method.
30
+ *
16
31
  * @param {WorkflowOptions} options - the workflow options
17
32
  * @returns {Promise<string>} - the childJobId
33
+ * @example
34
+ * const childJobId = await Durable.workflow.startChild({ ...options });
18
35
  */
19
- static startChild<T>(options: WorkflowOptions): Promise<string>;
36
+ static startChild(options: WorkflowOptions): Promise<string>;
20
37
  /**
21
- * Wraps activities in a proxy that will durably run them
22
- * @param {ActivityConfig} options - the activity configuration
23
- * that will be used to wrap the activities. You must pass an
24
- * `activities` object to this configuration. The activities object
25
- * should be a key-value pair of activity names and their respective
26
- * functions. This is typically done by importing the activities.
38
+ * Wraps activities in a proxy that durably runs/re-runs them to completion.
39
+ * TODO: verify that activities do not collide if named same on same server but bound to different workflows
27
40
  *
41
+ * @param {ActivityConfig} options - the activity configuration
42
+ * that will be used to wrap the activities.
28
43
  * @returns {ProxyType<ACT>} - a proxy object with the same keys as the
29
44
  * activities object, but with the values replaced by a wrapped function
45
+ *
30
46
  * @example
31
47
  * // import the activities
32
48
  * import * as activities from './activities';
@@ -36,6 +52,7 @@ export declare class WorkflowService {
36
52
  * const { activity1, activity2 } = WorkflowService.proxyActivities<typeof activities>({ activities });
37
53
  */
38
54
  static proxyActivities<ACT>(options?: ActivityConfig): ProxyType<ACT>;
55
+ static wrapActivity<T>(activityName: string, options?: ActivityConfig): T;
39
56
  /**
40
57
  * Returns a search session for use when reading/writing to the workflow HASH.
41
58
  * The search session provides access to methods like `get`, `mget`, `set`, `del`, and `incr`.
@@ -43,15 +60,12 @@ export declare class WorkflowService {
43
60
  */
44
61
  static search(): Promise<Search>;
45
62
  /**
46
- * Return a handle to the hotmesh client currently running the workflow
47
- * @returns {Promise<HotMesh>} - a hotmesh client
63
+ * Returns the synchronous output from the activity (replay)
64
+ * if available locally
65
+ * @param {string} prefix - one of: proxy, child, start, wait etc
66
+ * @returns
48
67
  */
49
- static getHotMesh(): Promise<HotMesh>;
50
- /**
51
- * Returns the current workflow context
52
- * @returns {WorkflowContext} - the current workflow context
53
- */
54
- static getContext(): WorkflowContext;
68
+ static didRun(prefix: string): Promise<[boolean, number, any]>;
55
69
  /**
56
70
  * Those methods that may only be called once must be protected by flagging
57
71
  * their execution with a unique key (the key is stored in the HASH alongside
@@ -67,8 +81,8 @@ export declare class WorkflowService {
67
81
  */
68
82
  static random(): number;
69
83
  /**
70
- * Sends signal data into any other paused thread (which is paused and
71
- * awaiting the signal) from within a hook-thread or the main-thread
84
+ * Sends signal data into any other paused thread (which is currently
85
+ * awaiting the signal)
72
86
  * @param {string} signalId - the signal id
73
87
  * @param {Record<any, any>} data - the signal data
74
88
  * @returns {Promise<string>} - the stream id
@@ -81,44 +95,33 @@ export declare class WorkflowService {
81
95
  * @param {HookOptions} options - the hook options
82
96
  */
83
97
  static hook(options: HookOptions): Promise<string>;
84
- static getLocalState(): {
85
- workflowId: any;
86
- namespace: any;
87
- workflowTopic: any;
88
- workflowDimension: any;
89
- counter: any;
90
- replay: any;
91
- };
92
98
  /**
93
99
  * Executes a function once and caches the result. If the function is called
94
100
  * again, the cached result is returned. This is useful for wrapping
95
101
  * expensive activity calls that should only be run once, but which might
96
- * not require the configuration nuance/expense provided by proxyActivities.
102
+ * not require the cost and safety provided by proxyActivities.
97
103
  * @template T - the result type
98
104
  */
99
105
  static once<T>(fn: (...args: any[]) => Promise<T>, ...args: any[]): Promise<T>;
100
106
  /**
101
107
  * Interrupts a running job
102
- *
103
- * @param {string} jobId - the target job id
104
- * @param {JobInterruptOptions} options - the interrupt options
105
- * @returns {Promise<string>} - the stream id
106
108
  */
107
109
  static interrupt(jobId: string, options?: JobInterruptOptions): Promise<string | void>;
108
110
  /**
109
111
  * Sleeps the workflow for a duration. As the function is reentrant,
110
112
  * upon reentry, the function will traverse prior execution paths up
111
- * until the sleep command and then resume execution from that point.
112
- * @param {string} duration - for example: '1 minute', '2 hours', '3 days'
113
- * @returns {Promise<number>}
113
+ * until the sleep command and then resume execution thereafter.
114
+ * @param {string} duration - See the `ms` package for syntax examples: '1 minute', '2 hours', '3 days'
115
+ * @returns {Promise<number>} - resolved duration in seconds
114
116
  */
115
117
  static sleepFor(duration: string): Promise<number>;
116
118
  /**
117
- * Waits for a signal to awaken
118
- * @param {string[]} signals - the signals to wait for
119
- * @param {Record<string, string>} options - the options
120
- * @returns {Promise<Record<any, any>[]>}
119
+ * Pauses the workflow until `signalId` is received.
120
+ * @template T - the result type
121
+ * @param {string} signalId - a unique, shareable guid (e.g, 'abc123')
122
+ * @returns {Promise<T>}
123
+ * @example
124
+ * const result = await Durable.workflow.waitFor<typeof resultType>('abc123');
121
125
  */
122
- static waitForSignal(signals: string[], options?: Record<string, string>): Promise<Record<any, any>[]>;
123
- static wrapActivity<T>(activityName: string, options?: ActivityConfig): T;
126
+ static waitFor<T>(signalId: string): Promise<T>;
124
127
  }