@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
@@ -9,6 +9,9 @@ import { JobMessageCallback, QuorumMessage, QuorumMessageCallback, QuorumProfile
9
9
  import { StringAnyType, StringStringType } from '../../types/serializer';
10
10
  import { JobStatsInput, GetStatsOptions, IdsResponse, StatsResponse } from '../../types/stats';
11
11
  import { StreamCode, StreamData, StreamDataResponse, StreamStatus } from '../../types/stream';
12
+ import type { PayloadCodec } from '../../types/codec';
13
+ import * as WorkerCredentials from '../worker/credentials';
14
+ import type { WorkerCredential, WorkerCredentialInfo } from '../worker/credentials';
12
15
  /**
13
16
  * A distributed service mesh that turns Postgres into a durable workflow
14
17
  * orchestration engine. Every `HotMesh.init()` call creates a **point of
@@ -88,67 +91,6 @@ import { StreamCode, StreamData, StreamDataResponse, StreamStatus } from '../../
88
91
  * const result = await hotMesh.pubsub('order.placed', { id: 'ORD-456' });
89
92
  * ```
90
93
  *
91
- * ## Quorum: The Mesh Control Plane
92
- *
93
- * The quorum channel is a broadcast bus available to every mesh member.
94
- * Use it for operational control, observability, and custom messaging.
95
- *
96
- * ```typescript
97
- * // Roll call — discover every engine and worker in the mesh
98
- * const members = await hotMesh.rollCall();
99
- * // => [{ engine_id, worker_topic, throttle, system: { CPULoad, ... } }, ...]
100
- *
101
- * // Subscribe to ALL quorum traffic (throttle, activate, pong, job, user)
102
- * await hotMesh.subQuorum((topic, message) => {
103
- * switch (message.type) {
104
- * case 'pong': // roll call response from a mesh member
105
- * console.log(`Member ${message.guid} on topic ${message.profile?.worker_topic}`);
106
- * break;
107
- * case 'throttle': // a throttle command was broadcast
108
- * console.log(`Throttle ${message.throttle}ms on ${message.topic ?? 'all'}`);
109
- * break;
110
- * case 'activate': // a version activation is in progress
111
- * console.log(`Activating version ${message.until_version}`);
112
- * break;
113
- * case 'job': // a workflow completed and published its result
114
- * console.log(`Job done on ${message.topic}:`, message.job);
115
- * break;
116
- * case 'user': // a custom user message
117
- * console.log(`User event ${message.topic}:`, message.message);
118
- * break;
119
- * }
120
- * });
121
- *
122
- * // Publish a custom message to every mesh member
123
- * await hotMesh.pubQuorum({
124
- * type: 'user',
125
- * topic: 'deploy.notify',
126
- * message: { version: '2.1.0', deployer: 'ci-pipeline' },
127
- * });
128
- * ```
129
- *
130
- * ## Throttling: Backpressure Across the Mesh
131
- *
132
- * Throttle commands propagate instantly to every targeted member via
133
- * the quorum channel, providing fine-grained flow control.
134
- *
135
- * ```typescript
136
- * // Pause the ENTIRE mesh (emergency stop)
137
- * await hotMesh.throttle({ throttle: -1 });
138
- *
139
- * // Resume the entire mesh
140
- * await hotMesh.throttle({ throttle: 0 });
141
- *
142
- * // Slow a specific worker topic to 1 message per 500ms
143
- * await hotMesh.throttle({ throttle: 500, topic: 'order.process' });
144
- *
145
- * // Throttle a single engine/worker instance by GUID
146
- * await hotMesh.throttle({ throttle: 2000, guid: 'abc-123' });
147
- *
148
- * // Combine: throttle a specific topic on a specific instance
149
- * await hotMesh.throttle({ throttle: 1000, guid: 'abc-123', topic: 'order.process' });
150
- * ```
151
- *
152
94
  * ## Lifecycle
153
95
  *
154
96
  * 1. **`init`** — Create an engine + workers; join the quorum.
@@ -160,7 +102,7 @@ import { StreamCode, StreamData, StreamDataResponse, StreamStatus } from '../../
160
102
  * ## Higher-Level Modules
161
103
  *
162
104
  * For most use cases, prefer the higher-level wrappers:
163
- * - **Durable** — Temporal-style durable workflow functions.
105
+ * - **Durable** — Durable workflow functions with replay and retry.
164
106
  * - **Virtual** — Virtual network functions and idempotent RPC.
165
107
  *
166
108
  * @see {@link https://hotmeshio.github.io/sdk-typescript/} - API reference
@@ -183,6 +125,10 @@ declare class HotMesh {
183
125
  workers: WorkerService[];
184
126
  logger: ILogger;
185
127
  static disconnecting: boolean;
128
+ /**
129
+ * @private
130
+ */
131
+ constructor();
186
132
  /**
187
133
  * @private
188
134
  */
@@ -192,92 +138,14 @@ declare class HotMesh {
192
138
  */
193
139
  verifyAndSetAppId(appId: string): void;
194
140
  /**
195
- * Instance initializer. Workers are configured
196
- * similarly to the engine, but as an array with
197
- * multiple worker objects.
198
- *
199
- * ## Retry Policy Configuration
200
- *
201
- * HotMesh supports retry policies with exponential backoff. Retry behavior
202
- * can be configured independently on both the `engine` and individual
203
- * `workers`. They are **not inherited**; each operates at its own level.
141
+ * Create a HotMesh instance with an engine and optional workers.
204
142
  *
205
- * - **Engine `retryPolicy`**: Stamps messages the engine publishes with
206
- * retry metadata (stored as Postgres columns). Workers that consume
207
- * these messages will use the embedded config when handling failures.
208
- * - **Worker `retryPolicy`**: Used as the fallback when the consumed
209
- * message does not carry explicit retry metadata.
143
+ * The engine manages workflow state in Postgres. Workers are callback
144
+ * functions that consume messages from Postgres streams they can
145
+ * run on the same process or on entirely separate servers.
210
146
  *
211
- * @example Basic Configuration
212
- * ```typescript
213
- * const hotMesh = await HotMesh.init({
214
- * appId: 'myapp',
215
- * engine: {
216
- * connection: {
217
- * class: Postgres,
218
- * options: {
219
- * connectionString: 'postgresql://usr:pwd@localhost:5432/db',
220
- * }
221
- * }
222
- * },
223
- * workers: [...]
224
- * });
225
- * ```
226
- *
227
- * @example Engine Retry Policy
228
- * ```typescript
229
- * const hotMesh = await HotMesh.init({
230
- * appId: 'myapp',
231
- * engine: {
232
- * connection: {
233
- * class: Postgres,
234
- * options: { connectionString: 'postgresql://...' }
235
- * },
236
- * retryPolicy: {
237
- * maximumAttempts: 5,
238
- * backoffCoefficient: 2,
239
- * maximumInterval: '300s'
240
- * }
241
- * }
242
- * });
243
- * ```
244
- *
245
- * @example Worker Retry Policy
246
- * ```typescript
247
- * const hotMesh = await HotMesh.init({
248
- * appId: 'myapp',
249
- * engine: { connection },
250
- * workers: [{
251
- * topic: 'order.process',
252
- * connection,
253
- * retryPolicy: {
254
- * maximumAttempts: 5,
255
- * backoffCoefficient: 2,
256
- * maximumInterval: '30s',
257
- * },
258
- * callback: async (data: StreamData) => {
259
- * const result = await doWork(data.data);
260
- * return {
261
- * code: 200,
262
- * status: StreamStatus.SUCCESS,
263
- * metadata: { ...data.metadata },
264
- * data: { result },
265
- * } as StreamDataResponse;
266
- * }
267
- * }]
268
- * });
269
- * ```
270
- *
271
- * **Retry Policy Options**:
272
- * - `maximumAttempts` - Maximum retry attempts before failure (default: 3)
273
- * - `backoffCoefficient` - Base for exponential backoff calculation (default: 10)
274
- * - `maximumInterval` - Maximum delay between retries in seconds or duration string (default: '120s')
275
- *
276
- * **Retry Delays**: For `backoffCoefficient: 2`, delays are: 2s, 4s, 8s, 16s, 32s...
277
- * capped at `maximumInterval`.
278
- *
279
- * **Note**: Retry policies are stored in PostgreSQL columns for efficient querying and
280
- * observability. Each retry creates a new message, preserving message immutability.
147
+ * @param config - Engine connection, worker definitions, app ID, and options.
148
+ * @returns A running HotMesh instance joined to the quorum.
281
149
  */
282
150
  static init(config: HotMeshConfig): Promise<HotMesh>;
283
151
  /**
@@ -285,485 +153,189 @@ declare class HotMesh {
285
153
  * internally by HotMesh for job IDs and GUIDs.
286
154
  */
287
155
  static guid(): string;
288
- /**
289
- * @private
290
- */
291
- initEngine(config: HotMeshConfig, logger: ILogger): Promise<void>;
292
- /**
293
- * @private
294
- */
295
- initQuorum(config: HotMeshConfig, engine: EngineService, logger: ILogger): Promise<void>;
296
- /**
297
- * @private
298
- */
299
- constructor();
300
- /**
301
- * @private
302
- */
303
- doWork(config: HotMeshConfig, logger: ILogger): Promise<void>;
304
- /**
305
- * Initialize task queue with proper precedence:
306
- * 1. Use component-specific queue if set (engine/worker)
307
- * 2. Use global config queue if set
308
- * 3. Use default queue as fallback
309
- * @private
310
- */
311
- private initTaskQueue;
312
- /**
313
- * Apply retry policy to the stream connection within a ProviderConfig or ProvidersConfig.
314
- * Handles both short-form (ProviderConfig) and long-form (ProvidersConfig) connection configs.
315
- * @private
316
- */
317
- private applyRetryPolicy;
318
156
  /**
319
157
  * Publishes a message to a workflow topic, starting a new job.
320
- * Returns the job ID immediately (fire-and-forget). Use `pubsub`
321
- * to block until the workflow completes.
158
+ * Returns the job ID immediately (fire-and-forget).
322
159
  *
323
- * @example
324
- * ```typescript
325
- * const jobId = await hotMesh.pub('order.placed', {
326
- * id: 'ORD-123',
327
- * amount: 99.99,
328
- * });
329
- * console.log(`Started job ${jobId}`);
330
- * ```
160
+ * @param topic - The workflow topic (must match a deployed graph's `subscribes`).
161
+ * @param data - Input data for the workflow.
162
+ * @returns The new job ID.
331
163
  */
332
164
  pub(topic: string, data?: JobData, context?: JobState, extended?: ExtensionType): Promise<string>;
333
165
  /**
334
- * Subscribes to all output and interim emissions from a specific
335
- * workflow topic. The callback fires each time a job on that topic
336
- * completes or emits an interim result.
166
+ * Subscribes to all output and interim emissions from a workflow topic.
337
167
  *
338
- * @example
339
- * ```typescript
340
- * await hotMesh.sub('order.fulfilled', (topic, message) => {
341
- * console.log(`Order completed:`, message.data);
342
- * });
343
- * ```
168
+ * @param topic - The topic to subscribe to.
169
+ * @param callback - Invoked with each job output or interim emission.
344
170
  */
345
171
  sub(topic: string, callback: JobMessageCallback): Promise<void>;
346
172
  /**
347
- * Unsubscribes from a single workflow topic previously registered
348
- * with `sub()`.
173
+ * Unsubscribes from a workflow topic previously registered with {@link sub}.
349
174
  */
350
175
  unsub(topic: string): Promise<void>;
351
176
  /**
352
177
  * Subscribes to workflow emissions matching a wildcard pattern.
353
- * Useful for monitoring an entire domain of workflows at once.
354
178
  *
355
- * @example
356
- * ```typescript
357
- * // Listen to all order-related workflow completions
358
- * await hotMesh.psub('order.*', (topic, message) => {
359
- * console.log(`${topic} completed:`, message.data);
360
- * });
361
- * ```
179
+ * @param wild - The wildcard pattern (e.g., `'order.*'`).
180
+ * @param callback - Invoked with each matching emission.
362
181
  */
363
182
  psub(wild: string, callback: JobMessageCallback): Promise<void>;
364
183
  /**
365
- * Unsubscribes from a wildcard pattern previously registered with `psub()`.
184
+ * Unsubscribes from a wildcard pattern previously registered with {@link psub}.
366
185
  */
367
186
  punsub(wild: string): Promise<void>;
368
187
  /**
369
- * Publishes a message to a workflow topic and blocks until the workflow
370
- * completes, returning the final job output. Internally subscribes to
371
- * the workflow's `publishes` topic before publishing, then unsubscribes
372
- * after receiving the result.
188
+ * Publishes a message and blocks until the workflow completes,
189
+ * returning the final job output. Combines {@link pub} + {@link sub}
190
+ * into a single request/response call.
373
191
  *
374
- * @example
375
- * ```typescript
376
- * const result = await hotMesh.pubsub('order.placed', {
377
- * id: 'ORD-789',
378
- * amount: 49.99,
379
- * });
380
- * console.log('Order result:', result.data);
381
- * ```
192
+ * @param topic - The workflow topic.
193
+ * @param data - Input data for the workflow.
194
+ * @param context - Optional job state context.
195
+ * @param timeout - Optional timeout in milliseconds.
196
+ * @returns The completed job output.
382
197
  */
383
198
  pubsub(topic: string, data?: JobData, context?: JobState | null, timeout?: number): Promise<JobOutput>;
384
199
  /**
385
200
  * Adds a transition message to the workstream, resuming Leg 2 of a
386
- * paused reentrant activity (e.g., `await`, `worker`, `hook`). This
387
- * is typically called by the engine internally but is exposed for
388
- * advanced use cases like custom activity implementations.
201
+ * paused reentrant activity.
202
+ * @private
389
203
  */
390
204
  add(streamData: StreamData | StreamDataResponse): Promise<string>;
391
205
  /**
392
- * Broadcasts a roll call across the mesh and collects responses from
393
- * every connected engine and worker. Each member replies with its
394
- * `QuorumProfile` including GUID, worker topic, stream depth,
395
- * throttle rate, and system health (CPU, memory, network).
206
+ * Broadcasts a PING to all connected engines and workers via
207
+ * LISTEN/NOTIFY and collects their profiles. Returns one
208
+ * {@link QuorumProfile} per responding instance, including
209
+ * cumulative message `counts`, `error_count`, `stream_depth`,
210
+ * `throttle` state, and host-level `system` health (memory/CPU).
396
211
  *
397
- * Use this for service discovery, health checks, and capacity planning.
212
+ * Use this for health checks, topology discovery, and throughput
213
+ * monitoring across the mesh.
398
214
  *
399
- * @example
400
- * ```typescript
401
- * const members = await hotMesh.rollCall();
402
- * for (const member of members) {
403
- * console.log(
404
- * `${member.engine_id} | topic=${member.worker_topic ?? 'engine'} ` +
405
- * `| throttle=${member.throttle}ms | depth=${member.stream_depth}`,
406
- * );
407
- * }
408
- * ```
215
+ * @param delay - Time in ms to wait for PONG responses (default: quorum config).
216
+ * @returns One profile per responding engine/worker instance.
409
217
  */
410
218
  rollCall(delay?: number): Promise<QuorumProfile[]>;
411
219
  /**
412
- * Broadcasts a throttle command to the mesh via the quorum channel.
413
- * Targeted members insert a delay (in milliseconds) before processing
414
- * their next stream message, providing instant backpressure control
415
- * across any combination of engines and workers.
416
- *
417
- * Throttling is **stateless** — no data is lost. Messages accumulate
418
- * in Postgres streams and are processed once the throttle is lifted.
419
- *
420
- * ## Targeting
421
- *
422
- * | Option | Effect |
423
- * |---------|--------|
424
- * | *(none)* | Throttle the **entire mesh** (all engines + all workers) |
425
- * | `topic` | Throttle all workers subscribed to this topic |
426
- * | `guid` | Throttle a single engine or worker instance |
427
- * | `topic` + `guid` | Throttle a specific topic on a specific instance |
428
- *
429
- * ## Special Values
430
- *
431
- * | Value | Effect |
432
- * |--------|--------|
433
- * | `0` | Resume normal processing (remove throttle) |
434
- * | `-1` | Pause indefinitely (emergency stop) |
435
- * | `500` | 500ms delay between messages |
220
+ * Broadcasts a throttle command to all instances. Use to slow down or
221
+ * pause message consumption across the mesh.
436
222
  *
437
- * @example
438
- * ```typescript
439
- * // Emergency stop: pause the entire mesh
440
- * await hotMesh.throttle({ throttle: -1 });
441
- *
442
- * // Resume the entire mesh
443
- * await hotMesh.throttle({ throttle: 0 });
444
- *
445
- * // Slow a specific worker topic to 1 msg per second
446
- * await hotMesh.throttle({ throttle: 1000, topic: 'order.process' });
447
- *
448
- * // Throttle a single instance by GUID
449
- * await hotMesh.throttle({ throttle: 2000, guid: 'abc-123' });
450
- *
451
- * // Throttle a specific topic on a specific instance
452
- * await hotMesh.throttle({
453
- * throttle: 500,
454
- * guid: 'abc-123',
455
- * topic: 'payment.charge',
456
- * });
457
- * ```
223
+ * @param options - Throttle rate in ms (0 = no throttle, -1 = pause indefinitely).
224
+ * Optionally scope by `guid` (single instance) or `topic` (single worker).
458
225
  */
459
226
  throttle(options: ThrottleOptions): Promise<boolean>;
460
227
  /**
461
- * Publishes a message to every mesh member via the quorum channel
462
- * (Postgres LISTEN/NOTIFY). Any `QuorumMessage` type can be sent,
463
- * but the `user` type is the most common for application-level
464
- * messaging.
465
- *
466
- * @example
467
- * ```typescript
468
- * // Broadcast a custom event to all mesh members
469
- * await hotMesh.pubQuorum({
470
- * type: 'user',
471
- * topic: 'deploy.notify',
472
- * message: { version: '2.1.0', deployer: 'ci-pipeline' },
473
- * });
474
- *
475
- * // Broadcast a config-reload signal
476
- * await hotMesh.pubQuorum({
477
- * type: 'user',
478
- * topic: 'config.reload',
479
- * message: { features: { darkMode: true } },
480
- * });
481
- * ```
228
+ * Publishes a custom message to every instance via the quorum channel.
229
+ * Register a listener with {@link subQuorum} to receive these messages.
482
230
  */
483
231
  pubQuorum(quorumMessage: QuorumMessage): Promise<boolean>;
484
232
  /**
485
- * Subscribes to the quorum channel, receiving **every** message
486
- * broadcast across the mesh in real time. This is the primary
487
- * observability hook into the service mesh — use it to monitor
488
- * version activations, throttle commands, roll call responses,
489
- * workflow completions, and custom user events.
490
- *
491
- * Messages arrive as typed `QuorumMessage` unions. Switch on
492
- * `message.type` to handle each:
493
- *
494
- * | Type | When it fires |
495
- * |-------------|---------------|
496
- * | `pong` | A mesh member responds to a roll call |
497
- * | `throttle` | A throttle command was broadcast |
498
- * | `activate` | A version activation is in progress |
499
- * | `job` | A workflow completed and published its result |
500
- * | `user` | A custom user message (via `pubQuorum`) |
501
- * | `ping` | A roll call was initiated |
502
- * | `work` | A work distribution event |
503
- * | `cron` | A cron/scheduled event |
504
- *
505
- * @example
506
- * ```typescript
507
- * // Build a real-time mesh dashboard
508
- * await hotMesh.subQuorum((topic, message) => {
509
- * switch (message.type) {
510
- * case 'pong':
511
- * dashboard.updateMember(message.guid, {
512
- * topic: message.profile?.worker_topic,
513
- * throttle: message.profile?.throttle,
514
- * depth: message.profile?.stream_depth,
515
- * cpu: message.profile?.system?.CPULoad,
516
- * });
517
- * break;
518
- *
519
- * case 'throttle':
520
- * dashboard.logThrottle(
521
- * message.throttle,
522
- * message.topic,
523
- * message.guid,
524
- * );
525
- * break;
526
- *
527
- * case 'job':
528
- * dashboard.logCompletion(message.topic, message.job);
529
- * break;
530
- *
531
- * case 'user':
532
- * dashboard.logUserEvent(message.topic, message.message);
533
- * break;
534
- * }
535
- * });
536
- * ```
537
- *
538
- * @example
539
- * ```typescript
540
- * // React to custom deployment events
541
- * await hotMesh.subQuorum((topic, message) => {
542
- * if (message.type === 'user' && message.topic === 'config.reload') {
543
- * reloadFeatureFlags(message.message);
544
- * }
545
- * });
546
- * ```
547
- *
548
- * @example
549
- * ```typescript
550
- * // Log all mesh activity for audit
551
- * await hotMesh.subQuorum((topic, message) => {
552
- * auditLog.append({
553
- * timestamp: Date.now(),
554
- * type: message.type,
555
- * guid: message.guid,
556
- * topic: message.topic,
557
- * payload: message,
558
- * });
559
- * });
560
- * ```
233
+ * Subscribes to the quorum channel to receive system messages (version
234
+ * activations, throttle commands, roll calls) and custom user messages.
561
235
  */
562
236
  subQuorum(callback: QuorumMessageCallback): Promise<void>;
563
237
  /**
564
- * Unsubscribes a callback previously registered with `subQuorum()`.
238
+ * Unsubscribes a callback previously registered with {@link subQuorum}.
565
239
  */
566
240
  unsubQuorum(callback: QuorumMessageCallback): Promise<void>;
567
- /**
568
- * Preview changes and provide an analysis of risk
569
- * prior to deployment
570
- * @private
571
- */
241
+ /** @private */
572
242
  plan(path: string): Promise<HotMeshManifest>;
573
243
  /**
574
- * Deploys a YAML workflow graph to Postgres. Accepts a file path or
575
- * an inline YAML string. Referenced `$ref` files are resolved and
576
- * merged. The deployed version is **inactive** until `activate()` is
577
- * called.
578
- *
579
- * @example
580
- * ```typescript
581
- * // Deploy from an inline YAML string
582
- * await hotMesh.deploy(`
583
- * app:
584
- * id: myapp
585
- * version: '2'
586
- * graphs:
587
- * - subscribes: order.placed
588
- * activities:
589
- * t1:
590
- * type: trigger
591
- * process:
592
- * type: worker
593
- * topic: order.process
594
- * transitions:
595
- * t1:
596
- * - to: process
597
- * `);
244
+ * Deploys a YAML workflow graph to Postgres. The graph is stored but
245
+ * remains **inactive** until {@link activate} is called.
598
246
  *
599
- * // Deploy from a file path (resolves $ref references)
600
- * await hotMesh.deploy('./workflows/order.yaml');
601
- * ```
247
+ * @param pathOrYAML - A file path or raw YAML string defining the workflow graph.
248
+ * @returns The parsed manifest with version and graph metadata.
602
249
  */
603
250
  deploy(pathOrYAML: string): Promise<HotMeshManifest>;
604
251
  /**
605
- * Activates a deployed version across the entire mesh. The quorum
606
- * coordinates a synchronized switch-over:
607
- *
608
- * 1. Roll call to verify quorum health.
609
- * 2. Broadcast `nocache` mode — all engines consult Postgres for the
610
- * active version on every request.
611
- * 3. Set the new version as active.
612
- * 4. Broadcast `cache` mode — engines resume caching.
252
+ * Activates a previously deployed version across all connected instances.
253
+ * The quorum coordinates a synchronized version switch so every engine
254
+ * and worker transitions together.
613
255
  *
614
- * The optional `delay` adds a pause (in ms) for the quorum to reach
615
- * consensus under heavy traffic. Combine with `throttle()` for
616
- * zero-downtime version switches.
617
- *
618
- * @example
619
- * ```typescript
620
- * // Simple activation
621
- * await hotMesh.activate('2');
622
- *
623
- * // With consensus delay under heavy traffic
624
- * await hotMesh.throttle({ throttle: 500 }); // slow the mesh
625
- * await hotMesh.activate('2', 2000); // activate with 2s consensus window
626
- * await hotMesh.throttle({ throttle: 0 }); // resume full speed
627
- * ```
256
+ * @param version - The version string to activate (must match a deployed graph).
257
+ * @param delay - Optional delay in ms before activation takes effect.
628
258
  */
629
259
  activate(version: string, delay?: number): Promise<boolean>;
630
260
  /**
631
- * Exports the full job state as a structured JSON object, including
632
- * activity data, transitions, and dependency chains. Useful for
633
- * debugging, auditing, and visualizing workflow execution.
261
+ * Exports the full job state (data, metadata, activity results) as
262
+ * a structured JSON object.
263
+ *
264
+ * @param jobId - The job/workflow ID.
265
+ * @param options - Export options (e.g., include activity details).
634
266
  */
635
267
  export(jobId: string, options?: ExportOptions): Promise<JobExport>;
636
268
  /**
637
- * Returns all raw key-value pairs for a job's HASH record. This is
638
- * the lowest-level read it returns internal engine fields alongside
639
- * user data. Prefer `getState()` for structured output.
269
+ * Returns all raw key-value pairs from a job's HASH record in Postgres.
270
+ * Useful for debugging or low-level inspection.
640
271
  */
641
272
  getRaw(jobId: string): Promise<StringStringType>;
642
- /**
643
- * Reporter-related method to get the status of a job
644
- * @private
645
- */
273
+ /** @private */
646
274
  getStats(topic: string, query: JobStatsInput): Promise<StatsResponse>;
647
275
  /**
648
- * Returns the numeric status semaphore for a job.
649
- *
650
- * | Value | Meaning |
651
- * |------------------|---------|
652
- * | `> 0` | Running (count of open activities) |
653
- * | `0` | Completed normally |
654
- * | `-1` | Pending (awaiting activation) |
655
- * | `< -100,000,000` | Interrupted (abnormal termination) |
276
+ * Returns the numeric status code for a job: `0` = completed,
277
+ * positive = still running, negative = interrupted/errored.
656
278
  */
657
279
  getStatus(jobId: string): Promise<JobStatus>;
658
280
  /**
659
- * Returns the structured job state (data and metadata) for a job,
660
- * scoped to the given workflow topic.
281
+ * Returns the structured job state (data + metadata). For a completed
282
+ * job this is the final output; for a running job it reflects the
283
+ * latest persisted state.
661
284
  *
662
- * @example
663
- * ```typescript
664
- * const state = await hotMesh.getState('order.placed', jobId);
665
- * console.log(state.data); // workflow output data
666
- * console.log(state.metadata); // jid, aid, timestamps, etc.
667
- * ```
285
+ * @param topic - The workflow topic.
286
+ * @param jobId - The job/workflow ID.
668
287
  */
669
288
  getState(topic: string, jobId: string): Promise<JobOutput>;
670
289
  /**
671
290
  * Returns specific searchable fields from a job's HASH record.
672
- * Pass field names to retrieve; use `":"` to read the reserved
673
- * status field.
674
291
  *
675
- * @example
676
- * ```typescript
677
- * const fields = ['orderId', 'status', '":"'];
678
- * const data = await hotMesh.getQueryState(jobId, fields);
679
- * // => { orderId: 'ORD-123', status: 'paid', ':': '0' }
680
- * ```
292
+ * @param jobId - The job/workflow ID.
293
+ * @param fields - The field names to retrieve.
681
294
  */
682
295
  getQueryState(jobId: string, fields: string[]): Promise<StringAnyType>;
683
- /**
684
- * @private
685
- */
296
+ /** @private */
686
297
  getIds(topic: string, query: JobStatsInput, queryFacets?: any[]): Promise<IdsResponse>;
687
- /**
688
- * @private
689
- */
298
+ /** @private */
690
299
  resolveQuery(topic: string, query: JobStatsInput): Promise<GetStatsOptions>;
691
300
  /**
692
- * Interrupts (terminates) an active workflow job. The job's status is
693
- * set to an error code indicating abnormal termination, and any pending
694
- * activities or timers are cancelled.
301
+ * Immediately terminates a running job. The job is marked as
302
+ * interrupted and its HASH is expired. Unlike {@link cancel}, this
303
+ * does not give the workflow a chance to run cleanup code.
695
304
  *
696
- * @example
697
- * ```typescript
698
- * await hotMesh.interrupt('order.placed', jobId, {
699
- * reason: 'Customer cancelled',
700
- * descend: true, // also interrupt child workflows
701
- * });
702
- * ```
305
+ * @param topic - The workflow topic.
306
+ * @param jobId - The job/workflow ID.
307
+ * @param options - Optional interrupt configuration.
703
308
  */
704
309
  interrupt(topic: string, jobId: string, options?: JobInterruptOptions): Promise<string>;
705
310
  /**
706
- * Immediately deletes a completed job from the system. The job must
707
- * have a non-positive status (completed or interrupted). Running jobs
708
- * must be interrupted first.
311
+ * Requests cooperative cancellation of a running job. Sets a durable
312
+ * cancel flag; the workflow detects it at its next durable operation
313
+ * and throws `CancelledFailure`, which can be caught for cleanup.
314
+ *
315
+ * @param jobId - The job/workflow ID.
709
316
  */
710
- scrub(jobId: string): Promise<void>;
317
+ cancel(jobId: string): Promise<void>;
711
318
  /**
712
- * Sends a signal to a paused workflow, resuming its execution.
713
- * The `topic` must match a hook rule defined in the YAML graph's
714
- * `hooks` section. The engine locates the exact activity and
715
- * dimension for reentry based on the hook rule's match conditions.
716
- *
717
- * Use this to deliver external data (approval decisions, webhook
718
- * payloads, partner responses) into a workflow that is sleeping
719
- * on a hook activity or awaiting a `waitFor()` signal.
720
- *
721
- * @example
722
- * ```typescript
723
- * // Resume a paused approval workflow with external data
724
- * await hotMesh.signal('order.approval', {
725
- * id: jobId,
726
- * approved: true,
727
- * reviewer: 'manager@example.com',
728
- * });
729
- * ```
730
- *
731
- * @example
732
- * ```typescript
733
- * // Signal a Durable workflow waiting on waitFor('payment-received')
734
- * await hotMesh.signal(`${appId}.wfs.signal`, {
735
- * id: 'payment-received',
736
- * data: { amount: 99.99, currency: 'USD' },
737
- * });
738
- * ```
319
+ * Immediately deletes a completed job's HASH record from Postgres.
739
320
  */
740
- signal(topic: string, data: JobData, status?: StreamStatus, code?: StreamCode): Promise<string>;
321
+ scrub(jobId: string): Promise<void>;
741
322
  /**
742
- * Fan-out variant of `signal()` that delivers data to **all**
743
- * paused workflows matching a search query. Useful for resuming
744
- * a batch of workflows waiting on the same external event.
323
+ * Sends a signal to a paused workflow, delivering data and resuming
324
+ * execution. Pairs with `condition()` in the Durable workflow API.
745
325
  *
746
- * @private
326
+ * @param topic - The signal topic.
327
+ * @param data - Signal payload.
747
328
  */
329
+ signal(topic: string, data: JobData, status?: StreamStatus, code?: StreamCode): Promise<string>;
330
+ /** @private */
748
331
  signalAll(hookTopic: string, data: JobData, query: JobStatsInput, queryFacets?: string[]): Promise<string[]>;
749
332
  /**
750
- * Stops **all** HotMesh instances in the current process — engines,
751
- * workers, and connections. Typically called in signal handlers
752
- * (`SIGTERM`, `SIGINT`) for graceful shutdown.
753
- *
754
- * @example
755
- * ```typescript
756
- * process.on('SIGTERM', async () => {
757
- * await HotMesh.stop();
758
- * process.exit(0);
759
- * });
760
- * ```
333
+ * Stops **all** HotMesh instances in the current process.
761
334
  */
762
335
  static stop(): Promise<void>;
763
336
  /**
764
- * Stops this specific HotMesh instance — its engine, quorum
765
- * membership, and all attached workers. Other instances in the
766
- * same process are unaffected.
337
+ * Stops this specific HotMesh instance — leaves the quorum and
338
+ * stops all workers. Does not affect other instances in the process.
767
339
  */
768
340
  stop(): void;
769
341
  /**
@@ -771,5 +343,42 @@ declare class HotMesh {
771
343
  * @deprecated
772
344
  */
773
345
  compress(terms: string[]): Promise<boolean>;
346
+ /**
347
+ * Register a global payload codec for encoding/decoding serialized
348
+ * object data at rest. Once registered, all object values flowing
349
+ * through the serializer are stored as `/b{encoded}` instead of
350
+ * `/s{json}`. Use this for encryption, compression, or custom encoding.
351
+ *
352
+ * The codec is global — it applies to all HotMesh and Durable instances
353
+ * in the process. Pass `null` to remove a previously registered codec.
354
+ *
355
+ * **Constraints:** The codec must be synchronous and its output must be
356
+ * a valid UTF-8 string. Use base64 encoding for binary output.
357
+ *
358
+ * @example
359
+ * ```typescript
360
+ * import { HotMesh } from '@hotmeshio/hotmesh';
361
+ *
362
+ * HotMesh.registerCodec({
363
+ * encode(json) { return Buffer.from(json).toString('base64'); },
364
+ * decode(encoded) { return Buffer.from(encoded, 'base64').toString('utf8'); },
365
+ * });
366
+ * ```
367
+ */
368
+ static registerCodec(codec: PayloadCodec | null): void;
369
+ /**
370
+ * Provision a scoped Postgres role for a worker. The role can only
371
+ * dequeue, ack, and respond on its assigned stream names via stored
372
+ * procedures — zero direct table access.
373
+ */
374
+ static provisionWorkerRole: typeof WorkerCredentials.provisionWorkerRole;
375
+ /** Rotate a secured worker role's password. */
376
+ static rotateWorkerPassword: typeof WorkerCredentials.rotateWorkerPassword;
377
+ /** Revoke a secured worker role (disables login). */
378
+ static revokeWorkerRole: typeof WorkerCredentials.revokeWorkerRole;
379
+ /** List all provisioned secured worker roles. */
380
+ static listWorkerRoles: typeof WorkerCredentials.listWorkerRoles;
774
381
  }
775
382
  export { HotMesh };
383
+ export type { PayloadCodec };
384
+ export type { WorkerCredential, WorkerCredentialInfo };