@hotmeshio/hotmesh 0.0.1

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 (263) hide show
  1. package/LICENSE +214 -0
  2. package/README.md +241 -0
  3. package/build/index.d.ts +4 -0
  4. package/build/index.js +7 -0
  5. package/build/modules/errors.d.ts +28 -0
  6. package/build/modules/errors.js +50 -0
  7. package/build/modules/key.d.ts +75 -0
  8. package/build/modules/key.js +116 -0
  9. package/build/modules/utils.d.ts +34 -0
  10. package/build/modules/utils.js +173 -0
  11. package/build/package.json +73 -0
  12. package/build/services/activities/activity.d.ts +59 -0
  13. package/build/services/activities/activity.js +396 -0
  14. package/build/services/activities/await.d.ts +16 -0
  15. package/build/services/activities/await.js +143 -0
  16. package/build/services/activities/emit.d.ts +9 -0
  17. package/build/services/activities/emit.js +13 -0
  18. package/build/services/activities/index.d.ts +15 -0
  19. package/build/services/activities/index.js +16 -0
  20. package/build/services/activities/iterate.d.ts +9 -0
  21. package/build/services/activities/iterate.js +13 -0
  22. package/build/services/activities/trigger.d.ts +22 -0
  23. package/build/services/activities/trigger.js +161 -0
  24. package/build/services/activities/worker.d.ts +17 -0
  25. package/build/services/activities/worker.js +164 -0
  26. package/build/services/collator/index.d.ts +54 -0
  27. package/build/services/collator/index.js +171 -0
  28. package/build/services/compiler/deployer.d.ts +35 -0
  29. package/build/services/compiler/deployer.js +412 -0
  30. package/build/services/compiler/index.d.ts +30 -0
  31. package/build/services/compiler/index.js +111 -0
  32. package/build/services/compiler/validator.d.ts +32 -0
  33. package/build/services/compiler/validator.js +134 -0
  34. package/build/services/connector/clients/ioredis.d.ts +13 -0
  35. package/build/services/connector/clients/ioredis.js +50 -0
  36. package/build/services/connector/clients/redis.d.ts +13 -0
  37. package/build/services/connector/clients/redis.js +62 -0
  38. package/build/services/connector/index.d.ts +5 -0
  39. package/build/services/connector/index.js +31 -0
  40. package/build/services/dimension/index.d.ts +29 -0
  41. package/build/services/dimension/index.js +35 -0
  42. package/build/services/durable/asyncLocalStorage.d.ts +3 -0
  43. package/build/services/durable/asyncLocalStorage.js +5 -0
  44. package/build/services/durable/client.d.ts +15 -0
  45. package/build/services/durable/client.js +108 -0
  46. package/build/services/durable/connection.d.ts +4 -0
  47. package/build/services/durable/connection.js +51 -0
  48. package/build/services/durable/factory.d.ts +3 -0
  49. package/build/services/durable/factory.js +123 -0
  50. package/build/services/durable/handle.d.ts +8 -0
  51. package/build/services/durable/handle.js +38 -0
  52. package/build/services/durable/index.d.ts +57 -0
  53. package/build/services/durable/index.js +58 -0
  54. package/build/services/durable/native.d.ts +4 -0
  55. package/build/services/durable/native.js +47 -0
  56. package/build/services/durable/worker.d.ts +36 -0
  57. package/build/services/durable/worker.js +266 -0
  58. package/build/services/durable/workflow.d.ts +6 -0
  59. package/build/services/durable/workflow.js +135 -0
  60. package/build/services/engine/index.d.ts +82 -0
  61. package/build/services/engine/index.js +511 -0
  62. package/build/services/hotmesh/index.d.ts +45 -0
  63. package/build/services/hotmesh/index.js +134 -0
  64. package/build/services/logger/index.d.ts +17 -0
  65. package/build/services/logger/index.js +73 -0
  66. package/build/services/mapper/index.d.ts +24 -0
  67. package/build/services/mapper/index.js +72 -0
  68. package/build/services/pipe/functions/array.d.ts +24 -0
  69. package/build/services/pipe/functions/array.js +69 -0
  70. package/build/services/pipe/functions/bitwise.d.ts +9 -0
  71. package/build/services/pipe/functions/bitwise.js +24 -0
  72. package/build/services/pipe/functions/conditional.d.ts +10 -0
  73. package/build/services/pipe/functions/conditional.js +27 -0
  74. package/build/services/pipe/functions/date.d.ts +57 -0
  75. package/build/services/pipe/functions/date.js +167 -0
  76. package/build/services/pipe/functions/index.d.ts +25 -0
  77. package/build/services/pipe/functions/index.js +26 -0
  78. package/build/services/pipe/functions/json.d.ts +5 -0
  79. package/build/services/pipe/functions/json.js +12 -0
  80. package/build/services/pipe/functions/math.d.ts +38 -0
  81. package/build/services/pipe/functions/math.js +111 -0
  82. package/build/services/pipe/functions/number.d.ts +25 -0
  83. package/build/services/pipe/functions/number.js +133 -0
  84. package/build/services/pipe/functions/object.d.ts +22 -0
  85. package/build/services/pipe/functions/object.js +63 -0
  86. package/build/services/pipe/functions/string.d.ts +23 -0
  87. package/build/services/pipe/functions/string.js +69 -0
  88. package/build/services/pipe/functions/symbol.d.ts +12 -0
  89. package/build/services/pipe/functions/symbol.js +33 -0
  90. package/build/services/pipe/functions/unary.d.ts +7 -0
  91. package/build/services/pipe/functions/unary.js +18 -0
  92. package/build/services/pipe/index.d.ts +30 -0
  93. package/build/services/pipe/index.js +128 -0
  94. package/build/services/quorum/index.d.ts +34 -0
  95. package/build/services/quorum/index.js +147 -0
  96. package/build/services/reporter/index.d.ts +47 -0
  97. package/build/services/reporter/index.js +330 -0
  98. package/build/services/serializer/index.d.ts +36 -0
  99. package/build/services/serializer/index.js +222 -0
  100. package/build/services/signaler/store.d.ts +15 -0
  101. package/build/services/signaler/store.js +53 -0
  102. package/build/services/signaler/stream.d.ts +43 -0
  103. package/build/services/signaler/stream.js +317 -0
  104. package/build/services/store/cache.d.ts +66 -0
  105. package/build/services/store/cache.js +127 -0
  106. package/build/services/store/clients/ioredis.d.ts +27 -0
  107. package/build/services/store/clients/ioredis.js +96 -0
  108. package/build/services/store/clients/redis.d.ts +29 -0
  109. package/build/services/store/clients/redis.js +143 -0
  110. package/build/services/store/index.d.ts +88 -0
  111. package/build/services/store/index.js +657 -0
  112. package/build/services/stream/clients/ioredis.d.ts +23 -0
  113. package/build/services/stream/clients/ioredis.js +115 -0
  114. package/build/services/stream/clients/redis.d.ts +23 -0
  115. package/build/services/stream/clients/redis.js +119 -0
  116. package/build/services/stream/index.d.ts +21 -0
  117. package/build/services/stream/index.js +9 -0
  118. package/build/services/sub/clients/ioredis.d.ts +20 -0
  119. package/build/services/sub/clients/ioredis.js +72 -0
  120. package/build/services/sub/clients/redis.d.ts +20 -0
  121. package/build/services/sub/clients/redis.js +63 -0
  122. package/build/services/sub/index.d.ts +18 -0
  123. package/build/services/sub/index.js +9 -0
  124. package/build/services/task/index.d.ts +18 -0
  125. package/build/services/task/index.js +73 -0
  126. package/build/services/telemetry/index.d.ts +49 -0
  127. package/build/services/telemetry/index.js +223 -0
  128. package/build/services/worker/index.d.ts +30 -0
  129. package/build/services/worker/index.js +105 -0
  130. package/build/types/activity.d.ts +86 -0
  131. package/build/types/activity.js +2 -0
  132. package/build/types/app.d.ts +16 -0
  133. package/build/types/app.js +2 -0
  134. package/build/types/async.d.ts +5 -0
  135. package/build/types/async.js +2 -0
  136. package/build/types/cache.d.ts +1 -0
  137. package/build/types/cache.js +2 -0
  138. package/build/types/collator.d.ts +8 -0
  139. package/build/types/collator.js +11 -0
  140. package/build/types/durable.d.ts +59 -0
  141. package/build/types/durable.js +2 -0
  142. package/build/types/hook.d.ts +31 -0
  143. package/build/types/hook.js +9 -0
  144. package/build/types/hotmesh.d.ts +82 -0
  145. package/build/types/hotmesh.js +2 -0
  146. package/build/types/index.d.ts +20 -0
  147. package/build/types/index.js +21 -0
  148. package/build/types/ioredisclient.d.ts +5 -0
  149. package/build/types/ioredisclient.js +5 -0
  150. package/build/types/job.d.ts +50 -0
  151. package/build/types/job.js +2 -0
  152. package/build/types/logger.d.ts +6 -0
  153. package/build/types/logger.js +2 -0
  154. package/build/types/map.d.ts +4 -0
  155. package/build/types/map.js +2 -0
  156. package/build/types/pipe.d.ts +4 -0
  157. package/build/types/pipe.js +2 -0
  158. package/build/types/quorum.d.ts +46 -0
  159. package/build/types/quorum.js +2 -0
  160. package/build/types/redis.d.ts +8 -0
  161. package/build/types/redis.js +2 -0
  162. package/build/types/redisclient.d.ts +25 -0
  163. package/build/types/redisclient.js +2 -0
  164. package/build/types/serializer.d.ts +33 -0
  165. package/build/types/serializer.js +2 -0
  166. package/build/types/stats.d.ts +83 -0
  167. package/build/types/stats.js +2 -0
  168. package/build/types/stream.d.ts +67 -0
  169. package/build/types/stream.js +25 -0
  170. package/build/types/telemetry.d.ts +1 -0
  171. package/build/types/telemetry.js +11 -0
  172. package/build/types/transition.d.ts +17 -0
  173. package/build/types/transition.js +2 -0
  174. package/index.ts +5 -0
  175. package/modules/errors.ts +55 -0
  176. package/modules/key.ts +129 -0
  177. package/modules/utils.ts +170 -0
  178. package/package.json +73 -0
  179. package/services/activities/activity.ts +473 -0
  180. package/services/activities/await.ts +172 -0
  181. package/services/activities/emit.ts +25 -0
  182. package/services/activities/index.ts +15 -0
  183. package/services/activities/iterate.ts +26 -0
  184. package/services/activities/trigger.ts +196 -0
  185. package/services/activities/worker.ts +190 -0
  186. package/services/collator/README.md +102 -0
  187. package/services/collator/index.ts +182 -0
  188. package/services/compiler/deployer.ts +432 -0
  189. package/services/compiler/index.ts +98 -0
  190. package/services/compiler/validator.ts +154 -0
  191. package/services/connector/clients/ioredis.ts +57 -0
  192. package/services/connector/clients/redis.ts +72 -0
  193. package/services/connector/index.ts +44 -0
  194. package/services/dimension/README.md +73 -0
  195. package/services/dimension/index.ts +39 -0
  196. package/services/durable/asyncLocalStorage.ts +3 -0
  197. package/services/durable/client.ts +116 -0
  198. package/services/durable/connection.ts +50 -0
  199. package/services/durable/factory.ts +124 -0
  200. package/services/durable/handle.ts +43 -0
  201. package/services/durable/index.ts +60 -0
  202. package/services/durable/native.ts +46 -0
  203. package/services/durable/worker.ts +254 -0
  204. package/services/durable/workflow.ts +136 -0
  205. package/services/engine/index.ts +615 -0
  206. package/services/hotmesh/index.ts +182 -0
  207. package/services/logger/index.ts +79 -0
  208. package/services/mapper/index.ts +84 -0
  209. package/services/pipe/functions/array.ts +87 -0
  210. package/services/pipe/functions/bitwise.ts +27 -0
  211. package/services/pipe/functions/conditional.ts +31 -0
  212. package/services/pipe/functions/date.ts +214 -0
  213. package/services/pipe/functions/index.ts +25 -0
  214. package/services/pipe/functions/json.ts +11 -0
  215. package/services/pipe/functions/math.ts +143 -0
  216. package/services/pipe/functions/number.ts +150 -0
  217. package/services/pipe/functions/object.ts +79 -0
  218. package/services/pipe/functions/string.ts +86 -0
  219. package/services/pipe/functions/symbol.ts +39 -0
  220. package/services/pipe/functions/unary.ts +19 -0
  221. package/services/pipe/index.ts +138 -0
  222. package/services/quorum/index.ts +200 -0
  223. package/services/reporter/index.ts +379 -0
  224. package/services/serializer/README.md +10 -0
  225. package/services/serializer/index.ts +243 -0
  226. package/services/signaler/store.ts +61 -0
  227. package/services/signaler/stream.ts +354 -0
  228. package/services/store/cache.ts +172 -0
  229. package/services/store/clients/ioredis.ts +123 -0
  230. package/services/store/clients/redis.ts +169 -0
  231. package/services/store/index.ts +757 -0
  232. package/services/stream/clients/ioredis.ts +148 -0
  233. package/services/stream/clients/redis.ts +144 -0
  234. package/services/stream/index.ts +57 -0
  235. package/services/sub/clients/ioredis.ts +83 -0
  236. package/services/sub/clients/redis.ts +74 -0
  237. package/services/sub/index.ts +25 -0
  238. package/services/task/index.ts +86 -0
  239. package/services/telemetry/index.ts +267 -0
  240. package/services/worker/index.ts +165 -0
  241. package/types/activity.ts +115 -0
  242. package/types/app.ts +20 -0
  243. package/types/async.ts +7 -0
  244. package/types/cache.ts +1 -0
  245. package/types/collator.ts +9 -0
  246. package/types/durable.ts +81 -0
  247. package/types/hook.ts +32 -0
  248. package/types/hotmesh.ts +102 -0
  249. package/types/index.ts +138 -0
  250. package/types/ioredisclient.ts +10 -0
  251. package/types/job.ts +59 -0
  252. package/types/logger.ts +6 -0
  253. package/types/map.ts +5 -0
  254. package/types/ms.d.ts +7 -0
  255. package/types/pipe.ts +7 -0
  256. package/types/quorum.ts +59 -0
  257. package/types/redis.ts +27 -0
  258. package/types/redisclient.ts +29 -0
  259. package/types/serializer.ts +38 -0
  260. package/types/stats.ts +100 -0
  261. package/types/stream.ts +75 -0
  262. package/types/telemetry.ts +15 -0
  263. package/types/transition.ts +20 -0
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getWorkflowYAML = exports.getActivityYAML = void 0;
4
+ const getWorkflowYAML = (topic, version = '1') => {
5
+ return `app:
6
+ id: ${topic}
7
+ version: '${version}'
8
+ graphs:
9
+ - subscribes: ${topic}
10
+ publishes: ${topic}
11
+ expire: 120
12
+ input:
13
+ schema:
14
+ type: object
15
+ properties:
16
+ workflowId:
17
+ type: string
18
+ arguments:
19
+ type: array
20
+ output:
21
+ schema:
22
+ type: object
23
+ properties:
24
+ response:
25
+ type: any
26
+
27
+ activities:
28
+ t1:
29
+ type: trigger
30
+ stats:
31
+ id: '{$self.input.data.workflowId}'
32
+ a1:
33
+ type: worker
34
+ topic: ${topic}
35
+ input:
36
+ schema:
37
+ type: object
38
+ properties:
39
+ workflowId:
40
+ type: string
41
+ arguments:
42
+ type: array
43
+ maps:
44
+ workflowId: '{t1.output.data.workflowId}'
45
+ arguments: '{t1.output.data.arguments}'
46
+ output:
47
+ schema:
48
+ type: object
49
+ properties:
50
+ response:
51
+ type: any
52
+ job:
53
+ maps:
54
+ response: '{$self.output.data.response}'
55
+ transitions:
56
+ t1:
57
+ - to: a1`;
58
+ };
59
+ exports.getWorkflowYAML = getWorkflowYAML;
60
+ const getActivityYAML = (topic, version = '1') => {
61
+ return `app:
62
+ id: ${topic}
63
+ version: '${version}'
64
+ graphs:
65
+ - subscribes: ${topic}
66
+ input:
67
+ schema:
68
+ type: object
69
+ properties:
70
+ workflowId:
71
+ type: string
72
+ workflowTopic:
73
+ type: string
74
+ activityName:
75
+ type: array
76
+ arguments:
77
+ type: array
78
+ output:
79
+ schema:
80
+ type: object
81
+ properties:
82
+ response:
83
+ type: any
84
+
85
+ activities:
86
+ t1:
87
+ type: trigger
88
+ stats:
89
+ id: '{$self.input.data.workflowId}'
90
+ a1:
91
+ type: worker
92
+ topic: ${topic}
93
+ input:
94
+ schema:
95
+ type: object
96
+ properties:
97
+ workflowId:
98
+ type: string
99
+ workflowTopic:
100
+ type: string
101
+ activityName:
102
+ type: array
103
+ arguments:
104
+ type: array
105
+ maps:
106
+ workflowId: '{t1.output.data.workflowId}'
107
+ workflowTopic: '{t1.output.data.workflowTopic}'
108
+ activityName: '{t1.output.data.activityName}'
109
+ arguments: '{t1.output.data.arguments}'
110
+ output:
111
+ schema:
112
+ type: object
113
+ properties:
114
+ response:
115
+ type: any
116
+ job:
117
+ maps:
118
+ response: '{$self.output.data.response}'
119
+ transitions:
120
+ t1:
121
+ - to: a1`;
122
+ };
123
+ exports.getActivityYAML = getActivityYAML;
@@ -0,0 +1,8 @@
1
+ import { HotMeshService as HotMesh } from "../hotmesh";
2
+ export declare class WorkflowHandleService {
3
+ hotMesh: HotMesh;
4
+ workflowTopic: string;
5
+ workflowId: string;
6
+ constructor(hotMesh: HotMesh, workflowTopic: string, workflowId: string);
7
+ result(): Promise<any>;
8
+ }
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WorkflowHandleService = void 0;
4
+ class WorkflowHandleService {
5
+ constructor(hotMesh, workflowTopic, workflowId) {
6
+ this.workflowTopic = workflowTopic;
7
+ this.workflowId = workflowId;
8
+ this.hotMesh = hotMesh;
9
+ }
10
+ async result() {
11
+ let status = await this.hotMesh.getStatus(this.workflowId);
12
+ const topic = `${this.workflowTopic}.${this.workflowId}`;
13
+ if (status == 0) {
14
+ return (await this.hotMesh.getState(this.workflowTopic, this.workflowId)).data?.response;
15
+ }
16
+ return new Promise((resolve, reject) => {
17
+ let isResolved = false;
18
+ //common fulfill/unsubscribe
19
+ const complete = async (response) => {
20
+ if (isResolved)
21
+ return;
22
+ isResolved = true;
23
+ this.hotMesh.unsub(topic);
24
+ resolve(response || (await this.hotMesh.getState(this.workflowTopic, this.workflowId)).data?.response);
25
+ };
26
+ this.hotMesh.sub(topic, async (topic, message) => {
27
+ await complete(message.data?.response);
28
+ });
29
+ setTimeout(async () => {
30
+ status = await this.hotMesh.getStatus(this.workflowId);
31
+ if (status == 0) {
32
+ await complete();
33
+ }
34
+ }, 0);
35
+ });
36
+ }
37
+ }
38
+ exports.WorkflowHandleService = WorkflowHandleService;
@@ -0,0 +1,57 @@
1
+ import { ClientService } from './client';
2
+ import { ConnectionService } from './connection';
3
+ import { NativeConnectionService } from './native';
4
+ import { WorkerService } from './worker';
5
+ import { WorkflowService } from './workflow';
6
+ import { ContextType } from '../../types/durable';
7
+ /**
8
+ * As a durable integration platform, HotMesh
9
+ * can model and emulate other durable systems
10
+ * (like Temporal). As you review the code in
11
+ * this file, note the following:
12
+ *
13
+ * 1) There is no central governing server.
14
+ * HotMesh is a client-side SDK that connects to Redis
15
+ * using CQRS principles to implicitly drive
16
+ * orchestrations using a headless quorum. Stream
17
+ * semantics guarantee that all events are
18
+ * processed by the quorum of connected clients.
19
+ *
20
+ * 2) Every developer-defined `workflow` function
21
+ * is assigned a HotMesh workflow (which runs in
22
+ * the background) to support it.
23
+ *
24
+ * If the HotMesh workflow is not yet defined,
25
+ * it will be deployed and activated on-the-fly.
26
+ * (The generated DAG will have one Trigger Activity
27
+ * and one Worker Activity.) The Worker Activity
28
+ * is configured to catch execution errors and
29
+ * return them, using a 'pending' status to
30
+ * indicate that the workflow is still running.
31
+ * It is possible for workflow activities to throw
32
+ * errors that will force the entire workflow to
33
+ * fail. This is not the case here. The workflow will
34
+ * continue to run until it is completed or cancelled.
35
+ *
36
+ * 2) Every developer-defined `activity` function
37
+ * is assigned a HotMesh workflow (which runs in
38
+ * the background) to support it.
39
+ *
40
+ * (The generated DAG will have one Trigger Activity and one
41
+ * Worker Activity.) The JOB ID for Worker Activity executions
42
+ * is derived from the containing JOB ID,
43
+ * allowing Activity state to be 'replayed' when the workflow
44
+ * is run again. The Activity Function Runner (activity proxy)
45
+ * is configured similar to how the workflow worker is and will
46
+ * catch execution errors and return them to the caller, using a
47
+ * 'pending' status to indicate that the activity is still running.
48
+ * This allows the activity to be retried until it succeeds.
49
+ */
50
+ export declare const Durable: {
51
+ Client: typeof ClientService;
52
+ Connection: typeof ConnectionService;
53
+ NativeConnection: typeof NativeConnectionService;
54
+ Worker: typeof WorkerService;
55
+ workflow: typeof WorkflowService;
56
+ };
57
+ export type { ContextType };
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Durable = void 0;
4
+ const client_1 = require("./client");
5
+ const connection_1 = require("./connection");
6
+ const native_1 = require("./native");
7
+ const worker_1 = require("./worker");
8
+ const workflow_1 = require("./workflow");
9
+ /**
10
+ * As a durable integration platform, HotMesh
11
+ * can model and emulate other durable systems
12
+ * (like Temporal). As you review the code in
13
+ * this file, note the following:
14
+ *
15
+ * 1) There is no central governing server.
16
+ * HotMesh is a client-side SDK that connects to Redis
17
+ * using CQRS principles to implicitly drive
18
+ * orchestrations using a headless quorum. Stream
19
+ * semantics guarantee that all events are
20
+ * processed by the quorum of connected clients.
21
+ *
22
+ * 2) Every developer-defined `workflow` function
23
+ * is assigned a HotMesh workflow (which runs in
24
+ * the background) to support it.
25
+ *
26
+ * If the HotMesh workflow is not yet defined,
27
+ * it will be deployed and activated on-the-fly.
28
+ * (The generated DAG will have one Trigger Activity
29
+ * and one Worker Activity.) The Worker Activity
30
+ * is configured to catch execution errors and
31
+ * return them, using a 'pending' status to
32
+ * indicate that the workflow is still running.
33
+ * It is possible for workflow activities to throw
34
+ * errors that will force the entire workflow to
35
+ * fail. This is not the case here. The workflow will
36
+ * continue to run until it is completed or cancelled.
37
+ *
38
+ * 2) Every developer-defined `activity` function
39
+ * is assigned a HotMesh workflow (which runs in
40
+ * the background) to support it.
41
+ *
42
+ * (The generated DAG will have one Trigger Activity and one
43
+ * Worker Activity.) The JOB ID for Worker Activity executions
44
+ * is derived from the containing JOB ID,
45
+ * allowing Activity state to be 'replayed' when the workflow
46
+ * is run again. The Activity Function Runner (activity proxy)
47
+ * is configured similar to how the workflow worker is and will
48
+ * catch execution errors and return them to the caller, using a
49
+ * 'pending' status to indicate that the activity is still running.
50
+ * This allows the activity to be retried until it succeeds.
51
+ */
52
+ exports.Durable = {
53
+ Client: client_1.ClientService,
54
+ Connection: connection_1.ConnectionService,
55
+ NativeConnection: native_1.NativeConnectionService,
56
+ Worker: worker_1.WorkerService,
57
+ workflow: workflow_1.WorkflowService,
58
+ };
@@ -0,0 +1,4 @@
1
+ import { Connection, ConnectionConfig } from "../../types/durable";
2
+ export declare class NativeConnectionService {
3
+ static connect(config: ConnectionConfig): Promise<Connection>;
4
+ }
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NativeConnectionService = void 0;
4
+ /*
5
+
6
+ Here is an example of how the methods in this file are used:
7
+
8
+ ./worker.ts
9
+
10
+ import { Durable: { NativeConnection, Worker } } from '@hotmeshio/hotmesh';
11
+ import Redis from 'ioredis'; //OR `import * as Redis from 'redis';`
12
+
13
+ import * as activities from './activities';
14
+
15
+ async function run() {
16
+ const connection = await NativeConnection.connect({
17
+ class: Redis,
18
+ options: {
19
+ host: 'localhost',
20
+ port: 6379,
21
+ },
22
+ });
23
+ const worker = await Worker.create({
24
+ connection,
25
+ namespace: 'default',
26
+ taskQueue: 'hello-world',
27
+ workflowsPath: require.resolve('./workflows'),
28
+ activities,
29
+ });
30
+ await worker.run();
31
+ }
32
+
33
+ run().catch((err) => {
34
+ console.error(err);
35
+ process.exit(1);
36
+ });
37
+
38
+ */
39
+ class NativeConnectionService {
40
+ static async connect(config) {
41
+ return {
42
+ class: config.class,
43
+ options: { ...config.options },
44
+ };
45
+ }
46
+ }
47
+ exports.NativeConnectionService = NativeConnectionService;
@@ -0,0 +1,36 @@
1
+ import { HotMeshService as HotMesh } from '../hotmesh';
2
+ import { Connection, Registry, WorkerConfig } from "../../types/durable";
3
+ export declare class WorkerService {
4
+ static activityRegistry: Registry;
5
+ static connection: Connection;
6
+ static instances: Map<string, HotMesh | Promise<HotMesh>>;
7
+ workflowRunner: HotMesh;
8
+ static getHotMesh: (worflowTopic: string) => Promise<HotMesh>;
9
+ static activateWorkflow(hotMesh: HotMesh, topic: string, factory: Function): Promise<void>;
10
+ /**
11
+ * The `worker` calls `registerActivities` immediately BEFORE
12
+ * dynamically importing the user's workflow module. That file
13
+ * contains a call, `proxyActivities`, which needs this info.
14
+ *
15
+ * NOTE: The `worker` and `client` both call `proxyActivities`,
16
+ * as a natural result of importing worflows.ts. However,
17
+ * because the worker imports the workflows dynamically AFTER
18
+ * the activities are loaded, there will be items in the registry,
19
+ * allowing proxyActivities to succeed.
20
+ */
21
+ static registerActivities<ACT>(activities: ACT): Registry;
22
+ static create(config: WorkerConfig): Promise<WorkerService>;
23
+ run(): Promise<void>;
24
+ initActivityWorkflow(config: WorkerConfig, activityTopic: string): Promise<HotMesh>;
25
+ wrapActivityFunctions(): Function;
26
+ activateActivityWorkflow(hotMesh: HotMesh, activityTopic: string): Promise<void>;
27
+ initWorkerWorkflow(config: WorkerConfig, workflowTopic: string, workflowFunction: Function): Promise<HotMesh>;
28
+ static Context: {
29
+ info: () => {
30
+ workflowId: string;
31
+ workflowTopic: string;
32
+ };
33
+ };
34
+ wrapWorkflowFunction(workflowFunction: Function, workflowTopic: string): Function;
35
+ static shutdown(): Promise<void>;
36
+ }
@@ -0,0 +1,266 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var _a;
26
+ Object.defineProperty(exports, "__esModule", { value: true });
27
+ exports.WorkerService = void 0;
28
+ const asyncLocalStorage_1 = require("./asyncLocalStorage");
29
+ const hotmesh_1 = require("../hotmesh");
30
+ const stream_1 = require("../../types/stream");
31
+ const factory_1 = require("./factory");
32
+ /*
33
+ Here is an example of how the methods in this file are used:
34
+
35
+ ./worker.ts
36
+
37
+ import { Durable: { NativeConnection, Worker } } from '@hotmeshio/hotmesh';
38
+ import Redis from 'ioredis'; //OR `import * as Redis from 'redis';`
39
+
40
+ import * as activities from './activities';
41
+
42
+ async function run() {
43
+ const connection = await NativeConnection.connect({
44
+ class: Redis,
45
+ options: {
46
+ host: 'localhost',
47
+ port: 6379,
48
+ },
49
+ });
50
+ const worker = await Worker.create({
51
+ connection,
52
+ namespace: 'default',
53
+ taskQueue: 'hello-world',
54
+ workflowsPath: require.resolve('./workflows'),
55
+ activities,
56
+ });
57
+ await worker.run();
58
+ }
59
+
60
+ run().catch((err) => {
61
+ console.error(err);
62
+ process.exit(1);
63
+ });
64
+ */
65
+ class WorkerService {
66
+ static async activateWorkflow(hotMesh, topic, factory) {
67
+ const version = '1';
68
+ const app = await hotMesh.engine.store.getApp(topic);
69
+ const appVersion = app?.version;
70
+ if (!appVersion) {
71
+ try {
72
+ await hotMesh.deploy(factory(topic, version));
73
+ await hotMesh.activate(version);
74
+ }
75
+ catch (err) {
76
+ hotMesh.engine.logger.error('durable-worker-workflow-activation-error', err);
77
+ throw err;
78
+ }
79
+ }
80
+ }
81
+ /**
82
+ * The `worker` calls `registerActivities` immediately BEFORE
83
+ * dynamically importing the user's workflow module. That file
84
+ * contains a call, `proxyActivities`, which needs this info.
85
+ *
86
+ * NOTE: The `worker` and `client` both call `proxyActivities`,
87
+ * as a natural result of importing worflows.ts. However,
88
+ * because the worker imports the workflows dynamically AFTER
89
+ * the activities are loaded, there will be items in the registry,
90
+ * allowing proxyActivities to succeed.
91
+ */
92
+ static registerActivities(activities) {
93
+ Object.keys(activities).forEach(key => {
94
+ WorkerService.activityRegistry[key] = activities[key];
95
+ });
96
+ return WorkerService.activityRegistry;
97
+ }
98
+ static async create(config) {
99
+ WorkerService.connection = config.connection;
100
+ //pre-cache user activity functions
101
+ WorkerService.registerActivities(config.activities);
102
+ //import the user's workflow file (triggers activity functions to be wrapped)
103
+ const workflow = await Promise.resolve(`${config.workflowsPath}`).then(s => __importStar(require(s)));
104
+ const workflowFunctionNames = Object.keys(workflow);
105
+ const workflowFunctionName = workflowFunctionNames[workflowFunctionNames.length - 1];
106
+ const workflowFunction = workflow[workflowFunctionName];
107
+ const baseTopic = `${config.taskQueue}-${workflowFunctionName}`;
108
+ const activityTopic = `${baseTopic}-activity`;
109
+ const workflowTopic = `${baseTopic}`;
110
+ //initialize supporting workflows
111
+ const worker = new WorkerService();
112
+ const activityRunner = await worker.initActivityWorkflow(config, activityTopic);
113
+ await WorkerService.activateWorkflow(activityRunner, activityTopic, factory_1.getActivityYAML);
114
+ worker.workflowRunner = await worker.initWorkerWorkflow(config, workflowTopic, workflowFunction);
115
+ await WorkerService.activateWorkflow(worker.workflowRunner, workflowTopic, factory_1.getWorkflowYAML);
116
+ return worker;
117
+ }
118
+ async run() {
119
+ if (this.workflowRunner) {
120
+ this.workflowRunner.engine.logger.info('WorkerService is running');
121
+ }
122
+ else {
123
+ console.log('WorkerService is running');
124
+ }
125
+ }
126
+ async initActivityWorkflow(config, activityTopic) {
127
+ const redisConfig = {
128
+ class: config.connection.class,
129
+ options: config.connection.options
130
+ };
131
+ const hmshInstance = await hotmesh_1.HotMeshService.init({
132
+ appId: activityTopic,
133
+ engine: { redis: redisConfig },
134
+ workers: [
135
+ { topic: activityTopic,
136
+ redis: redisConfig,
137
+ callback: this.wrapActivityFunctions().bind(this)
138
+ }
139
+ ]
140
+ });
141
+ WorkerService.instances.set(activityTopic, hmshInstance);
142
+ return hmshInstance;
143
+ }
144
+ wrapActivityFunctions() {
145
+ return async (data) => {
146
+ try {
147
+ //always run the activity function when instructed; return the response
148
+ const activityInput = data.data;
149
+ const activityName = activityInput.activityName;
150
+ const activityFunction = WorkerService.activityRegistry[activityName];
151
+ const pojoResponse = await activityFunction.apply(this, activityInput.arguments);
152
+ return {
153
+ status: stream_1.StreamStatus.SUCCESS,
154
+ metadata: { ...data.metadata },
155
+ data: { response: pojoResponse }
156
+ };
157
+ }
158
+ catch (err) {
159
+ console.error(err);
160
+ //todo (make retry configurable)
161
+ return {
162
+ status: stream_1.StreamStatus.PENDING,
163
+ metadata: { ...data.metadata },
164
+ data: { error: err }
165
+ };
166
+ }
167
+ };
168
+ }
169
+ async activateActivityWorkflow(hotMesh, activityTopic) {
170
+ const version = '1';
171
+ const app = await hotMesh.engine.store.getApp(activityTopic);
172
+ const appVersion = app?.version;
173
+ if (isNaN(appVersion)) {
174
+ try {
175
+ await hotMesh.deploy((0, factory_1.getActivityYAML)(activityTopic, version));
176
+ await hotMesh.activate(version);
177
+ }
178
+ catch (err) {
179
+ console.log('durable-worker-activity-workflow-activation-error', err);
180
+ throw err;
181
+ }
182
+ }
183
+ }
184
+ async initWorkerWorkflow(config, workflowTopic, workflowFunction) {
185
+ const redisConfig = {
186
+ class: config.connection.class,
187
+ options: config.connection.options
188
+ };
189
+ const hmshInstance = await hotmesh_1.HotMeshService.init({
190
+ appId: workflowTopic,
191
+ engine: { redis: redisConfig },
192
+ workers: [
193
+ { topic: workflowTopic,
194
+ redis: redisConfig,
195
+ callback: this.wrapWorkflowFunction(workflowFunction, workflowTopic).bind(this)
196
+ }
197
+ ]
198
+ });
199
+ WorkerService.instances.set(workflowTopic, hmshInstance);
200
+ return hmshInstance;
201
+ }
202
+ wrapWorkflowFunction(workflowFunction, workflowTopic) {
203
+ return async (data) => {
204
+ try {
205
+ //incoming data payload has arguments and workflowId
206
+ const workflowInput = data.data;
207
+ const context = new Map();
208
+ const counter = { counter: 0 };
209
+ context.set('counter', counter);
210
+ context.set('workflowId', workflowInput.workflowId);
211
+ context.set('workflowTopic', workflowTopic);
212
+ context.set('workflowName', workflowTopic.split('-').pop());
213
+ context.set('workflowTrace', data.metadata.trc);
214
+ context.set('workflowSpan', data.metadata.spn);
215
+ const workflowResponse = await asyncLocalStorage_1.asyncLocalStorage.run(context, async () => {
216
+ return await workflowFunction.apply(this, workflowInput.arguments);
217
+ });
218
+ return {
219
+ code: 200,
220
+ status: stream_1.StreamStatus.SUCCESS,
221
+ metadata: { ...data.metadata },
222
+ data: { response: workflowResponse }
223
+ };
224
+ }
225
+ catch (err) {
226
+ //todo: (retryable error types)
227
+ return {
228
+ code: 500,
229
+ status: stream_1.StreamStatus.PENDING,
230
+ metadata: { ...data.metadata },
231
+ data: { error: err }
232
+ };
233
+ }
234
+ };
235
+ }
236
+ static async shutdown() {
237
+ for (const [key, value] of WorkerService.instances) {
238
+ const hotMesh = await value;
239
+ await hotMesh.stop();
240
+ }
241
+ }
242
+ }
243
+ _a = WorkerService;
244
+ WorkerService.activityRegistry = {}; //user's activities
245
+ WorkerService.instances = new Map();
246
+ WorkerService.getHotMesh = async (worflowTopic) => {
247
+ if (WorkerService.instances.has(worflowTopic)) {
248
+ return await WorkerService.instances.get(worflowTopic);
249
+ }
250
+ const hotMesh = hotmesh_1.HotMeshService.init({
251
+ appId: worflowTopic,
252
+ engine: { redis: { ...WorkerService.connection } }
253
+ });
254
+ WorkerService.instances.set(worflowTopic, hotMesh);
255
+ await WorkerService.activateWorkflow(await hotMesh, worflowTopic, factory_1.getWorkflowYAML);
256
+ return hotMesh;
257
+ };
258
+ WorkerService.Context = {
259
+ info: () => {
260
+ return {
261
+ workflowId: '',
262
+ workflowTopic: '',
263
+ };
264
+ },
265
+ };
266
+ exports.WorkerService = WorkerService;
@@ -0,0 +1,6 @@
1
+ import { ActivityConfig, ProxyType, WorkflowOptions } from "../../types/durable";
2
+ export declare class WorkflowService {
3
+ static executeChild<T>(options: WorkflowOptions): Promise<T>;
4
+ static proxyActivities<ACT>(options?: ActivityConfig): ProxyType<ACT>;
5
+ static wrapActivity<T>(activityName: string, options?: ActivityConfig): T;
6
+ }