@hotmeshio/hotmesh 0.0.55 → 0.0.56

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 (181) hide show
  1. package/build/modules/enums.js +1 -10
  2. package/build/modules/key.d.ts +0 -38
  3. package/build/modules/key.js +4 -46
  4. package/build/modules/utils.d.ts +0 -8
  5. package/build/modules/utils.js +0 -14
  6. package/build/package.json +11 -4
  7. package/build/services/activities/activity.d.ts +0 -28
  8. package/build/services/activities/activity.js +1 -46
  9. package/build/services/activities/await.js +0 -4
  10. package/build/services/activities/cycle.d.ts +0 -7
  11. package/build/services/activities/cycle.js +1 -16
  12. package/build/services/activities/hook.d.ts +0 -6
  13. package/build/services/activities/hook.js +2 -12
  14. package/build/services/activities/interrupt.js +0 -8
  15. package/build/services/activities/signal.d.ts +0 -6
  16. package/build/services/activities/signal.js +0 -15
  17. package/build/services/activities/trigger.d.ts +0 -4
  18. package/build/services/activities/trigger.js +1 -7
  19. package/build/services/activities/worker.js +0 -4
  20. package/build/services/collator/index.d.ts +0 -70
  21. package/build/services/collator/index.js +1 -91
  22. package/build/services/compiler/deployer.js +6 -38
  23. package/build/services/compiler/index.d.ts +0 -15
  24. package/build/services/compiler/index.js +0 -20
  25. package/build/services/compiler/validator.d.ts +0 -3
  26. package/build/services/compiler/validator.js +0 -25
  27. package/build/services/connector/clients/ioredis.d.ts +2 -2
  28. package/build/services/connector/clients/ioredis.js +0 -2
  29. package/build/services/connector/clients/redis.d.ts +4 -4
  30. package/build/services/connector/clients/redis.js +1 -3
  31. package/build/services/connector/index.d.ts +1 -1
  32. package/build/services/connector/index.js +0 -2
  33. package/build/services/durable/client.d.ts +1 -26
  34. package/build/services/durable/client.js +0 -56
  35. package/build/services/durable/exporter.d.ts +0 -22
  36. package/build/services/durable/exporter.js +1 -30
  37. package/build/services/durable/handle.d.ts +0 -36
  38. package/build/services/durable/handle.js +0 -46
  39. package/build/services/durable/index.d.ts +0 -4
  40. package/build/services/durable/index.js +0 -4
  41. package/build/services/durable/schemas/factory.d.ts +0 -29
  42. package/build/services/durable/schemas/factory.js +0 -29
  43. package/build/services/durable/search.d.ts +1 -36
  44. package/build/services/durable/search.js +57 -56
  45. package/build/services/durable/worker.js +2 -22
  46. package/build/services/durable/workflow.d.ts +0 -114
  47. package/build/services/durable/workflow.js +1 -141
  48. package/build/services/engine/index.d.ts +1 -6
  49. package/build/services/engine/index.js +1 -43
  50. package/build/services/exporter/index.d.ts +0 -27
  51. package/build/services/exporter/index.js +0 -33
  52. package/build/services/hotmesh/index.d.ts +2 -2
  53. package/build/services/hotmesh/index.js +1 -9
  54. package/build/services/logger/index.js +0 -2
  55. package/build/services/mapper/index.d.ts +0 -14
  56. package/build/services/mapper/index.js +0 -14
  57. package/build/services/pipe/functions/date.d.ts +0 -7
  58. package/build/services/pipe/functions/date.js +0 -7
  59. package/build/services/pipe/functions/math.js +0 -2
  60. package/build/services/pipe/index.d.ts +0 -15
  61. package/build/services/pipe/index.js +2 -23
  62. package/build/services/quorum/index.d.ts +0 -7
  63. package/build/services/quorum/index.js +0 -21
  64. package/build/services/reporter/index.d.ts +0 -5
  65. package/build/services/reporter/index.js +0 -9
  66. package/build/services/router/index.d.ts +0 -9
  67. package/build/services/router/index.js +2 -38
  68. package/build/services/serializer/index.js +7 -26
  69. package/build/services/store/cache.d.ts +0 -18
  70. package/build/services/store/cache.js +0 -18
  71. package/build/services/store/clients/ioredis.d.ts +1 -1
  72. package/build/services/store/clients/ioredis.js +0 -1
  73. package/build/services/store/clients/redis.d.ts +1 -1
  74. package/build/services/store/index.d.ts +0 -55
  75. package/build/services/store/index.js +5 -81
  76. package/build/services/stream/clients/ioredis.d.ts +1 -1
  77. package/build/services/stream/clients/ioredis.js +1 -4
  78. package/build/services/stream/clients/redis.d.ts +1 -1
  79. package/build/services/sub/clients/ioredis.d.ts +1 -1
  80. package/build/services/sub/clients/redis.d.ts +1 -1
  81. package/build/services/task/index.d.ts +0 -9
  82. package/build/services/task/index.js +0 -31
  83. package/build/services/telemetry/index.d.ts +0 -7
  84. package/build/services/telemetry/index.js +1 -13
  85. package/build/services/worker/index.d.ts +0 -4
  86. package/build/services/worker/index.js +2 -6
  87. package/build/types/activity.d.ts +0 -81
  88. package/build/types/durable.d.ts +25 -177
  89. package/build/types/exporter.d.ts +0 -13
  90. package/build/types/hotmesh.d.ts +4 -16
  91. package/build/types/hotmesh.js +0 -3
  92. package/build/types/index.d.ts +4 -6
  93. package/build/types/index.js +4 -3
  94. package/build/types/job.d.ts +1 -86
  95. package/build/types/pipe.d.ts +0 -65
  96. package/build/types/quorum.d.ts +15 -10
  97. package/build/types/redis.d.ts +225 -7
  98. package/build/types/redis.js +9 -0
  99. package/build/types/stream.d.ts +0 -58
  100. package/build/types/stream.js +0 -4
  101. package/package.json +11 -4
  102. package/types/durable.ts +121 -3
  103. package/types/hotmesh.ts +3 -6
  104. package/types/index.ts +23 -10
  105. package/types/job.ts +1 -1
  106. package/types/quorum.ts +22 -0
  107. package/types/redis.ts +267 -18
  108. package/build/types/ioredisclient.d.ts +0 -5
  109. package/build/types/ioredisclient.js +0 -5
  110. package/build/types/redisclient.d.ts +0 -26
  111. package/build/types/redisclient.js +0 -2
  112. package/modules/enums.ts +0 -62
  113. package/modules/errors.ts +0 -280
  114. package/modules/key.ts +0 -101
  115. package/modules/storage.ts +0 -3
  116. package/modules/utils.ts +0 -242
  117. package/services/activities/activity.ts +0 -589
  118. package/services/activities/await.ts +0 -113
  119. package/services/activities/cycle.ts +0 -115
  120. package/services/activities/hook.ts +0 -197
  121. package/services/activities/index.ts +0 -19
  122. package/services/activities/interrupt.ts +0 -172
  123. package/services/activities/signal.ts +0 -148
  124. package/services/activities/trigger.ts +0 -295
  125. package/services/activities/worker.ts +0 -107
  126. package/services/collator/README.md +0 -102
  127. package/services/collator/index.ts +0 -291
  128. package/services/compiler/deployer.ts +0 -504
  129. package/services/compiler/index.ts +0 -98
  130. package/services/compiler/validator.ts +0 -158
  131. package/services/connector/clients/ioredis.ts +0 -57
  132. package/services/connector/clients/redis.ts +0 -72
  133. package/services/connector/index.ts +0 -42
  134. package/services/durable/client.ts +0 -266
  135. package/services/durable/connection.ts +0 -10
  136. package/services/durable/exporter.ts +0 -232
  137. package/services/durable/handle.ts +0 -160
  138. package/services/durable/index.ts +0 -27
  139. package/services/durable/schemas/factory.ts +0 -2358
  140. package/services/durable/search.ts +0 -196
  141. package/services/durable/worker.ts +0 -401
  142. package/services/durable/workflow.ts +0 -557
  143. package/services/engine/index.ts +0 -761
  144. package/services/exporter/index.ts +0 -146
  145. package/services/hotmesh/index.ts +0 -237
  146. package/services/logger/index.ts +0 -79
  147. package/services/mapper/index.ts +0 -89
  148. package/services/pipe/functions/array.ts +0 -78
  149. package/services/pipe/functions/bitwise.ts +0 -27
  150. package/services/pipe/functions/conditional.ts +0 -35
  151. package/services/pipe/functions/date.ts +0 -220
  152. package/services/pipe/functions/index.ts +0 -27
  153. package/services/pipe/functions/json.ts +0 -11
  154. package/services/pipe/functions/logical.ts +0 -11
  155. package/services/pipe/functions/math.ts +0 -217
  156. package/services/pipe/functions/number.ts +0 -75
  157. package/services/pipe/functions/object.ts +0 -98
  158. package/services/pipe/functions/string.ts +0 -86
  159. package/services/pipe/functions/symbol.ts +0 -39
  160. package/services/pipe/functions/unary.ts +0 -19
  161. package/services/pipe/index.ts +0 -216
  162. package/services/quorum/index.ts +0 -319
  163. package/services/reporter/index.ts +0 -387
  164. package/services/router/index.ts +0 -426
  165. package/services/serializer/README.md +0 -10
  166. package/services/serializer/index.ts +0 -285
  167. package/services/store/cache.ts +0 -172
  168. package/services/store/clients/ioredis.ts +0 -145
  169. package/services/store/clients/redis.ts +0 -191
  170. package/services/store/index.ts +0 -1091
  171. package/services/stream/clients/ioredis.ts +0 -157
  172. package/services/stream/clients/redis.ts +0 -158
  173. package/services/stream/index.ts +0 -58
  174. package/services/sub/clients/ioredis.ts +0 -83
  175. package/services/sub/clients/redis.ts +0 -74
  176. package/services/sub/index.ts +0 -25
  177. package/services/task/index.ts +0 -250
  178. package/services/telemetry/index.ts +0 -273
  179. package/services/worker/index.ts +0 -248
  180. package/types/ioredisclient.ts +0 -10
  181. package/types/redisclient.ts +0 -30
@@ -10,42 +10,20 @@ declare class ExporterService {
10
10
  symbols: Promise<Symbols> | Symbols;
11
11
  private static symbols;
12
12
  constructor(appId: string, store: StoreService<RedisClient, RedisMulti>, logger: ILogger);
13
- /**
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.
16
- */
17
13
  export(jobId: string, options?: ExportOptions): Promise<DurableJobExport>;
18
- /**
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
23
- */
24
14
  inflate(jobHash: StringStringType, options: ExportOptions): DurableJobExport;
25
15
  resolveValue(raw: string, withValues: boolean): Record<string, any> | string | number | null;
26
- /**
27
- * Inflates the key from Redis, 3-character symbol
28
- * into a human-readable JSON path, reflecting the
29
- * tree-like structure of the unidimensional Hash
30
- * @private
31
- */
32
16
  inflateKey(key: string): string;
33
17
  filterFields(fullObject: DurableJobExport, block?: ExportFields[], allow?: ExportFields[]): Partial<DurableJobExport>;
34
18
  inflateTransition(match: RegExpMatchArray, value: string, transitionsObject: Record<string, TransitionType>): void;
35
19
  sortEntriesByCreated(obj: {
36
20
  [key: string]: TransitionType;
37
21
  }): TransitionType[];
38
- /**
39
- * marker names are overloaded with details like sequence, type, etc
40
- */
41
22
  keyToObject(key: string): {
42
23
  index: number;
43
24
  dimension?: string;
44
25
  secondary?: number;
45
26
  };
46
- /**
47
- * idem list has a complicated sort order based on indexes and dimensions
48
- */
49
27
  sortParts(parts: TimelineType[]): TimelineType[];
50
28
  }
51
29
  export { ExporterService };
@@ -9,10 +9,6 @@ class ExporterService {
9
9
  this.logger = logger;
10
10
  this.store = store;
11
11
  }
12
- /**
13
- * Convert the job hash from its compiles format into a DurableJobExport object with
14
- * facets that describe the workflow in terms relevant to narrative storytelling.
15
- */
16
12
  async export(jobId, options = {}) {
17
13
  if (!ExporterService.symbols.has(this.appId)) {
18
14
  const symbols = this.store.getAllSymbols();
@@ -22,12 +18,6 @@ class ExporterService {
22
18
  const jobExport = this.inflate(jobData, options);
23
19
  return jobExport;
24
20
  }
25
- /**
26
- * Inflates the job data from Redis into a DurableJobExport object
27
- * @param jobHash - the job data from Redis
28
- * @param dependencyList - the list of dependencies for the job
29
- * @returns - the inflated job data
30
- */
31
21
  inflate(jobHash, options) {
32
22
  const timeline = [];
33
23
  const state = {};
@@ -37,20 +27,16 @@ class ExporterService {
37
27
  Object.entries(jobHash).forEach(([key, value]) => {
38
28
  const match = key.match(regex);
39
29
  if (match) {
40
- //transitions
41
30
  this.inflateTransition(match, value, transitionsObject);
42
31
  }
43
32
  else if (key.length === 3) {
44
- //state
45
33
  state[this.inflateKey(key)] = serializer_1.SerializerService.fromString(value);
46
34
  }
47
35
  else if (key.startsWith('_')) {
48
- //data
49
36
  data[key.substring(1)] = value;
50
37
  }
51
38
  else if (key.startsWith('-')) {
52
- //timeline
53
- const keyParts = this.keyToObject(key); //key parts have meaning
39
+ const keyParts = this.keyToObject(key);
54
40
  timeline.push({
55
41
  ...keyParts,
56
42
  key,
@@ -81,12 +67,6 @@ class ExporterService {
81
67
  }
82
68
  return resolved;
83
69
  }
84
- /**
85
- * Inflates the key from Redis, 3-character symbol
86
- * into a human-readable JSON path, reflecting the
87
- * tree-like structure of the unidimensional Hash
88
- * @private
89
- */
90
70
  inflateKey(key) {
91
71
  const symbols = ExporterService.symbols.get(this.appId);
92
72
  if (key in symbols) {
@@ -124,7 +104,6 @@ class ExporterService {
124
104
  const activity = parts[0];
125
105
  const isCreate = path.endsWith('/output/metadata/ac');
126
106
  const isUpdate = path.endsWith('/output/metadata/au');
127
- //for now only export activity start/stop; activity data would also be interesting
128
107
  if (isCreate || isUpdate) {
129
108
  const targetName = `${activity},${dimensions}`;
130
109
  let target = transitionsObject[targetName];
@@ -148,9 +127,6 @@ class ExporterService {
148
127
  });
149
128
  return entriesArray;
150
129
  }
151
- /**
152
- * marker names are overloaded with details like sequence, type, etc
153
- */
154
130
  keyToObject(key) {
155
131
  function extractDimension(label) {
156
132
  const parts = label.split(',');
@@ -161,14 +137,12 @@ class ExporterService {
161
137
  }
162
138
  const parts = key.split('-');
163
139
  if (parts.length === 4) {
164
- //-proxy-5- -search-1-1-
165
140
  return {
166
141
  index: parseInt(parts[2], 10),
167
142
  dimension: extractDimension(parts[1]),
168
143
  };
169
144
  }
170
145
  else {
171
- //-search,0,0-1-1- -proxy,0,0-1-
172
146
  return {
173
147
  index: parseInt(parts[2], 10),
174
148
  secondary: parseInt(parts[3], 10),
@@ -176,9 +150,6 @@ class ExporterService {
176
150
  };
177
151
  }
178
152
  }
179
- /**
180
- * idem list has a complicated sort order based on indexes and dimensions
181
- */
182
153
  sortParts(parts) {
183
154
  return parts.sort((a, b) => {
184
155
  const { dimension: aDim, index: aIdx, secondary: aSec } = a;
@@ -10,47 +10,11 @@ export declare class WorkflowHandleService {
10
10
  workflowId: string;
11
11
  constructor(hotMesh: HotMesh, workflowTopic: string, workflowId: string);
12
12
  export(options?: ExportOptions): Promise<DurableJobExport>;
13
- /**
14
- * Sends a signal to the workflow. This is a way to send
15
- * a message to a workflow that is paused due to having
16
- * executed `Durable.workflow.waitFor`. The workflow
17
- * will awaken if no other signals are pending.
18
- */
19
13
  signal(signalId: string, data: Record<any, any>): Promise<void>;
20
- /**
21
- * Returns the job state of the workflow. If the workflow has completed
22
- * this is also the job output. If the workflow is still running, this
23
- * is the current state of the job, but it may change depending upon
24
- * the activities that remain.
25
- */
26
14
  state(metadata?: boolean): Promise<Record<string, any>>;
27
- /**
28
- * Returns the current search state of the workflow. This is
29
- * different than the job state or individual activity state.
30
- * Search state represents name/value pairs that were added
31
- * to the workflow. As the workflow is stored in a Redis hash,
32
- * this is a way to store additional data that is indexed
33
- * and searchable using the RediSearch module.
34
- */
35
15
  queryState(fields: string[]): Promise<Record<string, any>>;
36
- /**
37
- * Returns the current status of the workflow. This is a semaphore
38
- * value that represents the current state of the workflow, where
39
- * 0 is complete and a negative value represents that the flow was
40
- * interrupted.
41
- */
42
16
  status(): Promise<number>;
43
- /**
44
- * Interrupts a running workflow. Standard Job Completion tasks will
45
- * run. Subscribers will be notified and the job hash will be expired.
46
- */
47
17
  interrupt(options?: JobInterruptOptions): Promise<string>;
48
- /**
49
- * Waits for the workflow to complete and returns the result. If
50
- * the workflow response includes an error, this method will rethrow
51
- * the error, including the stack trace if available.
52
- * Wrap calls in a try/catch as necessary to avoid unhandled exceptions.
53
- */
54
18
  result<T>(config?: {
55
19
  state?: boolean;
56
20
  throwOnError?: boolean;
@@ -12,21 +12,9 @@ class WorkflowHandleService {
12
12
  async export(options) {
13
13
  return this.exporter.export(this.workflowId, options);
14
14
  }
15
- /**
16
- * Sends a signal to the workflow. This is a way to send
17
- * a message to a workflow that is paused due to having
18
- * executed `Durable.workflow.waitFor`. The workflow
19
- * will awaken if no other signals are pending.
20
- */
21
15
  async signal(signalId, data) {
22
16
  await this.hotMesh.hook(`${this.hotMesh.appId}.wfs.signal`, { id: signalId, data });
23
17
  }
24
- /**
25
- * Returns the job state of the workflow. If the workflow has completed
26
- * this is also the job output. If the workflow is still running, this
27
- * is the current state of the job, but it may change depending upon
28
- * the activities that remain.
29
- */
30
18
  async state(metadata = false) {
31
19
  const state = await this.hotMesh.getState(`${this.hotMesh.appId}.execute`, this.workflowId);
32
20
  if (!state.data && state.metadata.err) {
@@ -34,56 +22,25 @@ class WorkflowHandleService {
34
22
  }
35
23
  return metadata ? state : state.data;
36
24
  }
37
- /**
38
- * Returns the current search state of the workflow. This is
39
- * different than the job state or individual activity state.
40
- * Search state represents name/value pairs that were added
41
- * to the workflow. As the workflow is stored in a Redis hash,
42
- * this is a way to store additional data that is indexed
43
- * and searchable using the RediSearch module.
44
- */
45
25
  async queryState(fields) {
46
26
  return await this.hotMesh.getQueryState(this.workflowId, fields);
47
27
  }
48
- /**
49
- * Returns the current status of the workflow. This is a semaphore
50
- * value that represents the current state of the workflow, where
51
- * 0 is complete and a negative value represents that the flow was
52
- * interrupted.
53
- */
54
28
  async status() {
55
29
  return await this.hotMesh.getStatus(this.workflowId);
56
30
  }
57
- /**
58
- * Interrupts a running workflow. Standard Job Completion tasks will
59
- * run. Subscribers will be notified and the job hash will be expired.
60
- */
61
31
  async interrupt(options) {
62
32
  return await this.hotMesh.interrupt(`${this.hotMesh.appId}.execute`, this.workflowId, options);
63
33
  }
64
- /**
65
- * Waits for the workflow to complete and returns the result. If
66
- * the workflow response includes an error, this method will rethrow
67
- * the error, including the stack trace if available.
68
- * Wrap calls in a try/catch as necessary to avoid unhandled exceptions.
69
- */
70
34
  async result(config) {
71
35
  const topic = `${this.hotMesh.appId}.executed.${this.workflowId}`;
72
36
  let isResolved = false;
73
37
  return new Promise(async (resolve, reject) => {
74
- /**
75
- * rejects/resolves the promise based on the `throwOnError`
76
- * default behavior is to throw if error
77
- */
78
38
  const safeReject = (err) => {
79
39
  if (config?.throwOnError === false) {
80
40
  return resolve(err);
81
41
  }
82
42
  reject(err);
83
43
  };
84
- /**
85
- * Common completion function that unsubscribes from the topic/returns
86
- */
87
44
  const complete = async (response, err) => {
88
45
  if (isResolved)
89
46
  return;
@@ -106,7 +63,6 @@ class WorkflowHandleService {
106
63
  }
107
64
  resolve(response);
108
65
  };
109
- //more expensive; fetches the entire job, not just the `status`
110
66
  if (config?.state) {
111
67
  const state = await this.hotMesh.getState(`${this.hotMesh.appId}.execute`, this.workflowId);
112
68
  if (state?.data?.done && !state.data?.$error) {
@@ -119,7 +75,6 @@ class WorkflowHandleService {
119
75
  return complete(null, JSON.parse(state.metadata.err));
120
76
  }
121
77
  }
122
- //subscribe to 'done' topic
123
78
  this.hotMesh.sub(topic, async (_topic, state) => {
124
79
  this.hotMesh.unsub(topic);
125
80
  if (state.data.done && !state.data?.$error) {
@@ -133,7 +88,6 @@ class WorkflowHandleService {
133
88
  return await complete(null, error);
134
89
  }
135
90
  });
136
- //check state in case completed during wiring
137
91
  const status = await this.hotMesh.getStatus(this.workflowId);
138
92
  if (status <= 0) {
139
93
  await complete();
@@ -10,10 +10,6 @@ export declare const Durable: {
10
10
  Search: typeof Search;
11
11
  Worker: typeof WorkerService;
12
12
  workflow: typeof WorkflowService;
13
- /**
14
- * Shutdown everything. All connections, workers, and clients will be closed.
15
- * Include in your signal handlers to ensure a clean shutdown.
16
- */
17
13
  shutdown(): Promise<void>;
18
14
  };
19
15
  export type { ContextType };
@@ -13,10 +13,6 @@ exports.Durable = {
13
13
  Search: search_1.Search,
14
14
  Worker: worker_1.WorkerService,
15
15
  workflow: workflow_1.WorkflowService,
16
- /**
17
- * Shutdown everything. All connections, workers, and clients will be closed.
18
- * Include in your signal handlers to ensure a clean shutdown.
19
- */
20
16
  async shutdown() {
21
17
  await client_1.ClientService.shutdown();
22
18
  await worker_1.WorkerService.shutdown();
@@ -1,33 +1,4 @@
1
- /**
2
- *********** HOTMESH 'DURABLE' MODULE APPLICATION GRAPH **********
3
- *
4
- * This HotMesh application spec uses 50 activities and 25 transitions
5
- * to model and emulate the Temporal Application & Query servers using
6
- * Redis as the backend.
7
- *
8
- * It's particularly useful for organizations with high-speed, high-volume
9
- * use cases as it uses in-memory Redis Streams for transactional,
10
- * workflow processing, while adhering to Temporal's developer-friendly syntax.
11
- *
12
- * This YAML file can also serve as a useful starting point for building
13
- * Integration/BPM/Workflow servers in general (MuleSoft, etc) without the need
14
- * for a physical application server.
15
- *
16
- * Possible use cases include:
17
- * * Orchestration servers
18
- * * Integration servers
19
- * * BPMN engines
20
- * * Reentrant process servers
21
- * * Service Meshes
22
- * * Master Data Management systems
23
- */
24
1
  declare const APP_VERSION = "1";
25
2
  declare const APP_ID = "durable";
26
- /**
27
- * returns a new durable workflow schema
28
- * @param {string} app - app name (e.g., 'durable')
29
- * @param {string} version - number as string (e.g., '1')
30
- * @returns {string} HotMesh App YAML
31
- */
32
3
  declare const getWorkflowYAML: (app: string, version: string) => string;
33
4
  export { getWorkflowYAML, APP_VERSION, APP_ID, };
@@ -1,39 +1,10 @@
1
1
  "use strict";
2
- /**
3
- *********** HOTMESH 'DURABLE' MODULE APPLICATION GRAPH **********
4
- *
5
- * This HotMesh application spec uses 50 activities and 25 transitions
6
- * to model and emulate the Temporal Application & Query servers using
7
- * Redis as the backend.
8
- *
9
- * It's particularly useful for organizations with high-speed, high-volume
10
- * use cases as it uses in-memory Redis Streams for transactional,
11
- * workflow processing, while adhering to Temporal's developer-friendly syntax.
12
- *
13
- * This YAML file can also serve as a useful starting point for building
14
- * Integration/BPM/Workflow servers in general (MuleSoft, etc) without the need
15
- * for a physical application server.
16
- *
17
- * Possible use cases include:
18
- * * Orchestration servers
19
- * * Integration servers
20
- * * BPMN engines
21
- * * Reentrant process servers
22
- * * Service Meshes
23
- * * Master Data Management systems
24
- */
25
2
  Object.defineProperty(exports, "__esModule", { value: true });
26
3
  exports.APP_ID = exports.APP_VERSION = exports.getWorkflowYAML = void 0;
27
4
  const APP_VERSION = '1';
28
5
  exports.APP_VERSION = APP_VERSION;
29
6
  const APP_ID = 'durable';
30
7
  exports.APP_ID = APP_ID;
31
- /**
32
- * returns a new durable workflow schema
33
- * @param {string} app - app name (e.g., 'durable')
34
- * @param {string} version - number as string (e.g., '1')
35
- * @returns {string} HotMesh App YAML
36
- */
37
8
  const getWorkflowYAML = (app, version) => {
38
9
  return `app:
39
10
  id: ${app}
@@ -8,51 +8,16 @@ export declare class Search {
8
8
  searchSessionIndex: number;
9
9
  hotMeshClient: HotMesh;
10
10
  store: StoreService<RedisClient, RedisMulti> | null;
11
+ cachedFields: Record<string, string>;
11
12
  constructor(workflowId: string, hotMeshClient: HotMesh, searchSessionId: string);
12
13
  safeKey(key: string): string;
13
- /**
14
- * For those deployments with a redis stack backend (with the FT module),
15
- * this method will configure the search index for the workflow. For all
16
- * others, this method will exit/fail gracefully and not index
17
- * the fields in the HASH. However, all values are still available
18
- * in the HASH.
19
- */
20
14
  static configureSearchIndex(hotMeshClient: HotMesh, search?: WorkflowSearchOptions): Promise<void>;
21
- /**
22
- * For those deployments with a redis stack backend (with the FT module),
23
- * this method will list all search indexes.
24
- * @param {HotMesh} hotMeshClient - the hotmesh client
25
- * @returns {Promise<string[]>} - the list of search indexes
26
- */
27
15
  static listSearchIndexes(hotMeshClient: HotMesh): Promise<string[]>;
28
- /**
29
- * increments the index to return a unique search session guid when
30
- * calling any method that produces side effects (changes the value)
31
- */
32
16
  getSearchSessionGuid(): string;
33
- /**
34
- * Sets the fields listed in args. Returns the
35
- * count of new fields that were set (does not
36
- * count fields that were updated)
37
- */
38
17
  set(...args: string[]): Promise<number>;
39
18
  get(key: string): Promise<string>;
40
19
  mget(...args: string[]): Promise<string[]>;
41
- /**
42
- * Deletes the fields listed in args. Returns the
43
- * count of fields that were deleted.
44
- */
45
20
  del(...args: string[]): Promise<number | void>;
46
- /**
47
- * Increments the value of a field by the given amount. Returns the
48
- * new value of the field after the increment. Can be
49
- * used to decrement the value of a field by specifying a negative.
50
- */
51
21
  incr(key: string, val: number): Promise<number>;
52
- /**
53
- * Multiplies the value of a field by the given amount. Returns the
54
- * new value of the field after the multiplication. NOTE:
55
- * this is exponential multiplication.
56
- */
57
22
  mult(key: string, val: number): Promise<number>;
58
23
  }
@@ -6,6 +6,7 @@ const storage_1 = require("../../modules/storage");
6
6
  class Search {
7
7
  constructor(workflowId, hotMeshClient, searchSessionId) {
8
8
  this.searchSessionIndex = 0;
9
+ this.cachedFields = {};
9
10
  const keyParams = {
10
11
  appId: hotMeshClient.appId,
11
12
  jobId: workflowId
@@ -16,25 +17,31 @@ class Search {
16
17
  this.store = hotMeshClient.engine.store;
17
18
  }
18
19
  safeKey(key) {
20
+ if (key.startsWith('"')) {
21
+ return key.slice(1, -1);
22
+ }
19
23
  return `_${key}`;
20
24
  }
21
- /**
22
- * For those deployments with a redis stack backend (with the FT module),
23
- * this method will configure the search index for the workflow. For all
24
- * others, this method will exit/fail gracefully and not index
25
- * the fields in the HASH. However, all values are still available
26
- * in the HASH.
27
- */
28
25
  static async configureSearchIndex(hotMeshClient, search) {
29
26
  if (search?.schema) {
30
27
  const store = hotMeshClient.engine.store;
31
28
  const schema = [];
32
29
  for (const [key, value] of Object.entries(search.schema)) {
33
- //prefix with a comma (avoids collisions with hotmesh reserved words)
34
- schema.push(`_${key}`);
35
- schema.push(value.type);
36
- if (value.sortable) {
37
- schema.push('SORTABLE');
30
+ if (value.indexed !== false) {
31
+ schema.push(`_${key}`);
32
+ schema.push(value.type);
33
+ if (value.sortable) {
34
+ schema.push('SORTABLE');
35
+ }
36
+ if (value.sortable) {
37
+ schema.push('SORTABLE');
38
+ }
39
+ if (value.noindex) {
40
+ schema.push('NOINDEX');
41
+ }
42
+ if (value.nostem && value.type === 'TEXT') {
43
+ schema.push('NOSTEM');
44
+ }
38
45
  }
39
46
  }
40
47
  try {
@@ -51,12 +58,6 @@ class Search {
51
58
  }
52
59
  }
53
60
  }
54
- /**
55
- * For those deployments with a redis stack backend (with the FT module),
56
- * this method will list all search indexes.
57
- * @param {HotMesh} hotMeshClient - the hotmesh client
58
- * @returns {Promise<string[]>} - the list of search indexes
59
- */
60
61
  static async listSearchIndexes(hotMeshClient) {
61
62
  try {
62
63
  const store = hotMeshClient.engine.store;
@@ -68,40 +69,36 @@ class Search {
68
69
  return [];
69
70
  }
70
71
  }
71
- /**
72
- * increments the index to return a unique search session guid when
73
- * calling any method that produces side effects (changes the value)
74
- */
75
72
  getSearchSessionGuid() {
76
- //return the search session as it would exist in the search session index
77
73
  return `${this.searchSessionId}-${this.searchSessionIndex++}-`;
78
74
  }
79
- /**
80
- * Sets the fields listed in args. Returns the
81
- * count of new fields that were set (does not
82
- * count fields that were updated)
83
- */
84
75
  async set(...args) {
85
76
  const ssGuid = this.getSearchSessionGuid();
86
77
  const store = storage_1.asyncLocalStorage.getStore();
87
78
  const replay = store?.get('replay') ?? {};
88
- if (ssGuid in replay) {
89
- return Number(replay[ssGuid]);
90
- }
91
79
  const safeArgs = [];
92
80
  for (let i = 0; i < args.length; i += 2) {
93
- const key = this.safeKey(args[i]);
81
+ const keyName = args[i];
82
+ delete this.cachedFields[keyName];
83
+ const key = this.safeKey(keyName);
94
84
  const value = args[i + 1].toString();
95
85
  safeArgs.push(key, value);
96
86
  }
87
+ if (ssGuid in replay) {
88
+ return Number(replay[ssGuid]);
89
+ }
97
90
  const fieldCount = await this.store.exec('HSET', this.jobId, ...safeArgs);
98
- //no need to wait; set this interim value in the replay
99
91
  this.store.exec('HSET', this.jobId, ssGuid, fieldCount.toString());
100
92
  return Number(fieldCount);
101
93
  }
102
94
  async get(key) {
103
95
  try {
104
- return await this.store.exec('HGET', this.jobId, this.safeKey(key));
96
+ if (key in this.cachedFields) {
97
+ return this.cachedFields[key];
98
+ }
99
+ const value = await this.store.exec('HGET', this.jobId, this.safeKey(key));
100
+ this.cachedFields[key] = value;
101
+ return value;
105
102
  }
106
103
  catch (error) {
107
104
  this.hotMeshClient.logger.error('durable-search-get-error', { ...error });
@@ -109,45 +106,55 @@ class Search {
109
106
  }
110
107
  }
111
108
  async mget(...args) {
109
+ let isCached = true;
110
+ const values = [];
112
111
  const safeArgs = [];
113
112
  for (let i = 0; i < args.length; i++) {
113
+ if (isCached && args[i] in this.cachedFields) {
114
+ values.push(this.cachedFields[args[i]]);
115
+ }
116
+ else {
117
+ isCached = false;
118
+ }
114
119
  safeArgs.push(this.safeKey(args[i]));
115
120
  }
116
121
  try {
117
- return await this.store.exec('HMGET', this.jobId, ...safeArgs);
122
+ if (isCached) {
123
+ return values;
124
+ }
125
+ const returnValues = await this.store.exec('HMGET', this.jobId, ...safeArgs);
126
+ returnValues.forEach((value, index) => {
127
+ if (value !== null) {
128
+ this.cachedFields[args[index]] = value;
129
+ }
130
+ });
131
+ return returnValues;
118
132
  }
119
133
  catch (error) {
120
134
  this.hotMeshClient.logger.error('durable-search-mget-error', { ...error });
121
135
  return [];
122
136
  }
123
137
  }
124
- /**
125
- * Deletes the fields listed in args. Returns the
126
- * count of fields that were deleted.
127
- */
128
138
  async del(...args) {
129
139
  const ssGuid = this.getSearchSessionGuid();
130
140
  const store = storage_1.asyncLocalStorage.getStore();
131
141
  const replay = store?.get('replay') ?? {};
132
- if (ssGuid in replay) {
133
- return Number(replay[ssGuid]);
134
- }
135
142
  const safeArgs = [];
136
143
  for (let i = 0; i < args.length; i++) {
137
- safeArgs.push(this.safeKey(args[i]));
144
+ const keyName = args[i];
145
+ delete this.cachedFields[keyName];
146
+ safeArgs.push(this.safeKey(keyName));
147
+ }
148
+ if (ssGuid in replay) {
149
+ return Number(replay[ssGuid]);
138
150
  }
139
151
  const response = await this.store.exec('HDEL', this.jobId, ...safeArgs);
140
152
  const formattedResponse = isNaN(response) ? 0 : Number(response);
141
- //no need to wait; set this interim value in the replay
142
153
  this.store.exec('HSET', this.jobId, ssGuid, formattedResponse.toString());
143
154
  return formattedResponse;
144
155
  }
145
- /**
146
- * Increments the value of a field by the given amount. Returns the
147
- * new value of the field after the increment. Can be
148
- * used to decrement the value of a field by specifying a negative.
149
- */
150
156
  async incr(key, val) {
157
+ delete this.cachedFields[key];
151
158
  const ssGuid = this.getSearchSessionGuid();
152
159
  const store = storage_1.asyncLocalStorage.getStore();
153
160
  const replay = store?.get('replay') ?? {};
@@ -155,16 +162,11 @@ class Search {
155
162
  return Number(replay[ssGuid]);
156
163
  }
157
164
  const num = await this.store.exec('HINCRBYFLOAT', this.jobId, this.safeKey(key), val.toString());
158
- //no need to wait; set this interim value in the replay
159
165
  this.store.exec('HSET', this.jobId, ssGuid, num.toString());
160
166
  return Number(num);
161
167
  }
162
- /**
163
- * Multiplies the value of a field by the given amount. Returns the
164
- * new value of the field after the multiplication. NOTE:
165
- * this is exponential multiplication.
166
- */
167
168
  async mult(key, val) {
169
+ delete this.cachedFields[key];
168
170
  const ssGuid = this.getSearchSessionGuid();
169
171
  const store = storage_1.asyncLocalStorage.getStore();
170
172
  const replay = store?.get('replay') ?? {};
@@ -175,7 +177,6 @@ class Search {
175
177
  if (ssGuidValue === 1) {
176
178
  const log = Math.log(val);
177
179
  const logTotal = await this.store.exec('HINCRBYFLOAT', this.jobId, this.safeKey(key), log.toString());
178
- //no need to wait; set this interim value in the replay
179
180
  this.store.exec('HSET', this.jobId, ssGuid, logTotal.toString());
180
181
  return Math.exp(Number(logTotal));
181
182
  }