@hotmeshio/hotmesh 0.0.9 → 0.0.11

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 (59) hide show
  1. package/README.md +84 -77
  2. package/build/modules/errors.d.ts +17 -1
  3. package/build/modules/errors.js +29 -1
  4. package/build/modules/key.d.ts +2 -2
  5. package/build/modules/key.js +3 -3
  6. package/build/package.json +2 -1
  7. package/build/services/activities/activity.d.ts +1 -0
  8. package/build/services/activities/activity.js +13 -2
  9. package/build/services/activities/cycle.js +6 -1
  10. package/build/services/activities/trigger.js +2 -3
  11. package/build/services/collator/index.d.ts +8 -0
  12. package/build/services/collator/index.js +11 -1
  13. package/build/services/durable/factory.d.ts +18 -1
  14. package/build/services/durable/factory.js +46 -4
  15. package/build/services/durable/handle.js +25 -7
  16. package/build/services/durable/native.js +0 -1
  17. package/build/services/durable/worker.d.ts +3 -3
  18. package/build/services/durable/worker.js +16 -11
  19. package/build/services/durable/workflow.js +1 -1
  20. package/build/services/hotmesh/index.js +1 -1
  21. package/build/services/pipe/functions/math.d.ts +4 -0
  22. package/build/services/pipe/functions/math.js +73 -0
  23. package/build/services/pipe/functions/number.d.ts +0 -4
  24. package/build/services/pipe/functions/number.js +0 -73
  25. package/build/services/signaler/stream.js +6 -3
  26. package/build/services/store/index.js +2 -2
  27. package/build/services/stream/clients/ioredis.js +1 -1
  28. package/build/services/stream/clients/redis.js +1 -1
  29. package/build/services/sub/clients/ioredis.js +1 -1
  30. package/build/services/sub/clients/redis.js +1 -1
  31. package/build/types/durable.d.ts +8 -3
  32. package/build/types/index.d.ts +1 -0
  33. package/modules/errors.ts +42 -1
  34. package/modules/key.ts +2 -2
  35. package/package.json +2 -1
  36. package/services/activities/activity.ts +14 -2
  37. package/services/activities/cycle.ts +6 -1
  38. package/services/activities/trigger.ts +2 -3
  39. package/services/collator/index.ts +12 -1
  40. package/services/durable/factory.ts +46 -4
  41. package/services/durable/handle.ts +23 -8
  42. package/services/durable/native.ts +0 -1
  43. package/services/durable/worker.ts +27 -13
  44. package/services/durable/workflow.ts +1 -1
  45. package/services/hotmesh/index.ts +2 -2
  46. package/services/pipe/functions/math.ts +74 -0
  47. package/services/pipe/functions/number.ts +0 -75
  48. package/services/signaler/stream.ts +6 -3
  49. package/services/store/index.ts +3 -3
  50. package/services/stream/clients/ioredis.ts +2 -2
  51. package/services/stream/clients/redis.ts +2 -2
  52. package/services/sub/clients/ioredis.ts +2 -2
  53. package/services/sub/clients/redis.ts +2 -2
  54. package/types/durable.ts +12 -5
  55. package/types/index.ts +15 -0
  56. package/build/services/dimension/index.d.ts +0 -29
  57. package/build/services/dimension/index.js +0 -35
  58. package/services/dimension/README.md +0 -73
  59. package/services/dimension/index.ts +0 -39
@@ -1,4 +1,21 @@
1
- const getWorkflowYAML = (topic: string, version = '1') => {
1
+ /**
2
+ * 1) `maxSystemRetries` | can be 0 to 3 and represents milliseconds;
3
+ * if there is an error, the workflow will retry up to `maxSystemRetries` times
4
+ * delaying by 10, 100, and 1000ms; this is a system level retry
5
+ * and is not configurable. It exists to handle intermittent network
6
+ * errors. (NOTE: each retry spawns a new transition stream)
7
+ *
8
+ * 2) `backoffExponent` | can be any number and represents `seconds` when applied;
9
+ * retries will happen indefinitely and adhere to the
10
+ * exponential backoff algorithm by multiplying by `backoffExponent`.
11
+ * For example, if `backoffExponent` is 10, the workflow will retry
12
+ * in 10s, 100s, 1000s, 10000s, etc.
13
+ *
14
+ * EXAMPLE | Using `maxSystemRetries = 3` and `backoffExponent = 10`, errant
15
+ * workflows will be retried on the following schedule (8 times in 27 hours):
16
+ * => 10ms, 100ms, 1000ms, 10s, 100s, 1_000s, 10_000s, 100_000s
17
+ */
18
+ const getWorkflowYAML = (topic: string, version = '1', maxSystemRetries = 2, backoffExponent = 10) => {
2
19
  return `app:
3
20
  id: ${topic}
4
21
  version: '${version}'
@@ -30,10 +47,20 @@ const getWorkflowYAML = (topic: string, version = '1') => {
30
47
  a1:
31
48
  type: activity
32
49
  cycle: true
33
-
50
+ output:
51
+ schema:
52
+ type: object
53
+ properties:
54
+ duration:
55
+ type: number
56
+ maps:
57
+ duration: ${backoffExponent}
58
+
34
59
  w1:
35
60
  type: worker
36
61
  topic: ${topic}
62
+ retry:
63
+ '599': [${maxSystemRetries}]
37
64
  input:
38
65
  schema:
39
66
  type: object
@@ -55,18 +82,33 @@ const getWorkflowYAML = (topic: string, version = '1') => {
55
82
  maps:
56
83
  response: '{$self.output.data.response}'
57
84
 
85
+ a599:
86
+ title: Sleep before trying again
87
+ type: activity
88
+ sleep: "{a1.output.data.duration}"
89
+
58
90
  c1:
91
+ title: Goto Activity a1
59
92
  type: cycle
60
93
  ancestor: a1
94
+ input:
95
+ maps:
96
+ duration:
97
+ '@pipe':
98
+ - ['{a1.output.data.duration}', ${backoffExponent}]
99
+ - ['{@math.multiply}']
100
+
61
101
  transitions:
62
102
  t1:
63
103
  - to: a1
64
104
  a1:
65
105
  - to: w1
66
106
  w1:
67
- - to: c1
107
+ - to: a599
68
108
  conditions:
69
- code: 500
109
+ code: 599
110
+ a599:
111
+ - to: c1
70
112
  `;
71
113
  }
72
114
 
@@ -16,22 +16,37 @@ export class WorkflowHandleService {
16
16
  let status = await this.hotMesh.getStatus(this.workflowId);
17
17
  const topic = `${this.workflowTopic}.${this.workflowId}`;
18
18
 
19
- if (status == 0) {
20
- return (await this.hotMesh.getState(this.workflowTopic, this.workflowId)).data?.response;
21
- }
22
-
23
19
  return new Promise((resolve, reject) => {
24
20
  let isResolved = false;
25
21
  //common fulfill/unsubscribe
26
- const complete = async (response?: any) => {
22
+ const complete = async (response?: any, err?: string) => {
27
23
  if (isResolved) return;
28
24
  isResolved = true;
29
25
  this.hotMesh.unsub(topic);
30
- resolve(response || (await this.hotMesh.getState(this.workflowTopic, this.workflowId)).data?.response);
26
+ if (err) {
27
+ return reject(JSON.parse(err));
28
+ } else if (!response) {
29
+ const state = await this.hotMesh.getState(this.workflowTopic, this.workflowId);
30
+ if (!state.data && state.metadata.err) {
31
+ return reject(JSON.parse(state.metadata.err));
32
+ }
33
+ response = state.data?.response;
34
+ }
35
+ resolve(response);
31
36
  };
32
- this.hotMesh.sub(topic, async (topic: string, message: JobOutput) => {
33
- await complete(message.data?.response);
37
+ //check for done
38
+ if (status == 0) {
39
+ return complete();
40
+ }
41
+ //subscribe to topic
42
+ this.hotMesh.sub(topic, async (topic: string, state: JobOutput) => {
43
+ if (!state.data && state.metadata.err) {
44
+ await complete(null, state.metadata.err);
45
+ } else {
46
+ await complete(state.data?.response);
47
+ }
34
48
  });
49
+ //resolve for race condition
35
50
  setTimeout(async () => {
36
51
  status = await this.hotMesh.getStatus(this.workflowId);
37
52
  if (status == 0) {
@@ -21,7 +21,6 @@ async function run() {
21
21
  });
22
22
  const worker = await Worker.create({
23
23
  connection,
24
- namespace: 'default',
25
24
  taskQueue: 'hello-world',
26
25
  workflow: workflows.example,
27
26
  activities,
@@ -2,8 +2,18 @@ import { asyncLocalStorage } from './asyncLocalStorage';
2
2
  import { HotMeshService as HotMesh } from '../hotmesh';
3
3
  import { RedisClass, RedisOptions } from '../../types/redis';
4
4
  import { StreamData, StreamDataResponse, StreamStatus } from '../../types/stream';
5
- import { ActivityDataType, Connection, Registry, WorkerConfig, WorkflowDataType } from "../../types/durable";
5
+ import { ActivityWorkflowDataType,
6
+ Connection,
7
+ Registry,
8
+ WorkerConfig,
9
+ WorkerOptions,
10
+ WorkflowDataType } from "../../types/durable";
6
11
  import { getWorkflowYAML, getActivityYAML } from './factory';
12
+ import {
13
+ DurableFatalError,
14
+ DurableMaxedError,
15
+ DurableRetryError,
16
+ DurableTimeoutError } from '../../modules/errors';
7
17
 
8
18
  /*
9
19
  Here is an example of how the methods in this file are used:
@@ -25,7 +35,6 @@ async function run() {
25
35
  });
26
36
  const worker = await Worker.create({
27
37
  connection,
28
- namespace: 'default',
29
38
  taskQueue: 'hello-world',
30
39
  workflow: workflows.example,
31
40
  activities,
@@ -46,7 +55,7 @@ export class WorkerService {
46
55
  workflowRunner: HotMesh;
47
56
  activityRunner: HotMesh;
48
57
 
49
- static getHotMesh = async (worflowTopic: string) => {
58
+ static getHotMesh = async (worflowTopic: string, options?: WorkerOptions) => {
50
59
  if (WorkerService.instances.has(worflowTopic)) {
51
60
  return await WorkerService.instances.get(worflowTopic);
52
61
  }
@@ -55,17 +64,17 @@ export class WorkerService {
55
64
  engine: { redis: { ...WorkerService.connection } }
56
65
  });
57
66
  WorkerService.instances.set(worflowTopic, hotMesh);
58
- await WorkerService.activateWorkflow(await hotMesh, worflowTopic, getWorkflowYAML);
67
+ await WorkerService.activateWorkflow(await hotMesh, worflowTopic, getWorkflowYAML, options);
59
68
  return hotMesh;
60
69
  }
61
70
 
62
- static async activateWorkflow(hotMesh: HotMesh, topic: string, factory: Function) {
71
+ static async activateWorkflow(hotMesh: HotMesh, topic: string, dagFactory: Function, options: WorkerOptions = {}) {
63
72
  const version = '1';
64
73
  const app = await hotMesh.engine.store.getApp(topic);
65
74
  const appVersion = app?.version;
66
75
  if(!appVersion) {
67
76
  try {
68
- await hotMesh.deploy(factory(topic, version));
77
+ await hotMesh.deploy(dagFactory(topic, version, options.maxSystemRetries, options.backoffExponent));
69
78
  await hotMesh.activate(version);
70
79
  } catch (err) {
71
80
  hotMesh.engine.logger.error('durable-worker-deploy-activate-err', err);
@@ -118,7 +127,7 @@ export class WorkerService {
118
127
  worker.activityRunner = await worker.initActivityWorkflow(config, activityTopic);
119
128
  await WorkerService.activateWorkflow(worker.activityRunner, activityTopic, getActivityYAML);
120
129
  worker.workflowRunner = await worker.initWorkerWorkflow(config, workflowTopic, workflowFunction);
121
- await WorkerService.activateWorkflow(worker.workflowRunner, workflowTopic, getWorkflowYAML);
130
+ await WorkerService.activateWorkflow(worker.workflowRunner, workflowTopic, getWorkflowYAML, config.options);
122
131
  return worker;
123
132
  }
124
133
 
@@ -161,7 +170,7 @@ export class WorkerService {
161
170
  return async (data: StreamData): Promise<StreamDataResponse> => {
162
171
  try {
163
172
  //always run the activity function when instructed; return the response
164
- const activityInput = data.data as unknown as ActivityDataType;
173
+ const activityInput = data.data as unknown as ActivityWorkflowDataType;
165
174
  const activityName = activityInput.activityName;
166
175
  const activityFunction = WorkerService.activityRegistry[activityName];
167
176
  const pojoResponse = await activityFunction.apply(this, activityInput.arguments);
@@ -173,12 +182,16 @@ export class WorkerService {
173
182
  };
174
183
  } catch (err) {
175
184
  this.activityRunner.engine.logger.error('durable-worker-activity-err', err);
185
+ if (!(err instanceof DurableTimeoutError) &&
186
+ !(err instanceof DurableMaxedError) &&
187
+ !(err instanceof DurableFatalError)) {
188
+ err = new DurableRetryError(err.message);
189
+ }
176
190
  return {
177
191
  status: StreamStatus.ERROR,
178
- code: 500,
179
- message: err.message,
192
+ code: err.code,
180
193
  metadata: { ...data.metadata },
181
- data: { error: err }
194
+ data: { message: err.message }
182
195
  } as StreamDataResponse;
183
196
  }
184
197
  }
@@ -258,11 +271,12 @@ export class WorkerService {
258
271
  data: { response: workflowResponse }
259
272
  };
260
273
  } catch (err) {
274
+ // 59* - Durable*Error
261
275
  return {
262
276
  status: StreamStatus.ERROR,
263
- code: 500,
277
+ code: err.code || new DurableRetryError(err.message).code,
264
278
  metadata: { ...data.metadata },
265
- data: { error: err }
279
+ data: { message: err.message, type: err.name }
266
280
  } as StreamDataResponse;
267
281
  }
268
282
  }
@@ -62,7 +62,7 @@ export class WorkflowService {
62
62
  const client = new Client({
63
63
  connection: await Connection.connect(WorkerService.connection),
64
64
  });
65
- //todo: should I allow-cross/app callback (pj:'@DURABLE@hello-world@<pjid>'/pa: <paid>/pd: <pdad>)
65
+ //todo: allow cross/app callback (pj:'@DURABLE@hello-world@<pjid>'/pa: <paid>/pd: <pdad>)
66
66
  const handle = await client.workflow.start({
67
67
  ...options,
68
68
  workflowId: `${workflowId}${options.workflowId}`, //concat
@@ -1,5 +1,5 @@
1
1
  import { v4 as uuidv4 } from 'uuid';
2
- import { PSNS } from '../../modules/key';
2
+ import { HMNS } from '../../modules/key';
3
3
  import { EngineService } from '../engine';
4
4
  import { LoggerService, ILogger } from '../logger';
5
5
  import { StreamSignaler } from '../signaler/stream';
@@ -33,7 +33,7 @@ class HotMeshService {
33
33
 
34
34
  verifyAndSetNamespace(namespace?: string) {
35
35
  if (!namespace) {
36
- this.namespace = PSNS;
36
+ this.namespace = HMNS;
37
37
  } else if (!namespace.match(/^[A-Za-z0-9-]+$/)) {
38
38
  throw new Error(`config.namespace [${namespace}] is invalid`);
39
39
  } else {
@@ -1,4 +1,78 @@
1
1
  class MathHandler {
2
+ add(...operands: (number | number[])[]): number {
3
+ // @ts-ignore
4
+ return operands.reduce((a: number, b: number | number[]) => {
5
+ if (Array.isArray(b)) {
6
+ return a + this.add(...b);
7
+ } else {
8
+ return a + b;
9
+ }
10
+ }, 0);
11
+ }
12
+
13
+ subtract(...operands: (number | number[])[]): number {
14
+ if (operands.length === 0) {
15
+ throw new Error('At least one operand is required.');
16
+ }
17
+ let flatOperands: number[] = [];
18
+ operands.forEach((op: number | number[]) => {
19
+ if (Array.isArray(op)) {
20
+ flatOperands = [...flatOperands, ...op];
21
+ } else {
22
+ flatOperands.push(op);
23
+ }
24
+ });
25
+ if (flatOperands.length === 0) {
26
+ throw new Error('At least one operand is required after flattening.');
27
+ }
28
+ const result = flatOperands.reduce((a: number, b: number, i: number) => {
29
+ return i === 0 ? a : a - b;
30
+ });
31
+ return result;
32
+ }
33
+
34
+ multiply(...operands: (number | number[])[]): number {
35
+ if (operands.length === 0) {
36
+ throw new Error('At least one operand is required.');
37
+ }
38
+
39
+ // @ts-ignore
40
+ return operands.reduce((a: number, b: number | number[]) => {
41
+ if (Array.isArray(b)) {
42
+ return a * this.multiply(...b);
43
+ } else {
44
+ return a * b;
45
+ }
46
+ }, 1);
47
+ }
48
+
49
+ divide(...operands: (number | number[])[]): number {
50
+ if (operands.length === 0) {
51
+ throw new Error('At least one operand is required.');
52
+ }
53
+ let flatOperands: number[] = [];
54
+ operands.forEach((op: number | number[]) => {
55
+ if (Array.isArray(op)) {
56
+ flatOperands = [...flatOperands, ...op];
57
+ } else {
58
+ flatOperands.push(op);
59
+ }
60
+ });
61
+ if (flatOperands.length === 0) {
62
+ throw new Error('At least one operand is required after flattening.');
63
+ }
64
+ const result = flatOperands.reduce((a: number, b: number, i: number) => {
65
+ if (b === 0) {
66
+ return NaN;
67
+ }
68
+ return i === 0 ? a : a / b;
69
+ });
70
+ if (isNaN(result)) {
71
+ return NaN;
72
+ }
73
+ return result;
74
+ }
75
+
2
76
  abs(x: number): number {
3
77
  return Math.abs(x);
4
78
  }
@@ -70,81 +70,6 @@ class NumberHandler {
70
70
  round(input: number): number {
71
71
  return Math.round(input);
72
72
  }
73
-
74
- add(...operands: (number | number[])[]): number {
75
- // @ts-ignore
76
- return operands.reduce((a: number, b: number | number[]) => {
77
- if (Array.isArray(b)) {
78
- return a + this.add(...b);
79
- } else {
80
- return a + b;
81
- }
82
- }, 0);
83
- }
84
-
85
- subtract(...operands: (number | number[])[]): number {
86
- if (operands.length === 0) {
87
- throw new Error('At least one operand is required.');
88
- }
89
- let flatOperands: number[] = [];
90
- operands.forEach((op: number | number[]) => {
91
- if (Array.isArray(op)) {
92
- flatOperands = [...flatOperands, ...op];
93
- } else {
94
- flatOperands.push(op);
95
- }
96
- });
97
- if (flatOperands.length === 0) {
98
- throw new Error('At least one operand is required after flattening.');
99
- }
100
- const result = flatOperands.reduce((a: number, b: number, i: number) => {
101
- return i === 0 ? a : a - b;
102
- });
103
- return result;
104
- }
105
-
106
-
107
- multiply(...operands: (number | number[])[]): number {
108
- if (operands.length === 0) {
109
- throw new Error('At least one operand is required.');
110
- }
111
-
112
- // @ts-ignore
113
- return operands.reduce((a: number, b: number | number[]) => {
114
- if (Array.isArray(b)) {
115
- return a * this.multiply(...b);
116
- } else {
117
- return a * b;
118
- }
119
- }, 1);
120
- }
121
-
122
- divide(...operands: (number | number[])[]): number {
123
- if (operands.length === 0) {
124
- throw new Error('At least one operand is required.');
125
- }
126
- let flatOperands: number[] = [];
127
- operands.forEach((op: number | number[]) => {
128
- if (Array.isArray(op)) {
129
- flatOperands = [...flatOperands, ...op];
130
- } else {
131
- flatOperands.push(op);
132
- }
133
- });
134
- if (flatOperands.length === 0) {
135
- throw new Error('At least one operand is required after flattening.');
136
- }
137
- const result = flatOperands.reduce((a: number, b: number, i: number) => {
138
- if (b === 0) {
139
- return NaN;
140
- }
141
- return i === 0 ? a : a / b;
142
- });
143
- if (isNaN(result)) {
144
- return NaN;
145
- }
146
- return result;
147
- }
148
73
  }
149
74
 
150
75
  export { NumberHandler };
@@ -16,7 +16,7 @@ import {
16
16
  StreamStatus
17
17
  } from '../../types/stream';
18
18
 
19
- const MAX_RETRIES = 4; //max delay (10s using exponential backoff);
19
+ const MAX_RETRIES = 3; //local retry; 10, 100, 1000ms
20
20
  const MAX_TIMEOUT_MS = 60000;
21
21
  const GRADUATED_INTERVAL_MS = 5000;
22
22
  const BLOCK_DURATION = 15000; //Set to `15` so SIGINT/SIGTERM can interrupt; set to `0` to BLOCK indefinitely
@@ -189,8 +189,11 @@ class StreamSignaler {
189
189
  const policy = policies?.[errorCode];
190
190
  const maxRetries = policy?.[0];
191
191
  const tryCount = Math.min(input.metadata.try || 0, MAX_RETRIES);
192
- if (maxRetries >= tryCount) {
193
- return[true, Math.pow(10, tryCount)];
192
+ //only possible values for maxRetries are 1, 2, 3
193
+ //only possible values for tryCount are 0, 1, 2
194
+ if (maxRetries > tryCount) {
195
+ // 10ms, 100ms, or 1000ms delays between system retries
196
+ return[true, Math.pow(10, tryCount + 1)];
194
197
  }
195
198
  return [false, 0];
196
199
  }
@@ -2,7 +2,7 @@ import {
2
2
  KeyService,
3
3
  KeyStoreParams,
4
4
  KeyType,
5
- PSNS} from '../../modules/key';
5
+ HMNS} from '../../modules/key';
6
6
  import { ILogger } from '../logger';
7
7
  import { MDATA_SYMBOLS, SerializerService as Serializer } from '../serializer';
8
8
  import { Cache } from './cache';
@@ -119,7 +119,7 @@ abstract class StoreService<T, U extends AbstractRedisClient> {
119
119
  this.redisClient = redisClient;
120
120
  }
121
121
 
122
- async init(namespace = PSNS, appId: string, logger: ILogger): Promise<HotMeshApps> {
122
+ async init(namespace = HMNS, appId: string, logger: ILogger): Promise<HotMeshApps> {
123
123
  this.namespace = namespace;
124
124
  this.appId = appId;
125
125
  this.logger = logger;
@@ -178,7 +178,7 @@ abstract class StoreService<T, U extends AbstractRedisClient> {
178
178
  if (bCreate) {
179
179
  const packageJson = await import('../../package.json');
180
180
  const version: string = packageJson['version'] || '0.0.0';
181
- settings = { namespace: PSNS, version } as HotMeshSettings;
181
+ settings = { namespace: HMNS, version } as HotMeshSettings;
182
182
  await this.setSettings(settings);
183
183
  return settings;
184
184
  }
@@ -1,4 +1,4 @@
1
- import { KeyService, KeyStoreParams, KeyType, PSNS } from '../../../modules/key';
1
+ import { KeyService, KeyStoreParams, KeyType, HMNS } from '../../../modules/key';
2
2
  import { ILogger } from '../../logger';
3
3
  import { StreamService } from '../index';
4
4
  import { RedisClientType, RedisMultiType } from '../../../types/ioredisclient';
@@ -14,7 +14,7 @@ class IORedisStreamService extends StreamService<RedisClientType, RedisMultiType
14
14
  super(redisClient);
15
15
  }
16
16
 
17
- async init(namespace = PSNS, appId: string, logger: ILogger): Promise<void> {
17
+ async init(namespace = HMNS, appId: string, logger: ILogger): Promise<void> {
18
18
  this.namespace = namespace;
19
19
  this.logger = logger;
20
20
  this.appId = appId;
@@ -1,4 +1,4 @@
1
- import { KeyService, KeyStoreParams, KeyType, PSNS } from '../../../modules/key';
1
+ import { KeyService, KeyStoreParams, KeyType, HMNS } from '../../../modules/key';
2
2
  import { ILogger } from '../../logger';
3
3
  import { StreamService } from '../index';
4
4
  import { RedisClientType, RedisMultiType } from '../../../types/redisclient';
@@ -14,7 +14,7 @@ class RedisStreamService extends StreamService<RedisClientType, RedisMultiType>
14
14
  super(redisClient);
15
15
  }
16
16
 
17
- async init(namespace = PSNS, appId: string, logger: ILogger): Promise<void> {
17
+ async init(namespace = HMNS, appId: string, logger: ILogger): Promise<void> {
18
18
  this.namespace = namespace;
19
19
  this.logger = logger;
20
20
  this.appId = appId;
@@ -1,4 +1,4 @@
1
- import { KeyService, KeyStoreParams, KeyType, PSNS } from '../../../modules/key';
1
+ import { KeyService, KeyStoreParams, KeyType, HMNS } from '../../../modules/key';
2
2
  import { ILogger } from '../../logger';
3
3
  import { SubService } from '../index';
4
4
  import { RedisClientType, RedisMultiType } from '../../../types/ioredisclient';
@@ -14,7 +14,7 @@ class IORedisSubService extends SubService<RedisClientType, RedisMultiType> {
14
14
  super(redisClient);
15
15
  }
16
16
 
17
- async init(namespace = PSNS, appId: string, engineId: string, logger: ILogger): Promise<void> {
17
+ async init(namespace = HMNS, appId: string, engineId: string, logger: ILogger): Promise<void> {
18
18
  this.namespace = namespace;
19
19
  this.logger = logger;
20
20
  this.appId = appId;
@@ -1,4 +1,4 @@
1
- import { KeyService, KeyStoreParams, KeyType, PSNS } from '../../../modules/key';
1
+ import { KeyService, KeyStoreParams, KeyType, HMNS } from '../../../modules/key';
2
2
  import { ILogger } from '../../logger';
3
3
  import { SubService } from '../index';
4
4
  import { RedisClientType, RedisMultiType } from '../../../types/redisclient';
@@ -14,7 +14,7 @@ class RedisSubService extends SubService<RedisClientType, RedisMultiType> {
14
14
  super(redisClient);
15
15
  }
16
16
 
17
- async init(namespace = PSNS, appId: string, engineId: string, logger: ILogger): Promise<void> {
17
+ async init(namespace = HMNS, appId: string, engineId: string, logger: ILogger): Promise<void> {
18
18
  this.namespace = namespace;
19
19
  this.logger = logger;
20
20
  this.appId = appId;
package/types/durable.ts CHANGED
@@ -9,7 +9,7 @@ type WorkflowOptions = {
9
9
  workflowSpan?: string;
10
10
  }
11
11
 
12
- type ActivityDataType = {
12
+ type ActivityWorkflowDataType = {
13
13
  activityName: string;
14
14
  arguments: any[];
15
15
  workflowId: string;
@@ -39,9 +39,15 @@ type Registry = {
39
39
 
40
40
  type WorkerConfig = {
41
41
  connection: Connection;
42
- namespace: string; //`appid` in the YAML (e.g, 'default')
42
+ namespace?: string; //`appid` in the YAML (e.g, 'default')
43
43
  taskQueue: string; //`subscribes` in the YAML (e.g, 'hello-world')
44
- workflow: Function //target function to run
44
+ workflow: Function; //target function to run
45
+ options?: WorkerOptions;
46
+ }
47
+
48
+ type WorkerOptions = {
49
+ maxSystemRetries?: number; //1-3 (10ms, 100ms, 1_000ms)
50
+ backoffExponent?: number; //2-10ish
45
51
  }
46
52
 
47
53
  type ContextType = {
@@ -67,7 +73,7 @@ type ActivityConfig = {
67
73
 
68
74
  export {
69
75
  ActivityConfig,
70
- ActivityDataType,
76
+ ActivityWorkflowDataType,
71
77
  ClientConfig,
72
78
  ContextType,
73
79
  ConnectionConfig,
@@ -76,6 +82,7 @@ export {
76
82
  ProxyType,
77
83
  Registry,
78
84
  WorkerConfig,
85
+ WorkerOptions,
79
86
  WorkflowDataType,
80
87
  WorkflowOptions,
81
- };
88
+ };
package/types/index.ts CHANGED
@@ -26,6 +26,21 @@ export { CacheMode } from './cache';
26
26
  export {
27
27
  CollationFaultType,
28
28
  CollationStage } from './collator';
29
+ export {
30
+ ActivityConfig,
31
+ ActivityWorkflowDataType,
32
+ ClientConfig,
33
+ ContextType,
34
+ ConnectionConfig,
35
+ Connection,
36
+ NativeConnection,
37
+ ProxyType,
38
+ Registry,
39
+ WorkerConfig,
40
+ WorkerOptions,
41
+ WorkflowDataType,
42
+ WorkflowOptions,
43
+ }from './durable'
29
44
  export {
30
45
  HookCondition,
31
46
  HookConditions,
@@ -1,29 +0,0 @@
1
- import { HotMeshGraph } from '../../types/hotmesh';
2
- declare class DimensionService {
3
- static targetLength: number;
4
- /**
5
- * entry point for compiler-type activities. This is called by the compiler
6
- * to bind the sorted activity IDs to the trigger activity. These are then used
7
- * at runtime by the activities to track job/activity status.
8
- * @param graphs
9
- */
10
- static compile(graphs: HotMeshGraph[]): void;
11
- /**
12
- * All activities exist on a dimensional plane. Zero
13
- * is the default and is implied if no dimension is
14
- * present in the hash item key. EVERY value in the
15
- * job ledger is dimensionalized even if the dimension
16
- * is not present. The key, `AaA`, might not contain
17
- * a dimensional index, but it is still implicitly
18
- * dimensionalized as `AaA,0` (assuming a trigger).
19
- * A value of `AxY,0,0,0,0,1,0,0` would reflect that
20
- * an ancestor activity was dimensionalized beyond
21
- * the default. The dimensional string must
22
- * be included if not zero. There is likely a preceding
23
- * sibling dimension, so it would not need to include
24
- * the suffix, so these addresses are equivalent:
25
- * `AxY,0,0,0,0,0,0,0` == `AxY` for said sibling.
26
- */
27
- static getSeed(index?: number): string;
28
- }
29
- export { DimensionService };