@hotmeshio/hotmesh 0.4.0 → 0.4.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 (283) hide show
  1. package/build/modules/enums.d.ts +110 -0
  2. package/build/modules/enums.js +134 -0
  3. package/build/modules/errors.d.ts +124 -0
  4. package/build/modules/errors.js +191 -0
  5. package/build/modules/key.d.ts +66 -0
  6. package/build/modules/key.js +190 -0
  7. package/build/modules/storage.d.ts +3 -0
  8. package/build/modules/storage.js +5 -0
  9. package/build/modules/utils.d.ts +119 -0
  10. package/build/modules/utils.js +374 -0
  11. package/build/package.json +1 -1
  12. package/build/services/activities/activity.d.ts +104 -0
  13. package/build/services/activities/activity.js +549 -0
  14. package/build/services/activities/await.d.ts +12 -0
  15. package/build/services/activities/await.js +114 -0
  16. package/build/services/activities/cycle.d.ts +19 -0
  17. package/build/services/activities/cycle.js +112 -0
  18. package/build/services/activities/hook.d.ts +27 -0
  19. package/build/services/activities/hook.js +168 -0
  20. package/build/services/activities/index.d.ts +19 -0
  21. package/build/services/activities/index.js +20 -0
  22. package/build/services/activities/interrupt.d.ts +16 -0
  23. package/build/services/activities/interrupt.js +158 -0
  24. package/build/services/activities/signal.d.ts +20 -0
  25. package/build/services/activities/signal.js +134 -0
  26. package/build/services/activities/trigger.d.ts +37 -0
  27. package/build/services/activities/trigger.js +246 -0
  28. package/build/services/activities/worker.d.ts +12 -0
  29. package/build/services/activities/worker.js +106 -0
  30. package/build/services/collator/index.d.ts +111 -0
  31. package/build/services/collator/index.js +293 -0
  32. package/build/services/compiler/deployer.d.ts +40 -0
  33. package/build/services/compiler/deployer.js +488 -0
  34. package/build/services/compiler/index.d.ts +32 -0
  35. package/build/services/compiler/index.js +112 -0
  36. package/build/services/compiler/validator.d.ts +34 -0
  37. package/build/services/compiler/validator.js +147 -0
  38. package/build/services/connector/factory.d.ts +22 -0
  39. package/build/services/connector/factory.js +99 -0
  40. package/build/services/connector/index.d.ts +30 -0
  41. package/build/services/connector/index.js +54 -0
  42. package/build/services/connector/providers/ioredis.d.ts +9 -0
  43. package/build/services/connector/providers/ioredis.js +26 -0
  44. package/build/services/connector/providers/nats.d.ts +9 -0
  45. package/build/services/connector/providers/nats.js +34 -0
  46. package/build/services/connector/providers/postgres.d.ts +20 -0
  47. package/build/services/connector/providers/postgres.js +102 -0
  48. package/build/services/connector/providers/redis.d.ts +9 -0
  49. package/build/services/connector/providers/redis.js +38 -0
  50. package/build/services/engine/index.d.ts +264 -0
  51. package/build/services/engine/index.js +761 -0
  52. package/build/services/exporter/index.d.ts +44 -0
  53. package/build/services/exporter/index.js +126 -0
  54. package/build/services/hotmesh/index.d.ts +483 -0
  55. package/build/services/hotmesh/index.js +622 -0
  56. package/build/services/logger/index.d.ts +16 -0
  57. package/build/services/logger/index.js +54 -0
  58. package/build/services/mapper/index.d.ts +28 -0
  59. package/build/services/mapper/index.js +81 -0
  60. package/build/services/memflow/client.d.ts +108 -0
  61. package/build/services/memflow/client.js +372 -0
  62. package/build/services/memflow/connection.d.ts +23 -0
  63. package/build/services/memflow/connection.js +33 -0
  64. package/build/services/memflow/context.d.ts +143 -0
  65. package/build/services/memflow/context.js +299 -0
  66. package/build/services/memflow/exporter.d.ts +51 -0
  67. package/build/services/memflow/exporter.js +215 -0
  68. package/build/services/memflow/handle.d.ts +90 -0
  69. package/build/services/memflow/handle.js +176 -0
  70. package/build/services/memflow/index.d.ts +116 -0
  71. package/build/services/memflow/index.js +122 -0
  72. package/build/services/memflow/schemas/factory.d.ts +29 -0
  73. package/build/services/memflow/schemas/factory.js +2492 -0
  74. package/build/services/memflow/search.d.ts +142 -0
  75. package/build/services/memflow/search.js +320 -0
  76. package/build/services/memflow/worker.d.ts +124 -0
  77. package/build/services/memflow/worker.js +514 -0
  78. package/build/services/memflow/workflow/all.d.ts +7 -0
  79. package/build/services/memflow/workflow/all.js +15 -0
  80. package/build/services/memflow/workflow/common.d.ts +20 -0
  81. package/build/services/memflow/workflow/common.js +47 -0
  82. package/build/services/memflow/workflow/context.d.ts +6 -0
  83. package/build/services/memflow/workflow/context.js +45 -0
  84. package/build/services/memflow/workflow/contextMethods.d.ts +14 -0
  85. package/build/services/memflow/workflow/contextMethods.js +33 -0
  86. package/build/services/memflow/workflow/didRun.d.ts +7 -0
  87. package/build/services/memflow/workflow/didRun.js +22 -0
  88. package/build/services/memflow/workflow/emit.d.ts +11 -0
  89. package/build/services/memflow/workflow/emit.js +29 -0
  90. package/build/services/memflow/workflow/enrich.d.ts +9 -0
  91. package/build/services/memflow/workflow/enrich.js +17 -0
  92. package/build/services/memflow/workflow/execChild.d.ts +18 -0
  93. package/build/services/memflow/workflow/execChild.js +102 -0
  94. package/build/services/memflow/workflow/execHook.d.ts +65 -0
  95. package/build/services/memflow/workflow/execHook.js +73 -0
  96. package/build/services/memflow/workflow/hook.d.ts +9 -0
  97. package/build/services/memflow/workflow/hook.js +56 -0
  98. package/build/services/memflow/workflow/index.d.ts +74 -0
  99. package/build/services/memflow/workflow/index.js +87 -0
  100. package/build/services/memflow/workflow/interrupt.d.ts +9 -0
  101. package/build/services/memflow/workflow/interrupt.js +24 -0
  102. package/build/services/memflow/workflow/isSideEffectAllowed.d.ts +10 -0
  103. package/build/services/memflow/workflow/isSideEffectAllowed.js +33 -0
  104. package/build/services/memflow/workflow/proxyActivities.d.ts +20 -0
  105. package/build/services/memflow/workflow/proxyActivities.js +97 -0
  106. package/build/services/memflow/workflow/random.d.ts +6 -0
  107. package/build/services/memflow/workflow/random.js +16 -0
  108. package/build/services/memflow/workflow/searchMethods.d.ts +6 -0
  109. package/build/services/memflow/workflow/searchMethods.js +25 -0
  110. package/build/services/memflow/workflow/signal.d.ts +7 -0
  111. package/build/services/memflow/workflow/signal.js +28 -0
  112. package/build/services/memflow/workflow/sleepFor.d.ts +8 -0
  113. package/build/services/memflow/workflow/sleepFor.js +35 -0
  114. package/build/services/memflow/workflow/trace.d.ts +14 -0
  115. package/build/services/memflow/workflow/trace.js +33 -0
  116. package/build/services/memflow/workflow/waitFor.d.ts +8 -0
  117. package/build/services/memflow/workflow/waitFor.js +35 -0
  118. package/build/services/meshcall/index.d.ts +194 -0
  119. package/build/services/meshcall/index.js +452 -0
  120. package/build/services/meshcall/schemas/factory.d.ts +9 -0
  121. package/build/services/meshcall/schemas/factory.js +189 -0
  122. package/build/services/meshdata/index.d.ts +795 -0
  123. package/build/services/meshdata/index.js +1235 -0
  124. package/build/services/meshos/index.d.ts +293 -0
  125. package/build/services/meshos/index.js +547 -0
  126. package/build/services/pipe/functions/array.d.ts +17 -0
  127. package/build/services/pipe/functions/array.js +74 -0
  128. package/build/services/pipe/functions/bitwise.d.ts +9 -0
  129. package/build/services/pipe/functions/bitwise.js +24 -0
  130. package/build/services/pipe/functions/conditional.d.ts +13 -0
  131. package/build/services/pipe/functions/conditional.js +36 -0
  132. package/build/services/pipe/functions/cron.d.ts +12 -0
  133. package/build/services/pipe/functions/cron.js +40 -0
  134. package/build/services/pipe/functions/date.d.ts +58 -0
  135. package/build/services/pipe/functions/date.js +171 -0
  136. package/build/services/pipe/functions/index.d.ts +29 -0
  137. package/build/services/pipe/functions/index.js +30 -0
  138. package/build/services/pipe/functions/json.d.ts +5 -0
  139. package/build/services/pipe/functions/json.js +12 -0
  140. package/build/services/pipe/functions/logical.d.ts +5 -0
  141. package/build/services/pipe/functions/logical.js +12 -0
  142. package/build/services/pipe/functions/math.d.ts +42 -0
  143. package/build/services/pipe/functions/math.js +184 -0
  144. package/build/services/pipe/functions/number.d.ts +21 -0
  145. package/build/services/pipe/functions/number.js +60 -0
  146. package/build/services/pipe/functions/object.d.ts +25 -0
  147. package/build/services/pipe/functions/object.js +81 -0
  148. package/build/services/pipe/functions/string.d.ts +23 -0
  149. package/build/services/pipe/functions/string.js +69 -0
  150. package/build/services/pipe/functions/symbol.d.ts +12 -0
  151. package/build/services/pipe/functions/symbol.js +33 -0
  152. package/build/services/pipe/functions/unary.d.ts +7 -0
  153. package/build/services/pipe/functions/unary.js +18 -0
  154. package/build/services/pipe/index.d.ts +48 -0
  155. package/build/services/pipe/index.js +242 -0
  156. package/build/services/quorum/index.d.ts +90 -0
  157. package/build/services/quorum/index.js +263 -0
  158. package/build/services/reporter/index.d.ts +50 -0
  159. package/build/services/reporter/index.js +348 -0
  160. package/build/services/router/config/index.d.ts +11 -0
  161. package/build/services/router/config/index.js +36 -0
  162. package/build/services/router/consumption/index.d.ts +34 -0
  163. package/build/services/router/consumption/index.js +395 -0
  164. package/build/services/router/error-handling/index.d.ts +8 -0
  165. package/build/services/router/error-handling/index.js +98 -0
  166. package/build/services/router/index.d.ts +57 -0
  167. package/build/services/router/index.js +121 -0
  168. package/build/services/router/lifecycle/index.d.ts +27 -0
  169. package/build/services/router/lifecycle/index.js +80 -0
  170. package/build/services/router/telemetry/index.d.ts +11 -0
  171. package/build/services/router/telemetry/index.js +32 -0
  172. package/build/services/router/throttling/index.d.ts +23 -0
  173. package/build/services/router/throttling/index.js +76 -0
  174. package/build/services/search/factory.d.ts +7 -0
  175. package/build/services/search/factory.js +24 -0
  176. package/build/services/search/index.d.ts +23 -0
  177. package/build/services/search/index.js +10 -0
  178. package/build/services/search/providers/postgres/postgres.d.ts +25 -0
  179. package/build/services/search/providers/postgres/postgres.js +149 -0
  180. package/build/services/search/providers/redis/ioredis.d.ts +19 -0
  181. package/build/services/search/providers/redis/ioredis.js +121 -0
  182. package/build/services/search/providers/redis/redis.d.ts +19 -0
  183. package/build/services/search/providers/redis/redis.js +134 -0
  184. package/build/services/serializer/index.d.ts +42 -0
  185. package/build/services/serializer/index.js +282 -0
  186. package/build/services/store/cache.d.ts +67 -0
  187. package/build/services/store/cache.js +128 -0
  188. package/build/services/store/factory.d.ts +8 -0
  189. package/build/services/store/factory.js +24 -0
  190. package/build/services/store/index.d.ts +89 -0
  191. package/build/services/store/index.js +9 -0
  192. package/build/services/store/providers/postgres/kvsql.d.ts +168 -0
  193. package/build/services/store/providers/postgres/kvsql.js +198 -0
  194. package/build/services/store/providers/postgres/kvtables.d.ts +20 -0
  195. package/build/services/store/providers/postgres/kvtables.js +441 -0
  196. package/build/services/store/providers/postgres/kvtransaction.d.ts +36 -0
  197. package/build/services/store/providers/postgres/kvtransaction.js +248 -0
  198. package/build/services/store/providers/postgres/kvtypes/hash.d.ts +60 -0
  199. package/build/services/store/providers/postgres/kvtypes/hash.js +1287 -0
  200. package/build/services/store/providers/postgres/kvtypes/list.d.ts +33 -0
  201. package/build/services/store/providers/postgres/kvtypes/list.js +194 -0
  202. package/build/services/store/providers/postgres/kvtypes/string.d.ts +20 -0
  203. package/build/services/store/providers/postgres/kvtypes/string.js +115 -0
  204. package/build/services/store/providers/postgres/kvtypes/zset.d.ts +41 -0
  205. package/build/services/store/providers/postgres/kvtypes/zset.js +214 -0
  206. package/build/services/store/providers/postgres/postgres.d.ts +145 -0
  207. package/build/services/store/providers/postgres/postgres.js +1036 -0
  208. package/build/services/store/providers/redis/_base.d.ts +137 -0
  209. package/build/services/store/providers/redis/_base.js +980 -0
  210. package/build/services/store/providers/redis/ioredis.d.ts +20 -0
  211. package/build/services/store/providers/redis/ioredis.js +180 -0
  212. package/build/services/store/providers/redis/redis.d.ts +18 -0
  213. package/build/services/store/providers/redis/redis.js +199 -0
  214. package/build/services/store/providers/store-initializable.d.ts +5 -0
  215. package/build/services/store/providers/store-initializable.js +2 -0
  216. package/build/services/stream/factory.d.ts +8 -0
  217. package/build/services/stream/factory.js +37 -0
  218. package/build/services/stream/index.d.ts +69 -0
  219. package/build/services/stream/index.js +11 -0
  220. package/build/services/stream/providers/nats/nats.d.ts +60 -0
  221. package/build/services/stream/providers/nats/nats.js +225 -0
  222. package/build/services/stream/providers/postgres/kvtables.d.ts +3 -0
  223. package/build/services/stream/providers/postgres/kvtables.js +146 -0
  224. package/build/services/stream/providers/postgres/postgres.d.ts +107 -0
  225. package/build/services/stream/providers/postgres/postgres.js +519 -0
  226. package/build/services/stream/providers/redis/ioredis.d.ts +61 -0
  227. package/build/services/stream/providers/redis/ioredis.js +272 -0
  228. package/build/services/stream/providers/redis/redis.d.ts +61 -0
  229. package/build/services/stream/providers/redis/redis.js +305 -0
  230. package/build/services/stream/providers/stream-initializable.d.ts +4 -0
  231. package/build/services/stream/providers/stream-initializable.js +2 -0
  232. package/build/services/sub/factory.d.ts +7 -0
  233. package/build/services/sub/factory.js +29 -0
  234. package/build/services/sub/index.d.ts +22 -0
  235. package/build/services/sub/index.js +10 -0
  236. package/build/services/sub/providers/nats/nats.d.ts +19 -0
  237. package/build/services/sub/providers/nats/nats.js +105 -0
  238. package/build/services/sub/providers/postgres/postgres.d.ts +19 -0
  239. package/build/services/sub/providers/postgres/postgres.js +92 -0
  240. package/build/services/sub/providers/redis/ioredis.d.ts +17 -0
  241. package/build/services/sub/providers/redis/ioredis.js +81 -0
  242. package/build/services/sub/providers/redis/redis.d.ts +17 -0
  243. package/build/services/sub/providers/redis/redis.js +72 -0
  244. package/build/services/task/index.d.ts +36 -0
  245. package/build/services/task/index.js +206 -0
  246. package/build/services/telemetry/index.d.ts +52 -0
  247. package/build/services/telemetry/index.js +306 -0
  248. package/build/services/worker/index.d.ts +77 -0
  249. package/build/services/worker/index.js +197 -0
  250. package/package.json +1 -1
  251. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -38
  252. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
  253. package/typedoc.json +0 -47
  254. package/types/activity.ts +0 -268
  255. package/types/app.ts +0 -20
  256. package/types/async.ts +0 -6
  257. package/types/cache.ts +0 -1
  258. package/types/collator.ts +0 -9
  259. package/types/error.ts +0 -56
  260. package/types/exporter.ts +0 -102
  261. package/types/hook.ts +0 -44
  262. package/types/hotmesh.ts +0 -314
  263. package/types/index.ts +0 -306
  264. package/types/job.ts +0 -233
  265. package/types/logger.ts +0 -8
  266. package/types/manifest.ts +0 -70
  267. package/types/map.ts +0 -5
  268. package/types/memflow.ts +0 -645
  269. package/types/meshcall.ts +0 -235
  270. package/types/meshdata.ts +0 -278
  271. package/types/ms.d.ts +0 -7
  272. package/types/nats.ts +0 -270
  273. package/types/pipe.ts +0 -90
  274. package/types/postgres.ts +0 -114
  275. package/types/provider.ts +0 -161
  276. package/types/quorum.ts +0 -167
  277. package/types/redis.ts +0 -404
  278. package/types/serializer.ts +0 -40
  279. package/types/stats.ts +0 -117
  280. package/types/stream.ts +0 -231
  281. package/types/task.ts +0 -7
  282. package/types/telemetry.ts +0 -16
  283. package/types/transition.ts +0 -20
@@ -0,0 +1,452 @@
1
+ "use strict";
2
+ var _a;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.MeshCall = void 0;
5
+ const hotmesh_1 = require("../hotmesh");
6
+ const enums_1 = require("../../modules/enums");
7
+ const utils_1 = require("../../modules/utils");
8
+ const key_1 = require("../../modules/key");
9
+ const cron_1 = require("../pipe/functions/cron");
10
+ const factory_1 = require("./schemas/factory");
11
+ /**
12
+ * MeshCall connects any function as an idempotent endpoint.
13
+ * Call functions from anywhere on the network connected to the
14
+ * target backend (Postgres, Redis/ValKey, NATS, etc). Function
15
+ * responses are cacheable and invocations can be scheduled to
16
+ * run as idempotent cron jobs (this one runs nightly at midnight
17
+ * and uses Postgres as the backend provider).
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * import { Client as Postgres } from 'pg';
22
+ * import { MeshCall } from '@hotmesh/meshcall';
23
+ *
24
+ * MeshCall.cron({
25
+ * topic: 'my.cron.function',
26
+ * connection: {
27
+ * class: Postgres,
28
+ * options: { connectionString: 'postgresql://usr:pwd@localhost:5432/db' }
29
+ * },
30
+ * callback: async () => {
31
+ * //your code here...anything goes
32
+ * },
33
+ * options: { id: 'myDailyCron123', interval: '0 0 * * *' }
34
+ * });
35
+ * ```
36
+ */
37
+ class MeshCall {
38
+ /**
39
+ * @private
40
+ */
41
+ constructor() { }
42
+ /**
43
+ * iterates cached worker/engine instances to locate the first match
44
+ * with the provided namespace and connection options
45
+ * @private
46
+ */
47
+ static async findFirstMatching(targets, namespace = key_1.HMNS, config, options = {}) {
48
+ for (const [id, hotMeshInstance] of targets) {
49
+ const hotMesh = await hotMeshInstance;
50
+ const appId = hotMesh.engine.appId;
51
+ if (appId === namespace) {
52
+ if (id.startsWith(MeshCall.hashOptions(config))) {
53
+ if (Boolean(options.readonly) == Boolean(hotMesh.engine.router.readonly)) {
54
+ return hotMeshInstance;
55
+ }
56
+ }
57
+ }
58
+ }
59
+ }
60
+ /**
61
+ * @private
62
+ */
63
+ static async verifyWorkflowActive(hotMesh, appId = key_1.HMNS, count = 0) {
64
+ const app = await hotMesh.engine.store.getApp(appId);
65
+ const appVersion = app?.version;
66
+ if (isNaN(appVersion)) {
67
+ if (count > 10) {
68
+ throw new Error('Workflow failed to activate');
69
+ }
70
+ await (0, utils_1.sleepFor)(enums_1.HMSH_QUORUM_DELAY_MS * 2);
71
+ return await MeshCall.verifyWorkflowActive(hotMesh, appId, count + 1);
72
+ }
73
+ return true;
74
+ }
75
+ /**
76
+ * @private
77
+ */
78
+ static async activateWorkflow(hotMesh, appId = key_1.HMNS, version = factory_1.VERSION) {
79
+ const app = await hotMesh.engine.store.getApp(appId);
80
+ const appVersion = app?.version;
81
+ if (appVersion === version && !app.active) {
82
+ try {
83
+ await hotMesh.activate(version);
84
+ }
85
+ catch (error) {
86
+ hotMesh.engine.logger.error('meshcall-client-activate-err', {
87
+ error,
88
+ });
89
+ throw error;
90
+ }
91
+ }
92
+ else if (isNaN(Number(appVersion)) || appVersion < version) {
93
+ try {
94
+ await hotMesh.deploy((0, factory_1.getWorkflowYAML)(appId));
95
+ await hotMesh.activate(version);
96
+ }
97
+ catch (error) {
98
+ hotMesh.engine.logger.error('meshcall-client-deploy-activate-err', {
99
+ error,
100
+ });
101
+ throw error;
102
+ }
103
+ }
104
+ }
105
+ /**
106
+ * Returns a cached worker instance or creates a new one
107
+ * @private
108
+ */
109
+ static async getInstance(namespace, providerConfig, options = {}) {
110
+ let hotMeshInstance;
111
+ if (!options.readonly) {
112
+ hotMeshInstance = await MeshCall.findFirstMatching(MeshCall.workers, namespace, providerConfig, options);
113
+ }
114
+ if (!hotMeshInstance) {
115
+ hotMeshInstance = await MeshCall.findFirstMatching(MeshCall.engines, namespace, providerConfig, options);
116
+ if (!hotMeshInstance) {
117
+ hotMeshInstance = (await MeshCall.getHotMeshClient(namespace, providerConfig, options));
118
+ }
119
+ }
120
+ return hotMeshInstance;
121
+ }
122
+ /**
123
+ * connection re-use is important when making repeated calls, but
124
+ * only if the connection options are an exact match. this method
125
+ * hashes the connection options to ensure that the same connection
126
+ */
127
+ static hashOptions(connection) {
128
+ if ('options' in connection) {
129
+ //shorthand format
130
+ return (0, utils_1.hashOptions)(connection.options);
131
+ }
132
+ else {
133
+ //longhand format (sub, store, stream, pub, search)
134
+ const response = [];
135
+ for (const p in connection) {
136
+ if (connection[p].options) {
137
+ response.push((0, utils_1.hashOptions)(connection[p].options));
138
+ }
139
+ }
140
+ return response.join('');
141
+ }
142
+ }
143
+ /**
144
+ * Connects and links a worker function to the mesh
145
+ * @example
146
+ * ```typescript
147
+ * import { Client as Postgres } from 'pg';
148
+ * import { MeshCall } from '@hotmesh/meshcall';
149
+ *
150
+ * MeshCall.connect({
151
+ * topic: 'my.function',
152
+ * connection: {
153
+ * class: Postgres,
154
+ * options: { connectionString: 'postgresql://usr:pwd@localhost:5432/db' }
155
+ * },
156
+ * callback: async (arg1: any) => {
157
+ * //your code here...
158
+ * }
159
+ * });
160
+ * ```
161
+ */
162
+ static async connect(params) {
163
+ const targetNamespace = params.namespace ?? key_1.HMNS;
164
+ const optionsHash = MeshCall.hashOptions(utils_1.polyfill.providerConfig(params));
165
+ const targetTopic = `${optionsHash}.${targetNamespace}.${params.topic}`;
166
+ const connection = utils_1.polyfill.providerConfig(params);
167
+ const hotMeshWorker = await hotmesh_1.HotMesh.init({
168
+ guid: params.guid,
169
+ logLevel: params.logLevel ?? enums_1.HMSH_LOGLEVEL,
170
+ appId: params.namespace ?? key_1.HMNS,
171
+ engine: { connection },
172
+ workers: [
173
+ {
174
+ topic: params.topic,
175
+ connection,
176
+ callback: async function (input) {
177
+ const response = await params.callback.apply(this, input.data.args);
178
+ return {
179
+ metadata: { ...input.metadata },
180
+ data: { response },
181
+ };
182
+ },
183
+ },
184
+ ],
185
+ });
186
+ MeshCall.workers.set(targetTopic, hotMeshWorker);
187
+ await MeshCall.activateWorkflow(hotMeshWorker, targetNamespace);
188
+ return hotMeshWorker;
189
+ }
190
+ /**
191
+ * Calls a function and returns the response.
192
+ *
193
+ * @template U - the return type of the linked worker function
194
+ *
195
+ * @example
196
+ * ```typescript
197
+ * const response = await MeshCall.exec({
198
+ * topic: 'my.function',
199
+ * args: [{ my: 'args' }],
200
+ * connection: {
201
+ * class: Postgres,
202
+ * options: { connectionString: 'postgresql://usr:pwd@localhost:5432/db' }
203
+ * }
204
+ * });
205
+ * ```
206
+ */
207
+ static async exec(params) {
208
+ const TOPIC = `${params.namespace ?? key_1.HMNS}.call`;
209
+ const hotMeshInstance = await MeshCall.getInstance(params.namespace, utils_1.polyfill.providerConfig(params));
210
+ let id = params.options?.id;
211
+ if (id) {
212
+ if (params.options?.flush) {
213
+ await hotMeshInstance.scrub(id);
214
+ }
215
+ else if (params.options?.ttl) {
216
+ //check cache
217
+ try {
218
+ const cached = await hotMeshInstance.getState(TOPIC, id);
219
+ if (cached) {
220
+ //todo: check if present; await if not (subscribe)
221
+ return cached.data.response;
222
+ }
223
+ }
224
+ catch (error) {
225
+ //just swallow error; it means the cache is empty (no doc by that id)
226
+ }
227
+ }
228
+ }
229
+ else {
230
+ id = hotmesh_1.HotMesh.guid();
231
+ }
232
+ let expire = 1;
233
+ if (params.options?.ttl) {
234
+ expire = (0, utils_1.s)(params.options.ttl);
235
+ }
236
+ const jobOutput = await hotMeshInstance.pubsub(TOPIC, { id, expire, topic: params.topic, args: params.args }, null, 30000);
237
+ return jobOutput?.data?.response;
238
+ }
239
+ /**
240
+ * Clears a cached function response.
241
+ *
242
+ * @example
243
+ * ```typescript
244
+ * import { Client as Postgres } from 'pg';
245
+ * import { MeshCall } from '@hotmesh/meshcall';
246
+ *
247
+ * MeshCall.flush({
248
+ * topic: 'my.function',
249
+ * connection: {
250
+ * class: Postgres,
251
+ * options: { connectionString: 'postgresql://usr:pwd@localhost:5432/db' }
252
+ * },
253
+ * options: { id: 'myCachedExecFunctionId' }
254
+ * });
255
+ * ```
256
+ */
257
+ static async flush(params) {
258
+ const hotMeshInstance = await MeshCall.getInstance(params.namespace, utils_1.polyfill.providerConfig(params));
259
+ await hotMeshInstance.scrub(params.id ?? params?.options?.id);
260
+ }
261
+ /**
262
+ * Schedules a cron job to run at a specified interval
263
+ * with optional args. Provided arguments are passed to the
264
+ * callback function each time the cron job runs. The `id`
265
+ * option is used to uniquely identify the cron job, allowing
266
+ * it to be interrupted at any time.
267
+ *
268
+ * @example
269
+ * ```typescript
270
+ * import { Client as Postgres } from 'pg';
271
+ * import { MeshCall } from '@hotmesh/meshcall';
272
+ *
273
+ * MeshCall.cron({
274
+ * topic: 'my.cron.function',
275
+ * args: ['arg1', 'arg2'], //optionally pass args
276
+ * connection: {
277
+ * class: Postgres,
278
+ * options: { connectionString: 'postgresql://usr:pwd@localhost:5432/db' }
279
+ * },
280
+ * callback: async (arg1: any, arg2: any) => {
281
+ * //your code here...
282
+ * },
283
+ * options: { id: 'myDailyCron123', interval: '0 0 * * *' }
284
+ * });
285
+ * ```
286
+ */
287
+ static async cron(params) {
288
+ let hotMeshInstance;
289
+ let readonly = true;
290
+ if (params.callback) {
291
+ //always connect cron worker if provided
292
+ hotMeshInstance = await MeshCall.connect({
293
+ logLevel: params.logLevel,
294
+ guid: params.guid,
295
+ topic: params.topic,
296
+ connection: utils_1.polyfill.providerConfig(params),
297
+ callback: params.callback,
298
+ namespace: params.namespace,
299
+ });
300
+ readonly = false;
301
+ }
302
+ else {
303
+ //this is a readonly cron connection which means
304
+ //it is only being created to connect as a readonly member
305
+ //of the mesh network that the cron is running on. it
306
+ //can start a job, but it cannot run the job itself in RO mode.
307
+ }
308
+ //configure job inputs
309
+ const TOPIC = `${params.namespace ?? key_1.HMNS}.cron`;
310
+ const maxCycles = params.options.maxCycles ?? 100000;
311
+ let interval = enums_1.HMSH_FIDELITY_SECONDS;
312
+ let delay;
313
+ let cron;
314
+ if ((0, utils_1.isValidCron)(params.options.interval)) {
315
+ //cron syntax
316
+ cron = params.options.interval;
317
+ const nextDelay = new cron_1.CronHandler().nextDelay(cron);
318
+ delay = nextDelay > 0 ? nextDelay : undefined;
319
+ }
320
+ else {
321
+ const seconds = (0, utils_1.s)(params.options.interval);
322
+ interval = Math.max(seconds, enums_1.HMSH_FIDELITY_SECONDS);
323
+ delay = params.options.delay ? (0, utils_1.s)(params.options.delay) : undefined;
324
+ }
325
+ try {
326
+ if (!hotMeshInstance) {
327
+ //get or create a read-only engine instance to start the cron
328
+ hotMeshInstance = await MeshCall.getInstance(params.namespace, utils_1.polyfill.providerConfig(params), { readonly, guid: params.guid });
329
+ await MeshCall.createStream(hotMeshInstance, params.topic, params.namespace);
330
+ }
331
+ //spawn the job (ok if it's a duplicate)
332
+ await hotMeshInstance.pub(TOPIC, {
333
+ id: params.options.id,
334
+ topic: params.topic,
335
+ args: params.args,
336
+ interval,
337
+ cron,
338
+ maxCycles,
339
+ delay,
340
+ });
341
+ return true;
342
+ }
343
+ catch (error) {
344
+ if (error.message.includes(`Duplicate job: ${params.options.id}`)) {
345
+ return false;
346
+ }
347
+ throw error;
348
+ }
349
+ }
350
+ /**
351
+ * Interrupts a running cron job. Returns `true` if the job
352
+ * was successfully interrupted, or `false` if the job was not
353
+ * found.
354
+ *
355
+ * @example
356
+ * ```typescript
357
+ * import { Client as Postgres } from 'pg';
358
+ * import { MeshCall } from '@hotmesh/meshcall';
359
+ *
360
+ * MeshCall.interrupt({
361
+ * topic: 'my.cron.function',
362
+ * connection: {
363
+ * class: Postgres,
364
+ * options: { connectionString: 'postgresql://usr:pwd@localhost:5432/db' }
365
+ * },
366
+ * options: { id: 'myDailyCron123' }
367
+ * });
368
+ * ```
369
+ */
370
+ static async interrupt(params) {
371
+ const hotMeshInstance = await MeshCall.getInstance(params.namespace, utils_1.polyfill.providerConfig(params));
372
+ try {
373
+ await hotMeshInstance.interrupt(`${params.namespace ?? key_1.HMNS}.cron`, params.options.id, { throw: false, expire: 1 });
374
+ }
375
+ catch (error) {
376
+ //job doesn't exist; is already stopped
377
+ return false;
378
+ }
379
+ return true;
380
+ }
381
+ /**
382
+ * Shuts down all meshcall instances. Call this method
383
+ * from the SIGTERM handler in your application.
384
+ */
385
+ static async shutdown() {
386
+ for (const [_, hotMeshInstance] of MeshCall.workers) {
387
+ (await hotMeshInstance).stop();
388
+ }
389
+ for (const [_, hotMeshInstance] of MeshCall.engines) {
390
+ (await hotMeshInstance).stop();
391
+ }
392
+ await hotmesh_1.HotMesh.stop();
393
+ }
394
+ }
395
+ exports.MeshCall = MeshCall;
396
+ _a = MeshCall;
397
+ /**
398
+ * @private
399
+ */
400
+ MeshCall.workers = new Map();
401
+ /**
402
+ * @private
403
+ */
404
+ MeshCall.engines = new Map();
405
+ /**
406
+ * @private
407
+ */
408
+ MeshCall.connections = new Map();
409
+ /**
410
+ * @private
411
+ */
412
+ MeshCall.getHotMeshClient = async (namespace, connection, options = {}) => {
413
+ //namespace isolation requires the connection options to be hashed
414
+ //as multiple intersecting databases can be used by the same service
415
+ const optionsHash = MeshCall.hashOptions(connection);
416
+ const targetNS = namespace ?? key_1.HMNS;
417
+ const connectionNS = `${optionsHash}.${targetNS}`;
418
+ if (MeshCall.engines.has(connectionNS)) {
419
+ const hotMeshClient = await MeshCall.engines.get(connectionNS);
420
+ await _a.verifyWorkflowActive(hotMeshClient, targetNS);
421
+ return hotMeshClient;
422
+ }
423
+ //create and cache an instance
424
+ const hotMeshClient = hotmesh_1.HotMesh.init({
425
+ guid: options.guid,
426
+ appId: targetNS,
427
+ logLevel: enums_1.HMSH_LOGLEVEL,
428
+ engine: {
429
+ connection,
430
+ readonly: options.readonly,
431
+ },
432
+ });
433
+ MeshCall.engines.set(connectionNS, hotMeshClient);
434
+ await _a.activateWorkflow(await hotMeshClient, targetNS);
435
+ return hotMeshClient;
436
+ };
437
+ /**
438
+ * Creates a stream where messages can be published to ensure there is a
439
+ * channel in place when the message arrives (a race condition for those
440
+ * platforms without implicit topic setup).
441
+ * @private
442
+ */
443
+ MeshCall.createStream = async (hotMeshClient, workflowTopic, namespace) => {
444
+ const params = { appId: namespace ?? key_1.HMNS, topic: workflowTopic };
445
+ const streamKey = hotMeshClient.engine.store.mintKey(key_1.KeyType.STREAMS, params);
446
+ try {
447
+ await hotMeshClient.engine.stream.createConsumerGroup(streamKey, 'WORKER');
448
+ }
449
+ catch (err) {
450
+ //ignore if already exists
451
+ }
452
+ };
@@ -0,0 +1,9 @@
1
+ export declare const VERSION = "2";
2
+ /**
3
+ * Provides the YAML necessary to create a workflow for the `MeshCall` service.
4
+ * The `appId` parameter is optional and defaults to the HMNS constant ('hmsh').
5
+ *
6
+ * The version is a string as it supports semantic versioning. It is also optional
7
+ * and defaults to '1'.
8
+ */
9
+ export declare const getWorkflowYAML: (appId?: string, version?: string) => string;
@@ -0,0 +1,189 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getWorkflowYAML = exports.VERSION = void 0;
4
+ const key_1 = require("../../../modules/key");
5
+ exports.VERSION = '2';
6
+ /**
7
+ * Provides the YAML necessary to create a workflow for the `MeshCall` service.
8
+ * The `appId` parameter is optional and defaults to the HMNS constant ('hmsh').
9
+ *
10
+ * The version is a string as it supports semantic versioning. It is also optional
11
+ * and defaults to '1'.
12
+ */
13
+ const getWorkflowYAML = (appId = key_1.HMNS, version = exports.VERSION) => {
14
+ return `app:
15
+ id: ${appId}
16
+ version: '${version}'
17
+ graphs:
18
+ - subscribes: ${appId}.call
19
+
20
+ expire: '{trigger.output.data.expire}'
21
+
22
+ input:
23
+ schema:
24
+ type: object
25
+ properties:
26
+ id:
27
+ type: string
28
+ description: unique id for this workflow
29
+ expire:
30
+ type: number
31
+ description: time in seconds to expire the completed job and remove it from the cache
32
+ topic:
33
+ type: string
34
+ description: topic assigned to locate the worker
35
+ args:
36
+ type: array
37
+ description: arguments to pass to the worker function
38
+ items:
39
+ type: any
40
+
41
+ output:
42
+ schema:
43
+ type: object
44
+ properties:
45
+ response:
46
+ type: any
47
+
48
+ activities:
49
+ trigger:
50
+ type: trigger
51
+
52
+ stats:
53
+ id: '{$self.input.data.id}'
54
+
55
+ worker:
56
+ type: worker
57
+ topic: '{trigger.output.data.topic}'
58
+ input:
59
+ schema:
60
+ type: object
61
+ properties:
62
+ args:
63
+ type: any
64
+ maps:
65
+ args: '{trigger.output.data.args}'
66
+ output:
67
+ schema:
68
+ type: object
69
+ properties:
70
+ response:
71
+ type: any
72
+ job:
73
+ maps:
74
+ response: '{$self.output.data.response}'
75
+
76
+ transitions:
77
+ trigger:
78
+ - to: worker
79
+
80
+ - subscribes: ${appId}.cron
81
+
82
+ input:
83
+ schema:
84
+ type: object
85
+ properties:
86
+ id:
87
+ type: string
88
+ description: unique id for this workflow
89
+ delay:
90
+ type: number
91
+ description: time in seconds to sleep before invoking the first cycle
92
+ interval:
93
+ type: number
94
+ description: time in seconds to sleep before the next cycle (also min interval in seconds if cron is provided)
95
+ cron:
96
+ type: string
97
+ description: cron expression to determine the next cycle (takes precedence over interval)
98
+ topic:
99
+ type: string
100
+ description: topic assigned to locate the worker
101
+ args:
102
+ type: array
103
+ description: arguments to pass to the worker function
104
+ items:
105
+ type: any
106
+ maxCycles:
107
+ type: number
108
+ description: maximum number of cycles to run before stopping
109
+
110
+ output:
111
+ schema:
112
+ type: object
113
+ properties:
114
+ response:
115
+ type: any
116
+
117
+ activities:
118
+ trigger_cron:
119
+ type: trigger
120
+ stats:
121
+ id: '{$self.input.data.id}'
122
+
123
+ cycle_hook_cron:
124
+ type: hook
125
+ output:
126
+ schema:
127
+ type: object
128
+ properties:
129
+ sleepSeconds:
130
+ type: number
131
+ iterationCount:
132
+ type: number
133
+ maps:
134
+ sleepSeconds:
135
+ '@pipe':
136
+ - ['{trigger_cron.output.data.delay}', '{@symbol.undefined}']
137
+ - ['{@conditional.nullish}']
138
+ iterationCount: 1
139
+
140
+ sleep_cron:
141
+ type: hook
142
+ sleep: '{cycle_hook_cron.output.data.sleepSeconds}'
143
+
144
+ worker_cron:
145
+ type: worker
146
+ topic: '{trigger_cron.output.data.topic}'
147
+ input:
148
+ schema:
149
+ type: object
150
+ properties:
151
+ args:
152
+ type: any
153
+ maps:
154
+ args: '{trigger_cron.output.data.args}'
155
+
156
+ cycle_cron:
157
+ type: cycle
158
+ ancestor: cycle_hook_cron
159
+ input:
160
+ maps:
161
+ sleepSeconds:
162
+ '@pipe':
163
+ - ['{trigger_cron.output.data.cron}']
164
+ - ['{@cron.nextDelay}', '{trigger_cron.output.data.interval}']
165
+ - ['{@math.max}']
166
+ iterationCount:
167
+ '@pipe':
168
+ - ['{cycle_hook_cron.output.data.iterationCount}', 1]
169
+ - ['{@math.add}']
170
+
171
+ transitions:
172
+ trigger_cron:
173
+ - to: cycle_hook_cron
174
+ cycle_hook_cron:
175
+ - to: sleep_cron
176
+ sleep_cron:
177
+ - to: worker_cron
178
+ worker_cron:
179
+ - to: cycle_cron
180
+ conditions:
181
+ match:
182
+ - expected: true
183
+ actual:
184
+ '@pipe':
185
+ - ['{cycle_hook_cron.output.data.iterationCount}', '{trigger_cron.output.data.maxCycles}']
186
+ - ['{@conditional.less_than}']
187
+ `;
188
+ };
189
+ exports.getWorkflowYAML = getWorkflowYAML;