@hotmeshio/hotmesh 0.12.1 → 0.14.0

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 (202) hide show
  1. package/README.md +18 -22
  2. package/build/modules/enums.d.ts +60 -5
  3. package/build/modules/enums.js +62 -7
  4. package/build/modules/errors.d.ts +15 -2
  5. package/build/modules/errors.js +17 -1
  6. package/build/modules/storage.d.ts +1 -0
  7. package/build/modules/storage.js +2 -1
  8. package/build/package.json +8 -2
  9. package/build/services/activities/activity/context.d.ts +22 -0
  10. package/build/services/activities/activity/context.js +76 -0
  11. package/build/services/activities/activity/index.d.ts +116 -0
  12. package/build/services/activities/activity/index.js +299 -0
  13. package/build/services/activities/activity/mapping.d.ts +12 -0
  14. package/build/services/activities/activity/mapping.js +63 -0
  15. package/build/services/activities/activity/process.d.ts +28 -0
  16. package/build/services/activities/activity/process.js +100 -0
  17. package/build/services/activities/activity/protocol.d.ts +39 -0
  18. package/build/services/activities/activity/protocol.js +151 -0
  19. package/build/services/activities/activity/state.d.ts +40 -0
  20. package/build/services/activities/activity/state.js +143 -0
  21. package/build/services/activities/activity/transition.d.ts +23 -0
  22. package/build/services/activities/activity/transition.js +71 -0
  23. package/build/services/activities/activity/verify.d.ts +22 -0
  24. package/build/services/activities/activity/verify.js +85 -0
  25. package/build/services/activities/await.d.ts +1 -4
  26. package/build/services/activities/await.js +2 -36
  27. package/build/services/activities/cycle.d.ts +1 -11
  28. package/build/services/activities/cycle.js +3 -46
  29. package/build/services/activities/hook.d.ts +2 -11
  30. package/build/services/activities/hook.js +30 -50
  31. package/build/services/activities/interrupt.d.ts +2 -4
  32. package/build/services/activities/interrupt.js +4 -38
  33. package/build/services/activities/signal.d.ts +1 -11
  34. package/build/services/activities/signal.js +3 -48
  35. package/build/services/activities/trigger.d.ts +1 -3
  36. package/build/services/activities/trigger.js +0 -3
  37. package/build/services/activities/worker.d.ts +3 -6
  38. package/build/services/activities/worker.js +4 -40
  39. package/build/services/connector/factory.d.ts +6 -0
  40. package/build/services/connector/factory.js +24 -0
  41. package/build/services/dba/index.d.ts +14 -4
  42. package/build/services/dba/index.js +57 -18
  43. package/build/services/durable/activity.d.ts +30 -0
  44. package/build/services/durable/activity.js +46 -0
  45. package/build/services/durable/client.d.ts +26 -31
  46. package/build/services/durable/client.js +26 -31
  47. package/build/services/durable/connection.d.ts +13 -7
  48. package/build/services/durable/connection.js +13 -7
  49. package/build/services/durable/exporter.d.ts +2 -2
  50. package/build/services/durable/exporter.js +27 -12
  51. package/build/services/durable/handle.d.ts +59 -41
  52. package/build/services/durable/handle.js +61 -41
  53. package/build/services/durable/index.d.ts +152 -283
  54. package/build/services/durable/index.js +161 -289
  55. package/build/services/durable/interceptor.d.ts +43 -33
  56. package/build/services/durable/interceptor.js +59 -39
  57. package/build/services/durable/schemas/factory.d.ts +2 -3
  58. package/build/services/durable/schemas/factory.js +180 -30
  59. package/build/services/durable/telemetry.d.ts +80 -0
  60. package/build/services/durable/telemetry.js +137 -0
  61. package/build/services/durable/worker.d.ts +100 -21
  62. package/build/services/durable/worker.js +314 -60
  63. package/build/services/durable/workflow/all.d.ts +1 -1
  64. package/build/services/durable/workflow/all.js +1 -1
  65. package/build/services/durable/workflow/cancellationScope.d.ts +104 -0
  66. package/build/services/durable/workflow/cancellationScope.js +139 -0
  67. package/build/services/durable/workflow/common.d.ts +5 -4
  68. package/build/services/durable/workflow/common.js +6 -1
  69. package/build/services/durable/workflow/{waitFor.d.ts → condition.d.ts} +9 -8
  70. package/build/services/durable/workflow/{waitFor.js → condition.js} +44 -11
  71. package/build/services/durable/workflow/continueAsNew.d.ts +65 -0
  72. package/build/services/durable/workflow/continueAsNew.js +92 -0
  73. package/build/services/durable/workflow/didRun.d.ts +2 -2
  74. package/build/services/durable/workflow/didRun.js +4 -4
  75. package/build/services/durable/workflow/enrich.d.ts +5 -0
  76. package/build/services/durable/workflow/enrich.js +5 -0
  77. package/build/services/durable/workflow/entityMethods.d.ts +7 -0
  78. package/build/services/durable/workflow/entityMethods.js +7 -0
  79. package/build/services/durable/workflow/execHook.js +3 -3
  80. package/build/services/durable/workflow/execHookBatch.js +2 -2
  81. package/build/services/durable/workflow/{execChild.d.ts → executeChild.d.ts} +4 -40
  82. package/build/services/durable/workflow/{execChild.js → executeChild.js} +36 -45
  83. package/build/services/durable/workflow/hook.d.ts +1 -1
  84. package/build/services/durable/workflow/hook.js +4 -3
  85. package/build/services/durable/workflow/index.d.ts +45 -50
  86. package/build/services/durable/workflow/index.js +46 -51
  87. package/build/services/durable/workflow/interruption.d.ts +7 -6
  88. package/build/services/durable/workflow/interruption.js +11 -7
  89. package/build/services/durable/workflow/patched.d.ts +72 -0
  90. package/build/services/durable/workflow/patched.js +110 -0
  91. package/build/services/durable/workflow/proxyActivities.d.ts +7 -7
  92. package/build/services/durable/workflow/proxyActivities.js +51 -15
  93. package/build/services/durable/workflow/searchMethods.d.ts +7 -0
  94. package/build/services/durable/workflow/searchMethods.js +7 -0
  95. package/build/services/durable/workflow/signal.d.ts +4 -4
  96. package/build/services/durable/workflow/signal.js +4 -4
  97. package/build/services/durable/workflow/{sleepFor.d.ts → sleep.d.ts} +7 -7
  98. package/build/services/durable/workflow/{sleepFor.js → sleep.js} +39 -10
  99. package/build/services/durable/workflow/terminate.d.ts +55 -0
  100. package/build/services/durable/workflow/{interrupt.js → terminate.js} +21 -21
  101. package/build/services/durable/workflow/trace.js +2 -2
  102. package/build/services/durable/workflow/uuid4.d.ts +14 -0
  103. package/build/services/durable/workflow/uuid4.js +39 -0
  104. package/build/services/durable/workflow/{context.d.ts → workflowInfo.d.ts} +5 -5
  105. package/build/services/durable/workflow/{context.js → workflowInfo.js} +7 -7
  106. package/build/services/engine/compiler.d.ts +19 -0
  107. package/build/services/engine/compiler.js +20 -0
  108. package/build/services/engine/completion.d.ts +46 -0
  109. package/build/services/engine/completion.js +145 -0
  110. package/build/services/engine/dispatch.d.ts +24 -0
  111. package/build/services/engine/dispatch.js +98 -0
  112. package/build/services/engine/index.d.ts +49 -81
  113. package/build/services/engine/index.js +175 -573
  114. package/build/services/engine/init.d.ts +42 -0
  115. package/build/services/engine/init.js +74 -0
  116. package/build/services/engine/pubsub.d.ts +50 -0
  117. package/build/services/engine/pubsub.js +118 -0
  118. package/build/services/engine/reporting.d.ts +20 -0
  119. package/build/services/engine/reporting.js +38 -0
  120. package/build/services/engine/schema.d.ts +23 -0
  121. package/build/services/engine/schema.js +62 -0
  122. package/build/services/engine/signal.d.ts +57 -0
  123. package/build/services/engine/signal.js +117 -0
  124. package/build/services/engine/state.d.ts +35 -0
  125. package/build/services/engine/state.js +61 -0
  126. package/build/services/engine/version.d.ts +31 -0
  127. package/build/services/engine/version.js +73 -0
  128. package/build/services/hotmesh/deployment.d.ts +21 -0
  129. package/build/services/hotmesh/deployment.js +25 -0
  130. package/build/services/hotmesh/index.d.ts +142 -533
  131. package/build/services/hotmesh/index.js +223 -674
  132. package/build/services/hotmesh/init.d.ts +42 -0
  133. package/build/services/hotmesh/init.js +93 -0
  134. package/build/services/hotmesh/jobs.d.ts +67 -0
  135. package/build/services/hotmesh/jobs.js +99 -0
  136. package/build/services/hotmesh/pubsub.d.ts +38 -0
  137. package/build/services/hotmesh/pubsub.js +54 -0
  138. package/build/services/hotmesh/quorum.d.ts +30 -0
  139. package/build/services/hotmesh/quorum.js +62 -0
  140. package/build/services/hotmesh/validation.d.ts +6 -0
  141. package/build/services/hotmesh/validation.js +28 -0
  142. package/build/services/quorum/index.js +1 -0
  143. package/build/services/router/consumption/index.d.ts +11 -5
  144. package/build/services/router/consumption/index.js +24 -17
  145. package/build/services/router/error-handling/index.d.ts +2 -2
  146. package/build/services/router/error-handling/index.js +14 -14
  147. package/build/services/router/index.d.ts +1 -1
  148. package/build/services/router/index.js +2 -2
  149. package/build/services/serializer/index.d.ts +22 -0
  150. package/build/services/serializer/index.js +39 -1
  151. package/build/services/store/index.d.ts +1 -0
  152. package/build/services/store/providers/postgres/exporter-sql.d.ts +2 -2
  153. package/build/services/store/providers/postgres/exporter-sql.js +4 -4
  154. package/build/services/store/providers/postgres/kvtables.js +7 -6
  155. package/build/services/store/providers/postgres/kvtypes/hash/basic.js +67 -52
  156. package/build/services/store/providers/postgres/kvtypes/hash/jsonb.js +87 -72
  157. package/build/services/store/providers/postgres/kvtypes/hash/udata.js +106 -79
  158. package/build/services/store/providers/postgres/kvtypes/hash/utils.d.ts +16 -0
  159. package/build/services/store/providers/postgres/kvtypes/hash/utils.js +29 -16
  160. package/build/services/store/providers/postgres/postgres.d.ts +1 -0
  161. package/build/services/store/providers/postgres/postgres.js +14 -4
  162. package/build/services/stream/factory.d.ts +3 -1
  163. package/build/services/stream/factory.js +2 -2
  164. package/build/services/stream/index.d.ts +1 -0
  165. package/build/services/stream/providers/nats/nats.d.ts +1 -0
  166. package/build/services/stream/providers/nats/nats.js +1 -0
  167. package/build/services/stream/providers/postgres/credentials.d.ts +56 -0
  168. package/build/services/stream/providers/postgres/credentials.js +129 -0
  169. package/build/services/stream/providers/postgres/kvtables.js +18 -0
  170. package/build/services/stream/providers/postgres/messages.js +7 -7
  171. package/build/services/stream/providers/postgres/notifications.js +16 -2
  172. package/build/services/stream/providers/postgres/postgres.d.ts +7 -0
  173. package/build/services/stream/providers/postgres/postgres.js +35 -4
  174. package/build/services/stream/providers/postgres/procedures.d.ts +21 -0
  175. package/build/services/stream/providers/postgres/procedures.js +213 -0
  176. package/build/services/stream/providers/postgres/secured.d.ts +34 -0
  177. package/build/services/stream/providers/postgres/secured.js +146 -0
  178. package/build/services/stream/providers/postgres/stats.d.ts +1 -0
  179. package/build/services/stream/providers/postgres/stats.js +1 -0
  180. package/build/services/stream/registry.d.ts +1 -1
  181. package/build/services/stream/registry.js +5 -2
  182. package/build/services/telemetry/index.d.ts +10 -1
  183. package/build/services/telemetry/index.js +40 -7
  184. package/build/services/worker/credentials.d.ts +51 -0
  185. package/build/services/worker/credentials.js +87 -0
  186. package/build/services/worker/index.d.ts +2 -2
  187. package/build/services/worker/index.js +7 -6
  188. package/build/types/codec.d.ts +84 -0
  189. package/build/types/codec.js +2 -0
  190. package/build/types/dba.d.ts +39 -3
  191. package/build/types/durable.d.ts +123 -25
  192. package/build/types/error.d.ts +10 -0
  193. package/build/types/exporter.d.ts +1 -1
  194. package/build/types/hotmesh.d.ts +67 -4
  195. package/build/types/index.d.ts +2 -1
  196. package/build/types/provider.d.ts +2 -2
  197. package/build/types/quorum.d.ts +35 -1
  198. package/build/types/stream.d.ts +12 -6
  199. package/package.json +8 -2
  200. package/build/services/activities/activity.d.ts +0 -192
  201. package/build/services/activities/activity.js +0 -786
  202. package/build/services/durable/workflow/interrupt.d.ts +0 -55
@@ -1,35 +1,78 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
2
+ /**
3
+ * EngineService the workflow execution engine.
4
+ *
5
+ * Consumes stream messages from the router and dispatches them
6
+ * to the appropriate activity handler (Trigger, Worker, Hook, …).
7
+ *
8
+ * Each section delegates to a purpose-specific module inside `engine/`.
9
+ * Open the module when you need implementation detail; read this file
10
+ * when you need the big picture.
11
+ *
12
+ * Lifecycle (maps to modules):
13
+ * 1. INIT → init.ts (channel setup, router, config)
14
+ * 2. VERSION → version.ts (app version resolution, caching)
15
+ * 3. SCHEMA → schema.ts (activity lookup, handler factory)
16
+ * 4. COMPILE → compiler.ts (YAML plan & deploy)
17
+ * 5. REPORT → reporting.ts (stats, IDs, query resolution)
18
+ * 6. DISPATCH → dispatch.ts (stream message → activity handler)
19
+ * 7. COMPLETION → completion.ts (parent notify, cleanup, expiry)
20
+ * 8. SIGNAL → signal.ts (webhook/timehook delivery, fan-out)
21
+ * 9. PUB/SUB → pubsub.ts (topic messaging, subscriptions)
22
+ * 10. STATE → state.ts (job state retrieval, export)
23
+ */
24
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
25
+ if (k2 === undefined) k2 = k;
26
+ var desc = Object.getOwnPropertyDescriptor(m, k);
27
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
28
+ desc = { enumerable: true, get: function() { return m[k]; } };
29
+ }
30
+ Object.defineProperty(o, k2, desc);
31
+ }) : (function(o, m, k, k2) {
32
+ if (k2 === undefined) k2 = k;
33
+ o[k2] = m[k];
34
+ }));
35
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
36
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
37
+ }) : function(o, v) {
38
+ o["default"] = v;
39
+ });
40
+ var __importStar = (this && this.__importStar) || function (mod) {
41
+ if (mod && mod.__esModule) return mod;
42
+ var result = {};
43
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
44
+ __setModuleDefault(result, mod);
45
+ return result;
4
46
  };
5
47
  Object.defineProperty(exports, "__esModule", { value: true });
6
48
  exports.EngineService = void 0;
7
49
  const key_1 = require("../../modules/key");
8
- const registry_1 = require("../stream/registry");
9
50
  const enums_1 = require("../../modules/enums");
10
51
  const utils_1 = require("../../modules/utils");
11
- const activities_1 = __importDefault(require("../activities"));
12
- const compiler_1 = require("../compiler");
13
- const exporter_1 = require("../exporter");
14
- const reporter_1 = require("../reporter");
15
- const router_1 = require("../router");
16
- const serializer_1 = require("../serializer");
17
- const factory_1 = require("../search/factory");
18
- const factory_2 = require("../store/factory");
19
- const factory_3 = require("../stream/factory");
20
- const factory_4 = require("../sub/factory");
21
- const task_1 = require("../task");
22
52
  const stream_1 = require("../../types/stream");
53
+ const Init = __importStar(require("./init"));
54
+ const Version = __importStar(require("./version"));
55
+ const Schema = __importStar(require("./schema"));
56
+ const Compiler = __importStar(require("./compiler"));
57
+ const Reporting = __importStar(require("./reporting"));
58
+ const Dispatch = __importStar(require("./dispatch"));
59
+ const Completion = __importStar(require("./completion"));
60
+ const Signal = __importStar(require("./signal"));
61
+ const PubSub = __importStar(require("./pubsub"));
62
+ const State = __importStar(require("./state"));
23
63
  class EngineService {
64
+ // ═════════════════════════════════════════════════════════════════
65
+ // 1. INIT — bootstrap channels, router, and services
66
+ // → see init.ts
67
+ // ═════════════════════════════════════════════════════════════════
24
68
  /**
25
69
  * @private
26
70
  */
27
71
  constructor() {
72
+ // ── execution state ───────────────────────────────────────────────
28
73
  this.cacheMode = 'cache';
29
74
  this.untilVersion = null;
30
75
  this.jobCallbacks = {};
31
- this.reporting = false;
32
- this.jobId = 1;
33
76
  }
34
77
  /**
35
78
  * @private
@@ -37,608 +80,238 @@ class EngineService {
37
80
  static async init(namespace, appId, guid, config, logger) {
38
81
  if (config.engine) {
39
82
  const instance = new EngineService();
40
- instance.verifyEngineFields(config);
83
+ Init.verifyEngineFields(config);
41
84
  instance.namespace = namespace;
42
85
  instance.appId = appId;
43
86
  instance.guid = guid;
44
87
  instance.logger = logger;
45
- await instance.initSearchChannel(config.engine.store);
46
- await instance.initStoreChannel(config.engine.store);
47
- //NOTE: if `pub` is present, use it; otherwise, use `store`
48
- await instance.initSubChannel(config.engine.sub, config.engine.pub ?? config.engine.store);
49
- await instance.initStreamChannel(config.engine.stream, config.engine.store);
50
- instance.router = await instance.initRouter(config);
51
- // Use singleton consumer via registry for engine stream
52
- await registry_1.StreamConsumerRegistry.registerEngine(namespace, appId, guid, instance.processStreamMessage.bind(instance), instance.stream, instance.store, logger, {
53
- reclaimDelay: config.engine.reclaimDelay,
54
- reclaimCount: config.engine.reclaimCount,
55
- });
56
- instance.taskService = new task_1.TaskService(instance.store, logger);
57
- instance.exporter = new exporter_1.ExporterService(instance.appId, instance.store, logger);
58
- instance.inited = (0, utils_1.formatISODate)(new Date());
88
+ await Init.initSearchChannel(instance, config.engine.store);
89
+ await Init.initStoreChannel(instance, config.engine.store);
90
+ await Init.initSubChannel(instance, config.engine.sub, config.engine.pub ?? config.engine.store);
91
+ await Init.initStreamChannel(instance, config.engine.stream, config.engine.store);
92
+ instance.router = await Init.initRouter(instance, config);
93
+ await Init.registerStreamConsumer(instance, config);
94
+ Init.initServices(instance);
59
95
  return instance;
60
96
  }
61
97
  }
62
98
  /**
63
99
  * @private
64
100
  */
65
- verifyEngineFields(config) {
66
- if (!(0, utils_1.identifyProvider)(config.engine.store) ||
67
- !(0, utils_1.identifyProvider)(config.engine.stream) ||
68
- !(0, utils_1.identifyProvider)(config.engine.sub)) {
69
- throw new Error('engine must include `store`, `stream`, and `sub` fields.');
70
- }
71
- }
72
- /**
73
- * @private
74
- */
75
- async initSearchChannel(search, store) {
76
- this.search = await factory_1.SearchServiceFactory.init(search, store, this.namespace, this.appId, this.logger);
77
- }
78
- /**
79
- * @private
80
- */
81
- async initStoreChannel(store) {
82
- this.store = await factory_2.StoreServiceFactory.init(store, this.namespace, this.appId, this.logger);
83
- }
84
- /**
85
- * @private
86
- */
87
- async initSubChannel(sub, store) {
88
- this.subscribe = await factory_4.SubServiceFactory.init(sub, store, this.namespace, this.appId, this.guid, this.logger);
89
- }
90
- /**
91
- * @private
92
- */
93
- async initStreamChannel(stream, store) {
94
- this.stream = await factory_3.StreamServiceFactory.init(stream, store, this.namespace, this.appId, this.logger);
95
- }
96
- /**
97
- * @private
98
- */
99
- async initRouter(config) {
100
- const throttle = await this.store.getThrottleRate(':');
101
- return new router_1.Router({
102
- namespace: this.namespace,
103
- appId: this.appId,
104
- guid: this.guid,
105
- role: stream_1.StreamRole.ENGINE,
106
- reclaimDelay: config.engine.reclaimDelay,
107
- reclaimCount: config.engine.reclaimCount,
108
- throttle,
109
- readonly: config.engine.readonly,
110
- }, this.stream, this.logger);
101
+ async getSettings() {
102
+ return Init.getSettings(this);
111
103
  }
104
+ // ═════════════════════════════════════════════════════════════════
105
+ // 2. VERSION — app version resolution and cache management
106
+ // → see version.ts
107
+ // ═════════════════════════════════════════════════════════════════
112
108
  /**
113
- * resolves the distributed executable version using a delay
114
- * to allow deployment race conditions to resolve
115
109
  * @private
116
110
  */
117
- async fetchAndVerifyVID(vid, count = 0) {
118
- if (isNaN(Number(vid.version))) {
119
- const app = await this.store.getApp(vid.id, true);
120
- if (!isNaN(Number(app.version))) {
121
- if (!this.apps)
122
- this.apps = {};
123
- this.apps[vid.id] = app;
124
- return { id: vid.id, version: app.version };
125
- }
126
- else if (count < 10) {
127
- await (0, utils_1.sleepFor)(enums_1.HMSH_QUORUM_DELAY_MS * 2);
128
- return await this.fetchAndVerifyVID(vid, count + 1);
129
- }
130
- else {
131
- this.logger.error('engine-vid-resolution-error', {
132
- id: vid.id,
133
- guid: this.guid,
134
- });
135
- }
136
- }
137
- return vid;
138
- }
139
111
  async getVID(vid) {
140
- if (this.cacheMode === 'nocache') {
141
- const app = await this.store.getApp(this.appId, true);
142
- if (app.version.toString() === this.untilVersion.toString()) {
143
- //new version is deployed; OK to cache again
144
- if (!this.apps)
145
- this.apps = {};
146
- this.apps[this.appId] = app;
147
- this.setCacheMode('cache', app.version.toString());
148
- }
149
- return { id: this.appId, version: app.version };
150
- }
151
- else if (!this.apps && vid) {
152
- this.apps = {};
153
- this.apps[this.appId] = vid;
154
- return vid;
155
- }
156
- else {
157
- return await this.fetchAndVerifyVID({
158
- id: this.appId,
159
- version: this.apps?.[this.appId].version,
160
- });
161
- }
112
+ return Version.getVID(this, vid);
162
113
  }
163
114
  /**
164
115
  * @private
165
116
  */
166
117
  setCacheMode(cacheMode, untilVersion) {
167
- this.logger.info(`engine-executable-cache`, {
168
- mode: cacheMode,
169
- [cacheMode === 'cache' ? 'target' : 'until']: untilVersion,
170
- });
171
- this.cacheMode = cacheMode;
172
- this.untilVersion = untilVersion;
118
+ Version.setCacheMode(this, cacheMode, untilVersion);
173
119
  }
120
+ // ═════════════════════════════════════════════════════════════════
121
+ // 3. SCHEMA — activity schema lookup and handler instantiation
122
+ // → see schema.ts
123
+ // ═════════════════════════════════════════════════════════════════
174
124
  /**
175
125
  * @private
176
126
  */
177
- async routeToSubscribers(topic, message) {
178
- const jobCallback = this.jobCallbacks[message.metadata.jid];
179
- if (jobCallback) {
180
- this.delistJobCallback(message.metadata.jid);
181
- jobCallback(topic, message);
182
- }
127
+ async initActivity(topic, data = {}, context) {
128
+ return Schema.initActivity(this, topic, data, context);
183
129
  }
184
130
  /**
185
131
  * @private
186
132
  */
187
- async processWebHooks() {
188
- this.taskService.processWebHooks(this.signal.bind(this));
133
+ async getSchema(topic) {
134
+ return Schema.getSchema(this, topic);
189
135
  }
190
136
  /**
191
137
  * @private
192
138
  */
193
- async processTimeHooks() {
194
- this.taskService.processTimeHooks(this.hookTime.bind(this));
139
+ isPrivate(topic) {
140
+ return Schema.isPrivate(topic);
195
141
  }
142
+ // ═════════════════════════════════════════════════════════════════
143
+ // 4. COMPILE — YAML app plan & deploy
144
+ // → see compiler.ts
145
+ // ═════════════════════════════════════════════════════════════════
196
146
  /**
197
147
  * @private
198
148
  */
199
- async throttle(delayInMillis) {
200
- try {
201
- this.router?.setThrottle(delayInMillis);
202
- }
203
- catch (e) {
204
- this.logger.error('engine-throttle-error', { error: e });
205
- }
149
+ async plan(pathOrYAML) {
150
+ return Compiler.plan(this, pathOrYAML);
206
151
  }
207
- // ************* METADATA/MODEL METHODS *************
208
152
  /**
209
153
  * @private
210
154
  */
211
- async initActivity(topic, data = {}, context) {
212
- const [activityId, schema] = await this.getSchema(topic);
213
- if (!schema) {
214
- throw new Error(`Activity schema not found for "${activityId}" (topic: ${topic}) in app ${this.appId}`);
215
- }
216
- const ActivityHandler = activities_1.default[schema.type];
217
- if (ActivityHandler) {
218
- const utc = (0, utils_1.formatISODate)(new Date());
219
- const metadata = {
220
- aid: activityId,
221
- atp: schema.type,
222
- stp: schema.subtype,
223
- ac: utc,
224
- au: utc,
225
- };
226
- const hook = null;
227
- return new ActivityHandler(schema, data, metadata, hook, this, context);
228
- }
229
- else {
230
- throw new Error(`activity type ${schema.type} not found`);
231
- }
232
- }
233
- async getSchema(topic) {
234
- const app = (await this.store.getApp(this.appId));
235
- if (!app) {
236
- throw new Error(`no app found for id ${this.appId}`);
237
- }
238
- if (this.isPrivate(topic)) {
239
- //private subscriptions use the schema id (.activityId)
240
- const activityId = topic.substring(1);
241
- const schema = await this.store.getSchema(activityId, await this.getVID(app));
242
- return [activityId, schema];
243
- }
244
- else {
245
- //public subscriptions use a topic (a.b.c) that is associated with a schema id
246
- const activityId = await this.store.getSubscription(topic, await this.getVID(app));
247
- if (activityId) {
248
- const schema = await this.store.getSchema(activityId, await this.getVID(app));
249
- return [activityId, schema];
250
- }
251
- }
252
- throw new Error(`no subscription found for topic ${topic} in app ${this.appId} for app version ${app.version}`);
155
+ async deploy(pathOrYAML) {
156
+ return Compiler.deploy(this, pathOrYAML);
253
157
  }
158
+ // ═════════════════════════════════════════════════════════════════
159
+ // 5. REPORT — stats queries and job-ID lookups
160
+ // → see reporting.ts
161
+ // ═════════════════════════════════════════════════════════════════
254
162
  /**
255
163
  * @private
256
164
  */
257
- async getSettings() {
258
- return await this.store.getSettings();
165
+ async getStats(topic, query) {
166
+ return Reporting.getStats(this, topic, query);
259
167
  }
260
168
  /**
261
169
  * @private
262
170
  */
263
- isPrivate(topic) {
264
- return topic.startsWith('.');
171
+ async getIds(topic, query, queryFacets = []) {
172
+ return Reporting.getIds(this, topic, query, queryFacets);
265
173
  }
266
- // ************* COMPILER METHODS *************
267
174
  /**
268
175
  * @private
269
176
  */
270
- async plan(pathOrYAML) {
271
- const compiler = new compiler_1.CompilerService(this.store, this.stream, this.logger);
272
- return await compiler.plan(pathOrYAML);
177
+ async resolveQuery(topic, query) {
178
+ return Reporting.resolveQuery(this, topic, query);
273
179
  }
180
+ // ═════════════════════════════════════════════════════════════════
181
+ // 6. DISPATCH — stream message routing to activity handlers
182
+ // → see dispatch.ts
183
+ // ═════════════════════════════════════════════════════════════════
274
184
  /**
275
185
  * @private
276
186
  */
277
- async deploy(pathOrYAML) {
278
- const compiler = new compiler_1.CompilerService(this.store, this.stream, this.logger);
279
- return await compiler.deploy(pathOrYAML);
187
+ async processStreamMessage(streamData) {
188
+ return Dispatch.processStreamMessage(this, streamData);
280
189
  }
281
- // ************* REPORTER METHODS *************
190
+ // ═════════════════════════════════════════════════════════════════
191
+ // 7. COMPLETION — parent notification, cleanup, and expiry
192
+ // → see completion.ts
193
+ // ═════════════════════════════════════════════════════════════════
282
194
  /**
283
195
  * @private
284
196
  */
285
- async getStats(topic, query) {
286
- const { id, version } = await this.getVID();
287
- const reporter = new reporter_1.ReporterService({ id, version }, this.store, this.logger);
288
- const resolvedQuery = await this.resolveQuery(topic, query);
289
- return await reporter.getStats(resolvedQuery);
197
+ async execAdjacentParent(context, jobOutput, emit = false, transaction) {
198
+ return Completion.execAdjacentParent(this, context, jobOutput, emit, transaction);
290
199
  }
291
200
  /**
292
201
  * @private
293
202
  */
294
- async getIds(topic, query, queryFacets = []) {
295
- const { id, version } = await this.getVID();
296
- const reporter = new reporter_1.ReporterService({ id, version }, this.store, this.logger);
297
- const resolvedQuery = await this.resolveQuery(topic, query);
298
- return await reporter.getIds(resolvedQuery, queryFacets);
203
+ hasParentJob(context, checkSevered = false) {
204
+ return Completion.hasParentJob(context, checkSevered);
299
205
  }
300
206
  /**
301
207
  * @private
302
208
  */
303
- async resolveQuery(topic, query) {
304
- const trigger = (await this.initActivity(topic, query.data));
305
- await trigger.getState();
306
- return {
307
- end: query.end,
308
- start: query.start,
309
- range: query.range,
310
- granularity: trigger.resolveGranularity(),
311
- key: trigger.resolveJobKey(trigger.createInputContext()),
312
- sparse: query.sparse,
313
- };
209
+ async interrupt(topic, jobId, options = {}) {
210
+ return Completion.interrupt(this, topic, jobId, options);
314
211
  }
315
- // ****************** STREAM RE-ENTRY POINT *****************
316
212
  /**
317
213
  * @private
318
214
  */
319
- async processStreamMessage(streamData) {
320
- this.logger.debug('engine-process', {
321
- jid: streamData.metadata.jid,
322
- gid: streamData.metadata.gid,
323
- dad: streamData.metadata.dad,
324
- aid: streamData.metadata.aid,
325
- status: streamData.status || stream_1.StreamStatus.SUCCESS,
326
- code: streamData.code || 200,
327
- type: streamData.type,
328
- });
329
- const context = {
330
- metadata: {
331
- guid: streamData.metadata.guid,
332
- jid: streamData.metadata.jid,
333
- gid: streamData.metadata.gid,
334
- dad: streamData.metadata.dad,
335
- aid: streamData.metadata.aid,
336
- },
337
- data: streamData.data,
338
- };
339
- if (streamData.type === stream_1.StreamDataType.TIMEHOOK) {
340
- //TIMEHOOK AWAKEN
341
- const activityHandler = (await this.initActivity(`.${streamData.metadata.aid}`, context.data, context));
342
- await activityHandler.processTimeHookEvent(streamData.metadata.jid);
343
- }
344
- else if (streamData.type === stream_1.StreamDataType.WEBHOOK) {
345
- //WEBHOOK AWAKEN (SIGNAL IN)
346
- const activityHandler = (await this.initActivity(`.${streamData.metadata.aid}`, context.data, context));
347
- await activityHandler.processWebHookEvent(streamData.status, streamData.code);
348
- }
349
- else if (streamData.type === stream_1.StreamDataType.TRANSITION) {
350
- //TRANSITION (ADJACENT ACTIVITY)
351
- const activityHandler = (await this.initActivity(`.${streamData.metadata.aid}`, context.data, context)); //todo: `as Activity` (type is more generic)
352
- await activityHandler.process();
353
- }
354
- else if (streamData.type === stream_1.StreamDataType.AWAIT) {
355
- //TRIGGER JOB
356
- context.metadata = {
357
- ...context.metadata,
358
- pj: streamData.metadata.jid,
359
- pg: streamData.metadata.gid,
360
- pd: streamData.metadata.dad,
361
- pa: streamData.metadata.aid,
362
- px: streamData.metadata.await === false,
363
- trc: streamData.metadata.trc,
364
- spn: streamData.metadata.spn,
365
- };
366
- const activityHandler = (await this.initActivity(streamData.metadata.topic, streamData.data, context));
367
- await activityHandler.process();
368
- }
369
- else if (streamData.type === stream_1.StreamDataType.RESULT) {
370
- //AWAIT RESULT
371
- const activityHandler = (await this.initActivity(`.${context.metadata.aid}`, streamData.data, context));
372
- await activityHandler.processEvent(streamData.status, streamData.code);
373
- }
374
- else {
375
- //WORKER RESULT
376
- const activityHandler = (await this.initActivity(`.${streamData.metadata.aid}`, streamData.data, context));
377
- await activityHandler.processEvent(streamData.status, streamData.code, 'output');
378
- }
379
- this.logger.debug('engine-process-end', {
380
- jid: streamData.metadata.jid,
381
- gid: streamData.metadata.gid,
382
- aid: streamData.metadata.aid,
383
- });
215
+ async scrub(jobId) {
216
+ return Completion.scrub(this, jobId);
384
217
  }
385
- // ***************** `AWAIT` ACTIVITY RETURN RESPONSE ****************
386
218
  /**
387
219
  * @private
388
220
  */
389
- async execAdjacentParent(context, jobOutput, emit = false, transaction) {
390
- if (this.hasParentJob(context)) {
391
- //errors are stringified `StreamError` objects
392
- const error = this.resolveError(jobOutput.metadata);
393
- const spn = context['$self']?.output?.metadata?.l2s ||
394
- context['$self']?.output?.metadata?.l1s;
395
- const streamData = {
396
- metadata: {
397
- guid: (0, utils_1.guid)(),
398
- jid: context.metadata.pj,
399
- gid: context.metadata.pg,
400
- dad: context.metadata.pd,
401
- aid: context.metadata.pa,
402
- trc: context.metadata.trc,
403
- spn,
404
- },
405
- type: stream_1.StreamDataType.RESULT,
406
- data: jobOutput.data,
407
- };
408
- if (error && error.code) {
409
- streamData.status = stream_1.StreamStatus.ERROR;
410
- streamData.data = error;
411
- streamData.code = error.code;
412
- streamData.stack = error.stack;
413
- }
414
- else if (emit) {
415
- streamData.status = stream_1.StreamStatus.PENDING;
416
- streamData.code = enums_1.HMSH_CODE_PENDING;
417
- }
418
- else {
419
- streamData.status = stream_1.StreamStatus.SUCCESS;
420
- streamData.code = enums_1.HMSH_CODE_SUCCESS;
421
- }
422
- return (await this.router?.publishMessage(null, streamData, transaction));
423
- }
221
+ async runJobCompletionTasks(context, options = {}, transaction) {
222
+ return Completion.runJobCompletionTasks(this, context, options, transaction);
424
223
  }
224
+ // ═════════════════════════════════════════════════════════════════
225
+ // 8. SIGNAL — webhook/timehook delivery and fan-out
226
+ // → see signal.ts
227
+ // ═════════════════════════════════════════════════════════════════
425
228
  /**
426
229
  * @private
427
230
  */
428
- hasParentJob(context, checkSevered = false) {
429
- if (checkSevered) {
430
- return Boolean(context.metadata.pj && context.metadata.pa && !context.metadata.px);
431
- }
432
- return Boolean(context.metadata.pj && context.metadata.pa);
231
+ async signal(topic, data, status = stream_1.StreamStatus.SUCCESS, code = 200, transaction) {
232
+ return Signal.signal(this, topic, data, status, code, transaction);
433
233
  }
434
234
  /**
435
235
  * @private
436
236
  */
437
- resolveError(metadata) {
438
- if (metadata && metadata.err) {
439
- return JSON.parse(metadata.err);
440
- }
237
+ async hookTime(jobId, gId, topicOrActivity, type) {
238
+ return Signal.hookTime(this, jobId, gId, topicOrActivity, type);
441
239
  }
442
- // ****************** `INTERRUPT` ACTIVE JOBS *****************
443
240
  /**
444
241
  * @private
445
242
  */
446
- async interrupt(topic, jobId, options = {}) {
447
- //immediately interrupt the job, going directly to the data source
448
- await this.store.interrupt(topic, jobId, options);
449
- //now that the job is interrupted, we can clean up
450
- const context = (await this.getState(topic, jobId));
451
- const completionOpts = {
452
- interrupt: options.descend,
453
- expire: options.expire,
454
- };
455
- return (await this.runJobCompletionTasks(context, completionOpts));
243
+ async signalAll(hookTopic, data, keyResolver, queryFacets = []) {
244
+ return Signal.signalAll(this, hookTopic, data, keyResolver, queryFacets);
456
245
  }
457
- // ****************** `SCRUB` CLEAN COMPLETED JOBS *****************
458
246
  /**
459
247
  * @private
460
248
  */
461
- async scrub(jobId) {
462
- //todo: do not allow scrubbing of non-existent or actively running job
463
- await this.store.scrub(jobId);
249
+ async routeToSubscribers(topic, message) {
250
+ return Signal.routeToSubscribers(this, topic, message);
464
251
  }
465
- // ****************** `SIGNAL` ACTIVITY RE-ENTRY POINT ****************
466
252
  /**
467
- * Delivers a signal (data payload) to a paused hook activity,
468
- * resuming its Leg 2 execution. The `topic` must match a hook rule
469
- * defined in the YAML graph's `hooks` section. The engine locates
470
- * the target activity and dimension for reentry based on the hook
471
- * rule's match conditions.
472
- *
473
253
  * @private
474
254
  */
475
- async signal(topic, data, status = stream_1.StreamStatus.SUCCESS, code = 200, transaction) {
476
- const hookRule = await this.taskService.getHookRule(topic);
477
- const [aid] = await this.getSchema(`.${hookRule.to}`);
478
- const streamData = {
479
- type: stream_1.StreamDataType.WEBHOOK,
480
- status,
481
- code,
482
- metadata: {
483
- guid: (0, utils_1.guid)(),
484
- aid,
485
- topic,
486
- },
487
- data,
488
- };
489
- return (await this.router?.publishMessage(null, streamData, transaction));
255
+ async processWebHooks() {
256
+ return Signal.processWebHooks(this, this.signal.bind(this));
490
257
  }
491
258
  /**
492
259
  * @private
493
260
  */
494
- async hookTime(jobId, gId, topicOrActivity, type) {
495
- if (type === 'interrupt' || type === 'expire') {
496
- return await this.interrupt(topicOrActivity, jobId, {
497
- suppress: true,
498
- expire: 1,
499
- });
500
- }
501
- const [aid, ...dimensions] = topicOrActivity.split(',');
502
- const dad = `,${dimensions.join(',')}`;
503
- const streamData = {
504
- type: stream_1.StreamDataType.TIMEHOOK,
505
- metadata: {
506
- guid: (0, utils_1.guid)(),
507
- jid: jobId,
508
- gid: gId,
509
- dad,
510
- aid,
511
- },
512
- data: { timestamp: Date.now() },
513
- };
514
- await this.router?.publishMessage(null, streamData);
515
- }
516
- /**
517
- * Fan-out variant of `signal()` that delivers data to **all**
518
- * paused workflows matching a search query. Useful for resuming
519
- * a batch of workflows waiting on the same external event.
520
- *
261
+ async processTimeHooks() {
262
+ return Signal.processTimeHooks(this, this.hookTime.bind(this));
263
+ }
264
+ /**
521
265
  * @private
522
266
  */
523
- async signalAll(hookTopic, data, keyResolver, queryFacets = []) {
524
- const config = await this.getVID();
525
- const hookRule = await this.taskService.getHookRule(hookTopic);
526
- if (hookRule) {
527
- const subscriptionTopic = await (0, utils_1.getSubscriptionTopic)(hookRule.to, this.store, config);
528
- const resolvedQuery = await this.resolveQuery(subscriptionTopic, keyResolver);
529
- const reporter = new reporter_1.ReporterService(config, this.store, this.logger);
530
- const workItems = await reporter.getWorkItems(resolvedQuery, queryFacets);
531
- if (workItems.length) {
532
- const taskService = new task_1.TaskService(this.store, this.logger);
533
- await taskService.enqueueWorkItems(workItems.map((workItem) => [
534
- hookTopic,
535
- workItem,
536
- keyResolver.scrub || false,
537
- JSON.stringify(data),
538
- ].join(key_1.VALSEP)));
539
- this.subscribe.publish(key_1.KeyType.QUORUM, { type: 'work', originator: this.guid }, this.appId);
540
- }
541
- return workItems;
542
- }
543
- else {
544
- throw new Error(`unable to find hook rule for topic ${hookTopic}`);
545
- }
267
+ async throttle(delayInMillis) {
268
+ return Signal.throttle(this, delayInMillis);
546
269
  }
547
- // ********************** PUB/SUB ENTRY POINT **********************
270
+ // ═════════════════════════════════════════════════════════════════
271
+ // 9. PUB/SUB — topic messaging, subscriptions, callbacks
272
+ // → see pubsub.ts
273
+ // ═════════════════════════════════════════════════════════════════
548
274
  /**
549
275
  * @private
550
276
  */
551
277
  async pub(topic, data, context, extended) {
552
- const activityHandler = await this.initActivity(topic, data, context);
553
- if (activityHandler) {
554
- return await activityHandler.process(extended);
555
- }
556
- else {
557
- throw new Error(`unable to process activity for topic ${topic}`);
558
- }
278
+ return PubSub.pub(this, topic, data, context, extended);
559
279
  }
560
280
  /**
561
281
  * @private
562
282
  */
563
283
  async sub(topic, callback) {
564
- const subscriptionCallback = async (topic, message) => {
565
- let jobOutput = message.job;
566
- // If _ref is true, payload was too large - fetch full job data via getState
567
- if (message._ref && message.job?.metadata) {
568
- jobOutput = await this.getState(message.job.metadata.tpc, message.job.metadata.jid);
569
- }
570
- callback(message.topic, jobOutput);
571
- };
572
- return await this.subscribe.subscribe(key_1.KeyType.QUORUM, subscriptionCallback, this.appId, topic);
284
+ return PubSub.sub(this, topic, callback);
573
285
  }
574
286
  /**
575
287
  * @private
576
288
  */
577
289
  async unsub(topic) {
578
- return await this.subscribe.unsubscribe(key_1.KeyType.QUORUM, this.appId, topic);
290
+ return PubSub.unsub(this, topic);
579
291
  }
580
292
  /**
581
293
  * @private
582
294
  */
583
295
  async psub(wild, callback) {
584
- const subscriptionCallback = async (topic, message) => {
585
- let jobOutput = message.job;
586
- // If _ref is true, payload was too large - fetch full job data via getState
587
- if (message._ref && message.job?.metadata) {
588
- jobOutput = await this.getState(message.job.metadata.tpc, message.job.metadata.jid);
589
- }
590
- callback(message.topic, jobOutput);
591
- };
592
- return await this.subscribe.psubscribe(key_1.KeyType.QUORUM, subscriptionCallback, this.appId, wild);
296
+ return PubSub.psub(this, wild, callback);
593
297
  }
594
298
  /**
595
299
  * @private
596
300
  */
597
301
  async punsub(wild) {
598
- return await this.subscribe.punsubscribe(key_1.KeyType.QUORUM, this.appId, wild);
302
+ return PubSub.punsub(this, wild);
599
303
  }
600
304
  /**
601
305
  * @private
602
306
  */
603
307
  async pubsub(topic, data, context, timeout = enums_1.HMSH_OTT_WAIT_TIME) {
604
- context = {
605
- metadata: {
606
- ngn: this.guid,
607
- trc: context?.metadata?.trc,
608
- spn: context?.metadata?.spn,
609
- },
610
- };
611
- const jobId = await this.pub(topic, data, context);
612
- return new Promise((resolve, reject) => {
613
- this.registerJobCallback(jobId, (topic, output) => {
614
- if (output.metadata.err) {
615
- const error = JSON.parse(output.metadata.err);
616
- reject({
617
- error,
618
- job_id: output.metadata.jid,
619
- });
620
- }
621
- else {
622
- resolve(output);
623
- }
624
- });
625
- setTimeout(() => {
626
- //note: job is still active (the subscriber timed out)
627
- this.delistJobCallback(jobId);
628
- reject({
629
- code: enums_1.HMSH_CODE_TIMEOUT,
630
- message: 'timeout',
631
- job_id: jobId,
632
- });
633
- }, timeout);
634
- });
308
+ return PubSub.pubsub(this, topic, data, context, timeout);
635
309
  }
636
310
  /**
637
311
  * @private
638
312
  */
639
313
  async pubOneTimeSubs(context, jobOutput, emit = false, transaction) {
640
- //todo: subscriber should query for the job...only publish minimum context needed
641
- if (this.hasOneTimeSubscription(context)) {
314
+ if (PubSub.hasOneTimeSubscription(context)) {
642
315
  const message = {
643
316
  type: 'job',
644
317
  topic: context.metadata.jid,
@@ -647,20 +320,11 @@ class EngineService {
647
320
  await this.subscribe.publish(key_1.KeyType.QUORUM, message, this.appId, context.metadata.ngn, transaction);
648
321
  }
649
322
  }
650
- /**
651
- * @private
652
- */
653
- async getPublishesTopic(context) {
654
- const config = await this.getVID();
655
- const activityId = context.metadata.aid || context['$self']?.output?.metadata?.aid;
656
- const schema = await this.store.getSchema(activityId, config);
657
- return schema.publishes;
658
- }
659
323
  /**
660
324
  * @private
661
325
  */
662
326
  async pubPermSubs(context, jobOutput, emit = false, transaction) {
663
- const topic = await this.getPublishesTopic(context);
327
+ const topic = await PubSub.getPublishesTopic(this, context);
664
328
  if (topic) {
665
329
  const message = {
666
330
  type: 'job',
@@ -673,135 +337,73 @@ class EngineService {
673
337
  /**
674
338
  * @private
675
339
  */
676
- async add(streamData) {
677
- return (await this.router?.publishMessage(null, streamData));
678
- }
679
- /**
680
- * @private
681
- */
682
- registerJobCallback(jobId, jobCallback) {
683
- this.jobCallbacks[jobId] = jobCallback;
340
+ async getPublishesTopic(context) {
341
+ return PubSub.getPublishesTopic(this, context);
684
342
  }
685
343
  /**
686
344
  * @private
687
345
  */
688
- delistJobCallback(jobId) {
689
- delete this.jobCallbacks[jobId];
346
+ async add(streamData) {
347
+ return PubSub.add(this, streamData);
690
348
  }
691
349
  /**
692
350
  * @private
693
351
  */
694
- hasOneTimeSubscription(context) {
695
- return Boolean(context.metadata.ngn);
352
+ registerJobCallback(jobId, jobCallback) {
353
+ PubSub.registerJobCallback(this, jobId, jobCallback);
696
354
  }
697
- // ********** JOB COMPLETION/CLEANUP (AND JOB EMIT) ***********
698
355
  /**
699
356
  * @private
700
357
  */
701
- async runJobCompletionTasks(context, options = {}, transaction) {
702
- //'emit' indicates the job is still active
703
- const isAwait = this.hasParentJob(context, true);
704
- const isOneTimeSub = this.hasOneTimeSubscription(context);
705
- const topic = await this.getPublishesTopic(context);
706
- let msgId;
707
- let jobOutput;
708
- if (isAwait || isOneTimeSub || topic) {
709
- jobOutput = await this.getState(context.metadata.tpc, context.metadata.jid);
710
- //only send RESULT to parent for non-severed children (execChild).
711
- //startChild (px=true) children already sent RESULT at spawn time
712
- //via Trigger.execAdjacentParent; sending again here would cause
713
- //a duplicate semaphore decrement in collation workflows.
714
- if (isAwait) {
715
- msgId = await this.execAdjacentParent(context, jobOutput, options.emit, transaction);
716
- }
717
- if (transaction) {
718
- //transactional: await to queue NOTIFY in the transaction
719
- await this.pubOneTimeSubs(context, jobOutput, options.emit, transaction);
720
- await this.pubPermSubs(context, jobOutput, options.emit, transaction);
721
- }
722
- else {
723
- //non-transactional: fire-and-forget to avoid race with inline
724
- //trigger processing (callback registered after pub() returns)
725
- this.pubOneTimeSubs(context, jobOutput, options.emit);
726
- this.pubPermSubs(context, jobOutput, options.emit);
727
- }
728
- }
729
- if (!options.emit) {
730
- if (transaction) {
731
- await this.taskService.registerJobForCleanup(context.metadata.jid, this.resolveExpires(context, options), options, transaction);
732
- }
733
- else {
734
- this.taskService.registerJobForCleanup(context.metadata.jid, this.resolveExpires(context, options), options);
735
- }
736
- }
737
- return msgId;
358
+ delistJobCallback(jobId) {
359
+ PubSub.removeJobCallback(this, jobId);
738
360
  }
739
361
  /**
740
- * Job hash expiration is typically reliant on the metadata field
741
- * if the activity concludes normally. However, if the job is `interrupted`,
742
- * it will be expired immediately.
743
362
  * @private
744
363
  */
745
- resolveExpires(context, options) {
746
- return options.expire ?? context.metadata.expire ?? enums_1.HMSH_EXPIRE_JOB_SECONDS;
364
+ hasOneTimeSubscription(context) {
365
+ return PubSub.hasOneTimeSubscription(context);
747
366
  }
748
- // ****** GET JOB STATE/COLLATION STATUS BY ID *********
367
+ // ═════════════════════════════════════════════════════════════════
368
+ // 10. STATE — job state retrieval, export, and compression
369
+ // → see state.ts
370
+ // ═════════════════════════════════════════════════════════════════
749
371
  /**
750
372
  * @private
751
373
  */
752
374
  async export(jobId, options = {}) {
753
- return await this.exporter.export(jobId, options);
375
+ return State.exportJob(this, jobId, options);
754
376
  }
755
377
  /**
756
378
  * @private
757
379
  */
758
380
  async getRaw(jobId) {
759
- return await this.store.getRaw(jobId);
381
+ return State.getRaw(this, jobId);
760
382
  }
761
383
  /**
762
384
  * @private
763
385
  */
764
386
  async getStatus(jobId) {
765
- const { id: appId } = await this.getVID();
766
- return await this.store.getStatus(jobId, appId);
387
+ return State.getStatus(this, jobId);
767
388
  }
768
389
  /**
769
390
  * @private
770
391
  */
771
392
  async getState(topic, jobId) {
772
- const jobSymbols = await this.store.getSymbols(`$${topic}`);
773
- const consumes = {
774
- [`$${topic}`]: Object.keys(jobSymbols),
775
- };
776
- //job data exists at the 'zero' dimension; pass an empty object
777
- const dIds = {};
778
- const output = await this.store.getState(jobId, consumes, dIds);
779
- if (!output) {
780
- throw new Error(`not found ${jobId}`);
781
- }
782
- const [state, status] = output;
783
- const stateTree = (0, utils_1.restoreHierarchy)(state);
784
- if (status != null && stateTree.metadata) {
785
- stateTree.metadata.js = status;
786
- }
787
- return stateTree;
393
+ return State.getState(this, topic, jobId);
788
394
  }
789
395
  /**
790
396
  * @private
791
397
  */
792
398
  async getQueryState(jobId, fields) {
793
- return await this.store.getQueryState(jobId, fields);
399
+ return State.getQueryState(this, jobId, fields);
794
400
  }
795
401
  /**
796
402
  * @private
797
403
  * @deprecated
798
404
  */
799
405
  async compress(terms) {
800
- const existingSymbols = await this.store.getSymbolValues();
801
- const startIndex = Object.keys(existingSymbols).length;
802
- const maxIndex = Math.pow(52, 2) - 1;
803
- const newSymbols = serializer_1.SerializerService.filterSymVals(startIndex, maxIndex, existingSymbols, new Set(terms));
804
- return await this.store.addSymbolValues(newSymbols);
406
+ return State.compress(this, terms);
805
407
  }
806
408
  }
807
409
  exports.EngineService = EngineService;