@hotmeshio/hotmesh 0.0.52 → 0.0.54

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 +22 -18
  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 +58 -20
  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 +63 -14
  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 +9 -5
  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.d.ts +5 -2
  20. package/build/services/activities/trigger.js +34 -4
  21. package/build/services/activities/worker.js +6 -6
  22. package/build/services/compiler/deployer.js +33 -5
  23. package/build/services/compiler/validator.d.ts +2 -0
  24. package/build/services/compiler/validator.js +5 -1
  25. package/build/services/durable/client.d.ts +7 -1
  26. package/build/services/durable/client.js +57 -38
  27. package/build/services/durable/exporter.d.ts +27 -81
  28. package/build/services/durable/exporter.js +153 -325
  29. package/build/services/durable/handle.d.ts +13 -8
  30. package/build/services/durable/handle.js +61 -48
  31. package/build/services/durable/index.d.ts +0 -2
  32. package/build/services/durable/index.js +0 -2
  33. package/build/services/durable/schemas/factory.d.ts +33 -0
  34. package/build/services/durable/schemas/factory.js +2356 -0
  35. package/build/services/durable/search.js +8 -8
  36. package/build/services/durable/worker.js +117 -25
  37. package/build/services/durable/workflow.d.ts +67 -52
  38. package/build/services/durable/workflow.js +322 -306
  39. package/build/services/engine/index.d.ts +2 -2
  40. package/build/services/engine/index.js +5 -2
  41. package/build/services/exporter/index.d.ts +2 -4
  42. package/build/services/exporter/index.js +4 -5
  43. package/build/services/hotmesh/index.d.ts +2 -2
  44. package/build/services/hotmesh/index.js +2 -2
  45. package/build/services/mapper/index.d.ts +6 -2
  46. package/build/services/mapper/index.js +6 -2
  47. package/build/services/pipe/functions/array.d.ts +2 -10
  48. package/build/services/pipe/functions/array.js +30 -28
  49. package/build/services/pipe/functions/conditional.d.ts +1 -0
  50. package/build/services/pipe/functions/conditional.js +3 -0
  51. package/build/services/pipe/functions/date.d.ts +1 -0
  52. package/build/services/pipe/functions/date.js +4 -0
  53. package/build/services/pipe/functions/index.d.ts +2 -0
  54. package/build/services/pipe/functions/index.js +2 -0
  55. package/build/services/pipe/functions/logical.d.ts +5 -0
  56. package/build/services/pipe/functions/logical.js +12 -0
  57. package/build/services/pipe/functions/object.d.ts +3 -0
  58. package/build/services/pipe/functions/object.js +25 -7
  59. package/build/services/pipe/index.d.ts +20 -3
  60. package/build/services/pipe/index.js +82 -16
  61. package/build/services/router/index.js +14 -3
  62. package/build/services/serializer/index.d.ts +3 -2
  63. package/build/services/serializer/index.js +11 -4
  64. package/build/services/store/clients/ioredis.js +6 -6
  65. package/build/services/store/clients/redis.js +7 -7
  66. package/build/services/store/index.d.ts +2 -0
  67. package/build/services/store/index.js +4 -1
  68. package/build/services/stream/clients/ioredis.js +8 -8
  69. package/build/services/stream/clients/redis.js +1 -1
  70. package/build/types/activity.d.ts +60 -5
  71. package/build/types/durable.d.ts +183 -36
  72. package/build/types/error.d.ts +48 -0
  73. package/build/types/error.js +2 -0
  74. package/build/types/exporter.d.ts +35 -7
  75. package/build/types/index.d.ts +4 -3
  76. package/build/types/job.d.ts +93 -6
  77. package/build/types/pipe.d.ts +81 -3
  78. package/build/types/stream.d.ts +61 -1
  79. package/build/types/stream.js +4 -0
  80. package/index.ts +1 -2
  81. package/modules/enums.ts +16 -8
  82. package/modules/errors.ts +139 -34
  83. package/package.json +7 -2
  84. package/services/activities/activity.ts +63 -14
  85. package/services/activities/await.ts +6 -6
  86. package/services/activities/cycle.ts +7 -6
  87. package/services/activities/hook.ts +12 -5
  88. package/services/activities/interrupt.ts +19 -9
  89. package/services/activities/signal.ts +6 -5
  90. package/services/activities/trigger.ts +43 -6
  91. package/services/activities/worker.ts +7 -7
  92. package/services/compiler/deployer.ts +33 -6
  93. package/services/compiler/validator.ts +7 -3
  94. package/services/durable/client.ts +49 -22
  95. package/services/durable/exporter.ts +162 -349
  96. package/services/durable/handle.ts +66 -53
  97. package/services/durable/index.ts +0 -2
  98. package/services/durable/schemas/factory.ts +2358 -0
  99. package/services/durable/search.ts +8 -8
  100. package/services/durable/worker.ts +128 -29
  101. package/services/durable/workflow.ts +371 -322
  102. package/services/engine/index.ts +8 -3
  103. package/services/exporter/index.ts +10 -12
  104. package/services/hotmesh/index.ts +4 -3
  105. package/services/mapper/index.ts +6 -2
  106. package/services/pipe/functions/array.ts +24 -37
  107. package/services/pipe/functions/conditional.ts +4 -0
  108. package/services/pipe/functions/date.ts +6 -0
  109. package/services/pipe/functions/index.ts +7 -5
  110. package/services/pipe/functions/logical.ts +11 -0
  111. package/services/pipe/functions/object.ts +26 -7
  112. package/services/pipe/index.ts +99 -21
  113. package/services/quorum/index.ts +1 -3
  114. package/services/router/index.ts +14 -3
  115. package/services/serializer/index.ts +12 -5
  116. package/services/store/clients/ioredis.ts +6 -6
  117. package/services/store/clients/redis.ts +7 -7
  118. package/services/store/index.ts +4 -1
  119. package/services/stream/clients/ioredis.ts +8 -8
  120. package/services/stream/clients/redis.ts +1 -1
  121. package/types/activity.ts +87 -15
  122. package/types/durable.ts +263 -75
  123. package/types/error.ts +52 -0
  124. package/types/exporter.ts +43 -9
  125. package/types/index.ts +14 -8
  126. package/types/job.ts +157 -36
  127. package/types/pipe.ts +84 -3
  128. package/types/stream.ts +82 -23
  129. package/build/services/durable/factory.d.ts +0 -17
  130. package/build/services/durable/factory.js +0 -817
  131. package/build/services/durable/meshos.d.ts +0 -127
  132. package/build/services/durable/meshos.js +0 -380
  133. package/services/durable/factory.ts +0 -818
  134. package/services/durable/meshos.ts +0 -441
@@ -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
+ };
5
+ var _a;
2
6
  Object.defineProperty(exports, "__esModule", { value: true });
3
7
  exports.ClientService = void 0;
4
- const factory_1 = require("./factory");
8
+ const ms_1 = __importDefault(require("ms"));
9
+ const factory_1 = require("./schemas/factory");
10
+ const enums_1 = require("../../modules/enums");
11
+ const utils_1 = require("../../modules/utils");
5
12
  const handle_1 = require("./handle");
6
13
  const hotmesh_1 = require("../hotmesh");
7
14
  const key_1 = require("../../modules/key");
8
15
  const search_1 = require("./search");
9
16
  const types_1 = require("../../types");
10
- const enums_1 = require("../../modules/enums");
11
- const utils_1 = require("../../modules/utils");
12
17
  class ClientService {
13
18
  constructor(config) {
14
19
  this.getHotMeshClient = async (workflowTopic, namespace) => {
@@ -18,7 +23,7 @@ class ClientService {
18
23
  await this.verifyWorkflowActive(hotMeshClient, targetNS);
19
24
  if (!ClientService.topics.includes(workflowTopic)) {
20
25
  ClientService.topics.push(workflowTopic);
21
- await this.createStream(hotMeshClient, workflowTopic, namespace);
26
+ await ClientService.createStream(hotMeshClient, workflowTopic, namespace);
22
27
  }
23
28
  return hotMeshClient;
24
29
  }
@@ -34,27 +39,10 @@ class ClientService {
34
39
  }
35
40
  });
36
41
  ClientService.instances.set(targetNS, hotMeshClient);
37
- await this.createStream(await hotMeshClient, workflowTopic, namespace);
42
+ await ClientService.createStream(await hotMeshClient, workflowTopic, namespace);
38
43
  await this.activateWorkflow(await hotMeshClient, targetNS);
39
44
  return hotMeshClient;
40
45
  };
41
- /**
42
- * Creates a stream (Redis `XGROUP.CREATE`) where events can be published (XADD).
43
- * It is possible that the worker that will read from this stream channel
44
- * has not yet been initialized, so this call ensures that the channel
45
- * exists and is ready to serve as a container for events.
46
- */
47
- this.createStream = async (hotMeshClient, workflowTopic, namespace) => {
48
- const store = hotMeshClient.engine.store;
49
- const params = { appId: namespace ?? factory_1.APP_ID, topic: workflowTopic };
50
- const streamKey = store.mintKey(key_1.KeyType.STREAMS, params);
51
- try {
52
- await store.xgroup('CREATE', streamKey, 'WORKER', '$', 'MKSTREAM');
53
- }
54
- catch (err) {
55
- //ignore if already exists
56
- }
57
- };
58
46
  /**
59
47
  * For those deployments with a redis stack backend (with the FT module),
60
48
  * this method will configure the search index for the workflow.
@@ -80,8 +68,8 @@ class ClientService {
80
68
  const prefixes = search.prefix.map((prefix) => `${hotMeshPrefix}${prefix}`);
81
69
  await store.exec('FT.CREATE', `${search.index}`, 'ON', 'HASH', 'PREFIX', prefixes.length, ...prefixes, 'SCHEMA', ...schema);
82
70
  }
83
- catch (err) {
84
- hotMeshClient.engine.logger.info('durable-client-search-err', { err });
71
+ catch (error) {
72
+ hotMeshClient.engine.logger.info('durable-client-search-err', { ...error });
85
73
  }
86
74
  }
87
75
  };
@@ -110,17 +98,12 @@ class ClientService {
110
98
  parentWorkflowId: options.parentWorkflowId,
111
99
  workflowId: options.workflowId || hotmesh_1.HotMeshService.guid(),
112
100
  workflowTopic: workflowTopic,
113
- backoffCoefficient: options.config?.backoffCoefficient || factory_1.DEFAULT_COEFFICIENT,
101
+ backoffCoefficient: options.config?.backoffCoefficient || enums_1.HMSH_DURABLE_EXP_BACKOFF,
102
+ maximumAttempts: options.config?.maximumAttempts || enums_1.HMSH_DURABLE_MAX_ATTEMPTS,
103
+ maximumInterval: (0, ms_1.default)(options.config?.maximumInterval || enums_1.HMSH_DURABLE_MAX_INTERVAL) / 1000,
114
104
  };
115
105
  const context = { metadata: { trc, spn }, data: {} };
116
- const jobId = await hotMeshClient.pub(`${options.namespace ?? factory_1.APP_ID}.execute`, payload, context);
117
- // Seed search data
118
- if (jobId && options.search?.data) {
119
- const searchSessionId = `-search-0`;
120
- const search = new search_1.Search(jobId, hotMeshClient, searchSessionId);
121
- const entries = Object.entries(options.search.data).flat();
122
- await search.set(...entries);
123
- }
106
+ const jobId = await hotMeshClient.pub(`${options.namespace ?? factory_1.APP_ID}.execute`, payload, context, { search: options?.search?.data, marker: options?.marker });
124
107
  return new handle_1.WorkflowHandleService(hotMeshClient, workflowTopic, jobId);
125
108
  },
126
109
  /**
@@ -142,7 +125,9 @@ class ClientService {
142
125
  arguments: [...options.args],
143
126
  id: options.workflowId,
144
127
  workflowTopic,
145
- backoffCoefficient: options.config?.backoffCoefficient || factory_1.DEFAULT_COEFFICIENT,
128
+ backoffCoefficient: options.config?.backoffCoefficient || enums_1.HMSH_DURABLE_EXP_BACKOFF,
129
+ maximumAttempts: options.config?.maximumAttempts || enums_1.HMSH_DURABLE_MAX_ATTEMPTS,
130
+ maximumInterval: (0, ms_1.default)(options.config?.maximumInterval || enums_1.HMSH_DURABLE_MAX_INTERVAL) / 1000,
146
131
  };
147
132
  //seed search data if presentthe hook before entering
148
133
  const hotMeshClient = await this.getHotMeshClient(workflowTopic, options.namespace);
@@ -166,9 +151,9 @@ class ClientService {
166
151
  try {
167
152
  return await this.search(hotMeshClient, index, query);
168
153
  }
169
- catch (err) {
170
- hotMeshClient.engine.logger.error('durable-client-search-err', { err });
171
- throw err;
154
+ catch (error) {
155
+ hotMeshClient.engine.logger.error('durable-client-search-err', { ...error });
156
+ throw error;
172
157
  }
173
158
  }
174
159
  };
@@ -195,7 +180,7 @@ class ClientService {
195
180
  await hotMesh.activate(version);
196
181
  }
197
182
  catch (error) {
198
- hotMesh.engine.logger.error('durable-client-deploy-activate-err', { error });
183
+ hotMesh.engine.logger.error('durable-client-deploy-activate-err', { ...error });
199
184
  throw error;
200
185
  }
201
186
  }
@@ -215,6 +200,40 @@ class ClientService {
215
200
  }
216
201
  }
217
202
  }
203
+ _a = ClientService;
218
204
  ClientService.topics = [];
219
205
  ClientService.instances = new Map();
206
+ /**
207
+ * Creates a stream (Redis `XGROUP.CREATE`) where events can be published (XADD).
208
+ * It is possible that the worker that will read from this stream channel
209
+ * has not yet been initialized, so this call ensures that the channel
210
+ * exists and is ready to serve as a container for events.
211
+ */
212
+ ClientService.createStream = async (hotMeshClient, workflowTopic, namespace) => {
213
+ const store = hotMeshClient.engine.store;
214
+ const params = { appId: namespace ?? factory_1.APP_ID, topic: workflowTopic };
215
+ const streamKey = store.mintKey(key_1.KeyType.STREAMS, params);
216
+ try {
217
+ await store.xgroup('CREATE', streamKey, 'WORKER', '$', 'MKSTREAM');
218
+ }
219
+ catch (err) {
220
+ //ignore if already exists
221
+ }
222
+ };
223
+ /**
224
+ * It is possible for a client to invoke a workflow without first
225
+ * creating the stream. This method will verify that the stream
226
+ * exists and if not, create it.
227
+ */
228
+ ClientService.verifyStream = async (workflowTopic, namespace) => {
229
+ const targetNS = namespace ?? factory_1.APP_ID;
230
+ if (ClientService.instances.has(targetNS)) {
231
+ const hotMeshClient = await ClientService.instances.get(targetNS);
232
+ if (!ClientService.topics.includes(workflowTopic)) {
233
+ ClientService.topics.push(workflowTopic);
234
+ await ClientService.createStream(hotMeshClient, workflowTopic, namespace);
235
+ }
236
+ return hotMeshClient;
237
+ }
238
+ };
220
239
  exports.ClientService = ClientService;
@@ -1,105 +1,51 @@
1
1
  import { ILogger } from '../logger';
2
2
  import { StoreService } from '../store';
3
- import { StringStringType, Symbols } from "../../types";
3
+ import { ExportOptions, DurableJobExport, TimelineType, TransitionType, ExportFields } from '../../types/exporter';
4
4
  import { RedisClient, RedisMulti } from '../../types/redis';
5
- import { ActivityAction, DependencyExport, ExportItem, ExportOptions, JobAction, JobActionExport, DurableJobExport, JobTimeline } from '../../types/exporter';
6
- import { SerializerService } from '../serializer';
7
- /**
8
- * Downloads job data from Redis (hscan, hmget, hgetall)
9
- * Splits, Inflates, and Sorts the job data for use in durable contexts
10
- */
5
+ import { StringStringType, Symbols } from "../../types/serializer";
11
6
  declare class ExporterService {
12
7
  appId: string;
13
8
  logger: ILogger;
14
- serializer: SerializerService;
15
9
  store: StoreService<RedisClient, RedisMulti>;
16
10
  symbols: Promise<Symbols> | Symbols;
17
- /**
18
- * Friendly names for the activity ids
19
- */
20
- activitySymbols: Symbols;
21
- transitions: {
22
- trigger: string[];
23
- pivot: string[];
24
- worker: string[];
25
- sleeper: string[];
26
- awaiter: string[];
27
- retryer: string[];
28
- hook: string[];
29
- hook_pivot: string[];
30
- hook_worker: string[];
31
- hook_sleeper: string[];
32
- hook_awaiter: string[];
33
- hook_retryer: string[];
34
- };
35
- cycles: {
36
- sleep_cycler: string[];
37
- await_cycler: string[];
38
- retry_cycler: string[];
39
- hook_sleep_cycler: string[];
40
- hook_await_cycler: string[];
41
- hook_retry_cycler: string[];
42
- };
11
+ private static symbols;
43
12
  constructor(appId: string, store: StoreService<RedisClient, RedisMulti>, logger: ILogger);
44
13
  /**
45
- * Convert the job hash and dependency list into a DurableJobExport object.
46
- * This object contains various facets that describe the interaction
47
- * in terms relevant to narrative storytelling.
14
+ * Convert the job hash from its compiles format into a DurableJobExport object with
15
+ * facets that describe the workflow in terms relevant to narrative storytelling.
48
16
  */
49
17
  export(jobId: string, options?: ExportOptions): Promise<DurableJobExport>;
50
18
  /**
51
- * Interleave actions into the replay timeline to create
52
- * a time-ordered timeline of the entire interaction, beginning
53
- * with the entry trigger and concluding with the scrubber
54
- * activity. Using the returned timeline, it is possible to
55
- * create an animated narrative of the job, highlighting
56
- * activities in the graph according to the timeline's
57
- * activity-created (/ac) and activity-updated (/au) entries.
58
- */
59
- createTimeline(replay: ExportItem[], actions: JobActionExport): JobTimeline[];
60
- /**
61
- * Interleave actions into the 'worker' and 'hook_worker'
62
- * activities (between their /ac and /au entries)
19
+ * Inflates the job data from Redis into a DurableJobExport object
20
+ * @param jobHash - the job data from Redis
21
+ * @param dependencyList - the list of dependencies for the job
22
+ * @returns - the inflated job data
63
23
  */
64
- interleaveActions(target: JobAction, actions: ActivityAction[]): void;
65
- isPausingAction(actionType: string): boolean;
66
- isMainEntry(key: string): boolean;
67
- isHookEntry(key: string): boolean;
24
+ inflate(jobHash: StringStringType, options: ExportOptions): DurableJobExport;
25
+ resolveValue(raw: string, withValues: boolean): Record<string, any> | string | number | null;
68
26
  /**
69
27
  * Inflates the key from Redis, 3-character symbol
70
28
  * into a human-readable JSON path, reflecting the
71
29
  * tree-like structure of the unidimensional Hash
30
+ * @private
72
31
  */
73
32
  inflateKey(key: string): string;
33
+ filterFields(fullObject: DurableJobExport, block?: ExportFields[], allow?: ExportFields[]): Partial<DurableJobExport>;
34
+ inflateTransition(match: RegExpMatchArray, value: string, transitionsObject: Record<string, TransitionType>): void;
35
+ sortEntriesByCreated(obj: {
36
+ [key: string]: TransitionType;
37
+ }): TransitionType[];
38
+ /**
39
+ * marker names are overloaded with details like sequence, type, etc
40
+ */
41
+ keyToObject(key: string): {
42
+ index: number;
43
+ dimension?: string;
44
+ secondary?: number;
45
+ };
74
46
  /**
75
- * Inflates the dependency data from Redis into a DurableJobExport object by
76
- * organizing the dimensional isolate in sch a way asto interleave
77
- * into a story
78
- * @param data - the dependency data from Redis
79
- * @returns - the organized dependency data
80
- */
81
- inflateDependencyData(data: string[], actions: JobActionExport): DependencyExport[];
82
- /**
83
- * Adds historical actions (proxyActivity, executeChild)
84
- * using the `dependency list` to determine
85
- * after-the-fact what happened within the 'black-box'
86
- * worker function. This is necessary to interleave the
87
- * actions into the replay timeline, given that it isn't
88
- * really possible to know the inner-workings of the user's
89
- * function
90
- *
91
- */
92
- seedActions(type: 'flow' | 'hook' | 'other', action: string, topic: string, dep: string, prefix: string, dimensionKey: string, actions: JobActionExport, jobId: string): void;
93
- /**
94
- * Inflates the job data from Redis into a DurableJobExport object
95
- * @param jobHash - the job data from Redis
96
- * @param dependencyList - the list of dependencies for the job
97
- * @returns - the inflated job data
47
+ * idem list has a complicated sort order based on indexes and dimensions
98
48
  */
99
- inflate(jobHash: StringStringType, dependencyList: string[]): DurableJobExport;
100
- inflateProcess(match: RegExpMatchArray, value: string, replay: ExportItem[]): void;
101
- inflateActions(key: string, value: string, actions: JobActionExport): void;
102
- reverseSort(aKey: ExportItem, bKey: ExportItem): 1 | -1 | 0;
103
- dateSort(aKey: ExportItem, bKey: ExportItem): 1 | -1 | 0;
49
+ sortParts(parts: TimelineType[]): TimelineType[];
104
50
  }
105
51
  export { ExporterService };