@hotmeshio/hotmesh 0.8.0 → 0.10.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.
- package/README.md +178 -43
- package/build/index.d.ts +12 -11
- package/build/index.js +15 -13
- package/build/modules/enums.d.ts +23 -34
- package/build/modules/enums.js +26 -38
- package/build/modules/errors.d.ts +16 -16
- package/build/modules/errors.js +37 -37
- package/build/package.json +63 -67
- package/build/services/activities/activity.d.ts +58 -7
- package/build/services/activities/activity.js +67 -38
- package/build/services/activities/await.d.ts +101 -0
- package/build/services/activities/await.js +101 -0
- package/build/services/activities/cycle.d.ts +82 -0
- package/build/services/activities/cycle.js +86 -8
- package/build/services/activities/hook.d.ts +139 -1
- package/build/services/activities/hook.js +140 -2
- package/build/services/activities/interrupt.d.ts +112 -0
- package/build/services/activities/interrupt.js +118 -5
- package/build/services/activities/signal.d.ts +108 -3
- package/build/services/activities/signal.js +113 -8
- package/build/services/activities/trigger.d.ts +56 -4
- package/build/services/activities/trigger.js +119 -35
- package/build/services/activities/worker.d.ts +107 -0
- package/build/services/activities/worker.js +107 -0
- package/build/services/collator/index.d.ts +3 -15
- package/build/services/collator/index.js +7 -34
- package/build/services/dba/index.d.ts +171 -0
- package/build/services/dba/index.js +280 -0
- package/build/services/{memflow → durable}/client.d.ts +3 -3
- package/build/services/{memflow → durable}/client.js +15 -15
- package/build/services/{memflow → durable}/connection.d.ts +2 -2
- package/build/services/{memflow → durable}/connection.js +1 -1
- package/build/services/{memflow → durable}/exporter.d.ts +6 -6
- package/build/services/{memflow → durable}/exporter.js +2 -2
- package/build/services/{memflow → durable}/handle.d.ts +4 -4
- package/build/services/{memflow → durable}/handle.js +3 -3
- package/build/services/{memflow → durable}/index.d.ts +126 -34
- package/build/services/{memflow → durable}/index.js +146 -50
- package/build/services/{memflow → durable}/interceptor.d.ts +45 -22
- package/build/services/{memflow → durable}/interceptor.js +54 -21
- package/build/services/{memflow → durable}/schemas/factory.d.ts +4 -4
- package/build/services/{memflow → durable}/schemas/factory.js +5 -5
- package/build/services/{memflow → durable}/search.d.ts +1 -1
- package/build/services/{memflow → durable}/search.js +4 -4
- package/build/services/{memflow → durable}/worker.d.ts +11 -11
- package/build/services/{memflow → durable}/worker.js +61 -60
- package/build/services/durable/workflow/all.d.ts +32 -0
- package/build/services/durable/workflow/all.js +40 -0
- package/build/services/{memflow → durable}/workflow/common.d.ts +5 -5
- package/build/services/durable/workflow/common.js +47 -0
- package/build/services/durable/workflow/context.d.ts +49 -0
- package/build/services/durable/workflow/context.js +88 -0
- package/build/services/durable/workflow/didRun.d.ts +27 -0
- package/build/services/durable/workflow/didRun.js +42 -0
- package/build/services/durable/workflow/emit.d.ts +50 -0
- package/build/services/durable/workflow/emit.js +68 -0
- package/build/services/durable/workflow/enrich.d.ts +37 -0
- package/build/services/durable/workflow/enrich.js +45 -0
- package/build/services/durable/workflow/entityMethods.d.ts +61 -0
- package/build/services/durable/workflow/entityMethods.js +80 -0
- package/build/services/durable/workflow/execChild.d.ts +106 -0
- package/build/services/durable/workflow/execChild.js +194 -0
- package/build/services/durable/workflow/execHook.d.ts +80 -0
- package/build/services/durable/workflow/execHook.js +97 -0
- package/build/services/durable/workflow/execHookBatch.d.ts +107 -0
- package/build/services/durable/workflow/execHookBatch.js +129 -0
- package/build/services/durable/workflow/hook.d.ts +74 -0
- package/build/services/durable/workflow/hook.js +123 -0
- package/build/services/durable/workflow/index.d.ts +129 -0
- package/build/services/{memflow → durable}/workflow/index.js +66 -11
- package/build/services/durable/workflow/interrupt.d.ts +55 -0
- package/build/services/durable/workflow/interrupt.js +70 -0
- package/build/services/durable/workflow/interruption.d.ts +61 -0
- package/build/services/durable/workflow/interruption.js +76 -0
- package/build/services/durable/workflow/isSideEffectAllowed.d.ts +27 -0
- package/build/services/{memflow → durable}/workflow/isSideEffectAllowed.js +21 -4
- package/build/services/durable/workflow/proxyActivities.d.ts +119 -0
- package/build/services/durable/workflow/proxyActivities.js +214 -0
- package/build/services/durable/workflow/random.d.ts +36 -0
- package/build/services/durable/workflow/random.js +46 -0
- package/build/services/durable/workflow/searchMethods.d.ts +53 -0
- package/build/services/durable/workflow/searchMethods.js +72 -0
- package/build/services/durable/workflow/signal.d.ts +58 -0
- package/build/services/durable/workflow/signal.js +79 -0
- package/build/services/durable/workflow/sleepFor.d.ts +63 -0
- package/build/services/durable/workflow/sleepFor.js +91 -0
- package/build/services/durable/workflow/trace.d.ts +47 -0
- package/build/services/durable/workflow/trace.js +66 -0
- package/build/services/durable/workflow/waitFor.d.ts +66 -0
- package/build/services/durable/workflow/waitFor.js +93 -0
- package/build/services/engine/index.d.ts +18 -2
- package/build/services/engine/index.js +14 -4
- package/build/services/exporter/index.d.ts +2 -0
- package/build/services/exporter/index.js +1 -0
- package/build/services/hotmesh/index.d.ts +471 -236
- package/build/services/hotmesh/index.js +473 -238
- package/build/services/store/index.d.ts +1 -1
- package/build/services/store/providers/postgres/postgres.d.ts +1 -1
- package/build/services/store/providers/postgres/postgres.js +4 -3
- package/build/services/telemetry/index.js +6 -0
- package/build/services/{meshcall → virtual}/index.d.ts +29 -29
- package/build/services/{meshcall → virtual}/index.js +49 -49
- package/build/services/{meshcall → virtual}/schemas/factory.d.ts +1 -1
- package/build/services/{meshcall → virtual}/schemas/factory.js +1 -1
- package/build/types/activity.d.ts +1 -1
- package/build/types/dba.d.ts +64 -0
- package/build/types/{memflow.d.ts → durable.d.ts} +75 -19
- package/build/types/error.d.ts +5 -5
- package/build/types/exporter.d.ts +1 -1
- package/build/types/hotmesh.d.ts +1 -1
- package/build/types/index.d.ts +5 -4
- package/build/types/job.d.ts +1 -1
- package/build/types/quorum.d.ts +2 -2
- package/build/types/{meshcall.d.ts → virtual.d.ts} +15 -15
- package/build/types/virtual.js +2 -0
- package/index.ts +15 -13
- package/package.json +63 -67
- package/vitest.config.ts +17 -0
- package/.claude/settings.local.json +0 -7
- package/build/services/memflow/workflow/all.d.ts +0 -7
- package/build/services/memflow/workflow/all.js +0 -15
- package/build/services/memflow/workflow/common.js +0 -47
- package/build/services/memflow/workflow/context.d.ts +0 -6
- package/build/services/memflow/workflow/context.js +0 -45
- package/build/services/memflow/workflow/didRun.d.ts +0 -7
- package/build/services/memflow/workflow/didRun.js +0 -22
- package/build/services/memflow/workflow/emit.d.ts +0 -11
- package/build/services/memflow/workflow/emit.js +0 -29
- package/build/services/memflow/workflow/enrich.d.ts +0 -9
- package/build/services/memflow/workflow/enrich.js +0 -17
- package/build/services/memflow/workflow/entityMethods.d.ts +0 -14
- package/build/services/memflow/workflow/entityMethods.js +0 -33
- package/build/services/memflow/workflow/execChild.d.ts +0 -18
- package/build/services/memflow/workflow/execChild.js +0 -106
- package/build/services/memflow/workflow/execHook.d.ts +0 -65
- package/build/services/memflow/workflow/execHook.js +0 -83
- package/build/services/memflow/workflow/execHookBatch.d.ts +0 -54
- package/build/services/memflow/workflow/execHookBatch.js +0 -77
- package/build/services/memflow/workflow/hook.d.ts +0 -9
- package/build/services/memflow/workflow/hook.js +0 -58
- package/build/services/memflow/workflow/index.d.ts +0 -74
- package/build/services/memflow/workflow/interrupt.d.ts +0 -9
- package/build/services/memflow/workflow/interrupt.js +0 -24
- package/build/services/memflow/workflow/interruption.d.ts +0 -28
- package/build/services/memflow/workflow/interruption.js +0 -43
- package/build/services/memflow/workflow/isSideEffectAllowed.d.ts +0 -10
- package/build/services/memflow/workflow/proxyActivities.d.ts +0 -91
- package/build/services/memflow/workflow/proxyActivities.js +0 -176
- package/build/services/memflow/workflow/random.d.ts +0 -6
- package/build/services/memflow/workflow/random.js +0 -16
- package/build/services/memflow/workflow/searchMethods.d.ts +0 -6
- package/build/services/memflow/workflow/searchMethods.js +0 -25
- package/build/services/memflow/workflow/signal.d.ts +0 -29
- package/build/services/memflow/workflow/signal.js +0 -50
- package/build/services/memflow/workflow/sleepFor.d.ts +0 -24
- package/build/services/memflow/workflow/sleepFor.js +0 -52
- package/build/services/memflow/workflow/trace.d.ts +0 -14
- package/build/services/memflow/workflow/trace.js +0 -33
- package/build/services/memflow/workflow/waitFor.d.ts +0 -29
- package/build/services/memflow/workflow/waitFor.js +0 -56
- /package/build/services/{memflow → durable}/entity.d.ts +0 -0
- /package/build/services/{memflow → durable}/entity.js +0 -0
- /package/build/types/{memflow.js → dba.js} +0 -0
- /package/build/types/{meshcall.js → durable.js} +0 -0
|
@@ -10,178 +10,160 @@ 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
12
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
13
|
+
* A distributed service mesh that turns Postgres into a durable workflow
|
|
14
|
+
* orchestration engine. Every `HotMesh.init()` call creates a **point of
|
|
15
|
+
* presence** — an engine, a quorum member, and zero or more workers — that
|
|
16
|
+
* collaborates with its peers through Postgres LISTEN/NOTIFY to form a
|
|
17
|
+
* self-coordinating mesh with no external dependencies.
|
|
15
18
|
*
|
|
16
|
-
* ##
|
|
19
|
+
* ## Service Mesh Architecture
|
|
17
20
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* - **Pattern Matching**: Pub/sub with wildcard pattern support
|
|
24
|
-
* - **Throttling**: Dynamic flow control and backpressure management
|
|
25
|
-
* - **Retry Policies**: PostgreSQL-native retry configuration with exponential backoff
|
|
21
|
+
* Each HotMesh instance joins a **quorum** — a real-time pub/sub channel
|
|
22
|
+
* backed by Postgres LISTEN/NOTIFY. The quorum is the mesh's nervous
|
|
23
|
+
* system: version activations, throttle commands, roll calls, and custom
|
|
24
|
+
* user messages all propagate instantly to every connected engine and
|
|
25
|
+
* worker across all processes and servers.
|
|
26
26
|
*
|
|
27
|
-
* ##
|
|
27
|
+
* ## Quick Start
|
|
28
28
|
*
|
|
29
|
-
* HotMesh consists of several specialized modules:
|
|
30
|
-
* - **HotMesh**: Core orchestration engine (this class)
|
|
31
|
-
* - **MemFlow**: Temporal.io-compatible workflow framework
|
|
32
|
-
* - **MeshCall**: Durable function execution (Temporal-like clone)
|
|
33
|
-
*
|
|
34
|
-
* ## Lifecycle Overview
|
|
35
|
-
*
|
|
36
|
-
* 1. **Initialize**: Create HotMesh instance with provider configuration
|
|
37
|
-
* 2. **Deploy**: Upload YAML workflow definitions to the backend
|
|
38
|
-
* 3. **Activate**: Coordinate quorum to enable the workflow version
|
|
39
|
-
* 4. **Execute**: Publish events to trigger workflow execution
|
|
40
|
-
* 5. **Monitor**: Track progress via OpenTelemetry and built-in observability
|
|
41
|
-
*
|
|
42
|
-
* ## Basic Usage
|
|
43
|
-
*
|
|
44
|
-
* @example
|
|
45
29
|
* ```typescript
|
|
46
30
|
* import { HotMesh } from '@hotmeshio/hotmesh';
|
|
47
31
|
* import { Client as Postgres } from 'pg';
|
|
48
32
|
*
|
|
49
|
-
* // Initialize with Postgres backend
|
|
50
33
|
* const hotMesh = await HotMesh.init({
|
|
51
|
-
* appId: '
|
|
34
|
+
* appId: 'myapp',
|
|
52
35
|
* engine: {
|
|
53
36
|
* connection: {
|
|
54
37
|
* class: Postgres,
|
|
55
|
-
* options: {
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
38
|
+
* options: { connectionString: 'postgresql://usr:pwd@localhost:5432/db' },
|
|
39
|
+
* },
|
|
40
|
+
* },
|
|
41
|
+
* workers: [{
|
|
42
|
+
* topic: 'order.process',
|
|
43
|
+
* connection: {
|
|
44
|
+
* class: Postgres,
|
|
45
|
+
* options: { connectionString: 'postgresql://usr:pwd@localhost:5432/db' },
|
|
46
|
+
* },
|
|
47
|
+
* callback: async (data) => ({
|
|
48
|
+
* metadata: { ...data.metadata },
|
|
49
|
+
* data: { orderId: data.data.id, status: 'fulfilled' },
|
|
50
|
+
* }),
|
|
51
|
+
* }],
|
|
60
52
|
* });
|
|
61
53
|
*
|
|
62
|
-
* // Deploy workflow
|
|
54
|
+
* // Deploy a YAML workflow graph
|
|
63
55
|
* await hotMesh.deploy(`
|
|
64
56
|
* app:
|
|
65
|
-
* id:
|
|
57
|
+
* id: myapp
|
|
66
58
|
* version: '1'
|
|
67
59
|
* graphs:
|
|
68
|
-
* - subscribes: order.
|
|
60
|
+
* - subscribes: order.placed
|
|
61
|
+
* publishes: order.fulfilled
|
|
62
|
+
* expire: 600
|
|
63
|
+
*
|
|
69
64
|
* activities:
|
|
70
|
-
*
|
|
71
|
-
* type:
|
|
72
|
-
*
|
|
73
|
-
* approve:
|
|
74
|
-
* type: hook
|
|
75
|
-
* topic: order.approve
|
|
76
|
-
* fulfill:
|
|
65
|
+
* t1:
|
|
66
|
+
* type: trigger
|
|
67
|
+
* process:
|
|
77
68
|
* type: worker
|
|
78
|
-
* topic: order.
|
|
69
|
+
* topic: order.process
|
|
70
|
+
* input:
|
|
71
|
+
* schema:
|
|
72
|
+
* type: object
|
|
73
|
+
* properties:
|
|
74
|
+
* id: { type: string }
|
|
75
|
+
* maps:
|
|
76
|
+
* id: '{t1.output.data.id}'
|
|
79
77
|
* transitions:
|
|
80
|
-
*
|
|
81
|
-
* - to:
|
|
82
|
-
* approve:
|
|
83
|
-
* - to: fulfill
|
|
78
|
+
* t1:
|
|
79
|
+
* - to: process
|
|
84
80
|
* `);
|
|
85
81
|
*
|
|
86
|
-
* // Activate the workflow version
|
|
87
82
|
* await hotMesh.activate('1');
|
|
88
83
|
*
|
|
89
|
-
* //
|
|
90
|
-
* const jobId = await hotMesh.pub('order.
|
|
91
|
-
* orderId: '12345',
|
|
92
|
-
* amount: 99.99
|
|
93
|
-
* });
|
|
84
|
+
* // Fire-and-forget
|
|
85
|
+
* const jobId = await hotMesh.pub('order.placed', { id: 'ORD-123' });
|
|
94
86
|
*
|
|
95
|
-
* //
|
|
96
|
-
* const result = await hotMesh.pubsub('order.
|
|
97
|
-
* orderId: '12345',
|
|
98
|
-
* amount: 99.99
|
|
99
|
-
* });
|
|
87
|
+
* // Request/response (blocks until workflow completes)
|
|
88
|
+
* const result = await hotMesh.pubsub('order.placed', { id: 'ORD-456' });
|
|
100
89
|
* ```
|
|
101
90
|
*
|
|
102
|
-
* ##
|
|
91
|
+
* ## Quorum: The Mesh Control Plane
|
|
103
92
|
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
* import { HotMesh } from '@hotmeshio/hotmesh';
|
|
107
|
-
* import { Client as Postgres } from 'pg';
|
|
93
|
+
* The quorum channel is a broadcast bus available to every mesh member.
|
|
94
|
+
* Use it for operational control, observability, and custom messaging.
|
|
108
95
|
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
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;
|
|
118
119
|
* }
|
|
119
120
|
* });
|
|
120
|
-
* ```
|
|
121
121
|
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
* console.log(`Received ${topic}:`, message);
|
|
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' },
|
|
128
127
|
* });
|
|
129
128
|
* ```
|
|
130
129
|
*
|
|
131
|
-
*
|
|
132
|
-
* ```typescript
|
|
133
|
-
* // Pause all processing for 5 seconds
|
|
134
|
-
* await hotMesh.throttle({ throttle: 5000 });
|
|
135
|
-
*
|
|
136
|
-
* // Emergency stop (pause indefinitely)
|
|
137
|
-
* await hotMesh.throttle({ throttle: -1 });
|
|
138
|
-
* ```
|
|
130
|
+
* ## Throttling: Backpressure Across the Mesh
|
|
139
131
|
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
* await hotMesh.interrupt('order.process', jobId, {
|
|
143
|
-
* reason: 'User cancellation'
|
|
144
|
-
* });
|
|
145
|
-
* ```
|
|
132
|
+
* Throttle commands propagate instantly to every targeted member via
|
|
133
|
+
* the quorum channel, providing fine-grained flow control.
|
|
146
134
|
*
|
|
147
|
-
* **State Inspection**: Query workflow state and progress
|
|
148
135
|
* ```typescript
|
|
149
|
-
*
|
|
150
|
-
*
|
|
151
|
-
* ```
|
|
136
|
+
* // Pause the ENTIRE mesh (emergency stop)
|
|
137
|
+
* await hotMesh.throttle({ throttle: -1 });
|
|
152
138
|
*
|
|
153
|
-
*
|
|
139
|
+
* // Resume the entire mesh
|
|
140
|
+
* await hotMesh.throttle({ throttle: 0 });
|
|
154
141
|
*
|
|
155
|
-
*
|
|
142
|
+
* // Slow a specific worker topic to 1 message per 500ms
|
|
143
|
+
* await hotMesh.throttle({ throttle: 500, topic: 'order.process' });
|
|
156
144
|
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
* const members = await hotMesh.rollCall();
|
|
145
|
+
* // Throttle a single engine/worker instance by GUID
|
|
146
|
+
* await hotMesh.throttle({ throttle: 2000, guid: 'abc-123' });
|
|
160
147
|
*
|
|
161
|
-
* //
|
|
162
|
-
* await hotMesh.
|
|
148
|
+
* // Combine: throttle a specific topic on a specific instance
|
|
149
|
+
* await hotMesh.throttle({ throttle: 1000, guid: 'abc-123', topic: 'order.process' });
|
|
163
150
|
* ```
|
|
164
151
|
*
|
|
165
|
-
* ##
|
|
152
|
+
* ## Lifecycle
|
|
166
153
|
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
154
|
+
* 1. **`init`** — Create an engine + workers; join the quorum.
|
|
155
|
+
* 2. **`deploy`** — Upload a YAML graph to Postgres (inactive).
|
|
156
|
+
* 3. **`activate`** — Coordinate the quorum to switch to the new version.
|
|
157
|
+
* 4. **`pub` / `pubsub`** — Trigger workflow execution.
|
|
158
|
+
* 5. **`stop`** — Leave the quorum and release connections.
|
|
170
159
|
*
|
|
171
|
-
* ##
|
|
160
|
+
* ## Higher-Level Modules
|
|
172
161
|
*
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
* hotMesh.stop();
|
|
162
|
+
* For most use cases, prefer the higher-level wrappers:
|
|
163
|
+
* - **Durable** — Temporal-style durable workflow functions.
|
|
164
|
+
* - **Virtual** — Virtual network functions and idempotent RPC.
|
|
177
165
|
*
|
|
178
|
-
*
|
|
179
|
-
* await HotMesh.stop();
|
|
180
|
-
* ```
|
|
181
|
-
*
|
|
182
|
-
* @see {@link https://docs.hotmesh.io/} - Complete documentation
|
|
183
|
-
* @see {@link https://github.com/hotmeshio/samples-typescript} - Examples and tutorials
|
|
184
|
-
* @see {@link https://zenodo.org/records/12168558} - White paper on the architecture
|
|
166
|
+
* @see {@link https://hotmeshio.github.io/sdk-typescript/} - API reference
|
|
185
167
|
*/
|
|
186
168
|
declare class HotMesh {
|
|
187
169
|
namespace: string;
|
|
@@ -216,12 +198,19 @@ declare class HotMesh {
|
|
|
216
198
|
*
|
|
217
199
|
* ## Retry Policy Configuration
|
|
218
200
|
*
|
|
219
|
-
* HotMesh supports
|
|
220
|
-
*
|
|
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.
|
|
204
|
+
*
|
|
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.
|
|
221
210
|
*
|
|
222
211
|
* @example Basic Configuration
|
|
223
212
|
* ```typescript
|
|
224
|
-
* const
|
|
213
|
+
* const hotMesh = await HotMesh.init({
|
|
225
214
|
* appId: 'myapp',
|
|
226
215
|
* engine: {
|
|
227
216
|
* connection: {
|
|
@@ -231,46 +220,49 @@ declare class HotMesh {
|
|
|
231
220
|
* }
|
|
232
221
|
* }
|
|
233
222
|
* },
|
|
234
|
-
* workers [...]
|
|
235
|
-
* };
|
|
236
|
-
* const hotMesh = await HotMesh.init(config);
|
|
223
|
+
* workers: [...]
|
|
224
|
+
* });
|
|
237
225
|
* ```
|
|
238
226
|
*
|
|
239
|
-
* @example
|
|
227
|
+
* @example Engine Retry Policy
|
|
240
228
|
* ```typescript
|
|
241
|
-
* import { HotMesh } from '@hotmeshio/hotmesh';
|
|
242
|
-
* import { Client as Postgres } from 'pg';
|
|
243
|
-
*
|
|
244
229
|
* const hotMesh = await HotMesh.init({
|
|
245
|
-
* appId: '
|
|
230
|
+
* appId: 'myapp',
|
|
246
231
|
* engine: {
|
|
247
232
|
* connection: {
|
|
248
233
|
* class: Postgres,
|
|
249
234
|
* options: { connectionString: 'postgresql://...' }
|
|
250
235
|
* },
|
|
251
|
-
* // Default retry policy for engine streams
|
|
252
236
|
* retryPolicy: {
|
|
253
|
-
* maximumAttempts: 5,
|
|
254
|
-
* backoffCoefficient: 2,
|
|
255
|
-
* maximumInterval: '300s'
|
|
237
|
+
* maximumAttempts: 5,
|
|
238
|
+
* backoffCoefficient: 2,
|
|
239
|
+
* maximumInterval: '300s'
|
|
256
240
|
* }
|
|
257
|
-
* }
|
|
241
|
+
* }
|
|
242
|
+
* });
|
|
243
|
+
* ```
|
|
244
|
+
*
|
|
245
|
+
* @example Worker Retry Policy
|
|
246
|
+
* ```typescript
|
|
247
|
+
* const hotMesh = await HotMesh.init({
|
|
248
|
+
* appId: 'myapp',
|
|
249
|
+
* engine: { connection },
|
|
258
250
|
* workers: [{
|
|
259
251
|
* topic: 'order.process',
|
|
260
|
-
* connection
|
|
261
|
-
* class: Postgres,
|
|
262
|
-
* options: { connectionString: 'postgresql://...' }
|
|
263
|
-
* },
|
|
264
|
-
* // Worker-specific retry policy
|
|
252
|
+
* connection,
|
|
265
253
|
* retryPolicy: {
|
|
266
|
-
* maximumAttempts:
|
|
267
|
-
* backoffCoefficient:
|
|
268
|
-
* maximumInterval: '
|
|
254
|
+
* maximumAttempts: 5,
|
|
255
|
+
* backoffCoefficient: 2,
|
|
256
|
+
* maximumInterval: '30s',
|
|
269
257
|
* },
|
|
270
|
-
* callback: async (data) => {
|
|
271
|
-
*
|
|
272
|
-
*
|
|
273
|
-
*
|
|
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;
|
|
274
266
|
* }
|
|
275
267
|
* }]
|
|
276
268
|
* });
|
|
@@ -289,8 +281,8 @@ declare class HotMesh {
|
|
|
289
281
|
*/
|
|
290
282
|
static init(config: HotMeshConfig): Promise<HotMesh>;
|
|
291
283
|
/**
|
|
292
|
-
*
|
|
293
|
-
*
|
|
284
|
+
* Generates a unique ID using the same nanoid generator used
|
|
285
|
+
* internally by HotMesh for job IDs and GUIDs.
|
|
294
286
|
*/
|
|
295
287
|
static guid(): string;
|
|
296
288
|
/**
|
|
@@ -324,96 +316,252 @@ declare class HotMesh {
|
|
|
324
316
|
*/
|
|
325
317
|
private applyRetryPolicy;
|
|
326
318
|
/**
|
|
327
|
-
*
|
|
319
|
+
* 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.
|
|
322
|
+
*
|
|
328
323
|
* @example
|
|
329
324
|
* ```typescript
|
|
330
|
-
* await hotMesh.pub('
|
|
325
|
+
* const jobId = await hotMesh.pub('order.placed', {
|
|
326
|
+
* id: 'ORD-123',
|
|
327
|
+
* amount: 99.99,
|
|
328
|
+
* });
|
|
329
|
+
* console.log(`Started job ${jobId}`);
|
|
331
330
|
* ```
|
|
332
331
|
*/
|
|
333
332
|
pub(topic: string, data?: JobData, context?: JobState, extended?: ExtensionType): Promise<string>;
|
|
334
333
|
/**
|
|
335
|
-
*
|
|
336
|
-
* workflow topic.
|
|
337
|
-
*
|
|
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.
|
|
338
337
|
*
|
|
339
338
|
* @example
|
|
340
339
|
* ```typescript
|
|
341
|
-
* await hotMesh.
|
|
342
|
-
*
|
|
340
|
+
* await hotMesh.sub('order.fulfilled', (topic, message) => {
|
|
341
|
+
* console.log(`Order completed:`, message.data);
|
|
343
342
|
* });
|
|
344
343
|
* ```
|
|
345
344
|
*/
|
|
346
345
|
sub(topic: string, callback: JobMessageCallback): Promise<void>;
|
|
347
346
|
/**
|
|
348
|
-
*
|
|
347
|
+
* Unsubscribes from a single workflow topic previously registered
|
|
348
|
+
* with `sub()`.
|
|
349
349
|
*/
|
|
350
350
|
unsub(topic: string): Promise<void>;
|
|
351
351
|
/**
|
|
352
|
-
*
|
|
353
|
-
*
|
|
352
|
+
* Subscribes to workflow emissions matching a wildcard pattern.
|
|
353
|
+
* Useful for monitoring an entire domain of workflows at once.
|
|
354
|
+
*
|
|
354
355
|
* @example
|
|
355
356
|
* ```typescript
|
|
356
|
-
*
|
|
357
|
-
*
|
|
357
|
+
* // Listen to all order-related workflow completions
|
|
358
|
+
* await hotMesh.psub('order.*', (topic, message) => {
|
|
359
|
+
* console.log(`${topic} completed:`, message.data);
|
|
358
360
|
* });
|
|
359
361
|
* ```
|
|
360
362
|
*/
|
|
361
363
|
psub(wild: string, callback: JobMessageCallback): Promise<void>;
|
|
362
364
|
/**
|
|
363
|
-
*
|
|
364
|
-
* unsubscription, so this method is not supported for Postgres.
|
|
365
|
+
* Unsubscribes from a wildcard pattern previously registered with `psub()`.
|
|
365
366
|
*/
|
|
366
367
|
punsub(wild: string): Promise<void>;
|
|
367
368
|
/**
|
|
368
|
-
*
|
|
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.
|
|
373
|
+
*
|
|
369
374
|
* @example
|
|
370
375
|
* ```typescript
|
|
371
|
-
* await hotMesh.pubsub('
|
|
376
|
+
* const result = await hotMesh.pubsub('order.placed', {
|
|
377
|
+
* id: 'ORD-789',
|
|
378
|
+
* amount: 49.99,
|
|
379
|
+
* });
|
|
380
|
+
* console.log('Order result:', result.data);
|
|
372
381
|
* ```
|
|
373
382
|
*/
|
|
374
383
|
pubsub(topic: string, data?: JobData, context?: JobState | null, timeout?: number): Promise<JobOutput>;
|
|
375
384
|
/**
|
|
376
|
-
*
|
|
377
|
-
* reentrant activity (e.g., await
|
|
385
|
+
* 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.
|
|
378
389
|
*/
|
|
379
390
|
add(streamData: StreamData | StreamDataResponse): Promise<string>;
|
|
380
391
|
/**
|
|
381
|
-
*
|
|
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).
|
|
396
|
+
*
|
|
397
|
+
* Use this for service discovery, health checks, and capacity planning.
|
|
398
|
+
*
|
|
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
|
+
* ```
|
|
382
409
|
*/
|
|
383
410
|
rollCall(delay?: number): Promise<QuorumProfile[]>;
|
|
384
411
|
/**
|
|
385
|
-
*
|
|
386
|
-
*
|
|
387
|
-
*
|
|
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.
|
|
388
419
|
*
|
|
389
|
-
*
|
|
390
|
-
* before processing the next message. Target specific engines and
|
|
391
|
-
* workers by passing a `guid` and/or `topic`. Pass no arguments to
|
|
392
|
-
* throttle the entire quorum.
|
|
420
|
+
* ## Targeting
|
|
393
421
|
*
|
|
394
|
-
*
|
|
395
|
-
*
|
|
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 |
|
|
396
428
|
*
|
|
397
|
-
*
|
|
398
|
-
* and down with no loss of data.
|
|
429
|
+
* ## Special Values
|
|
399
430
|
*
|
|
431
|
+
* | Value | Effect |
|
|
432
|
+
* |--------|--------|
|
|
433
|
+
* | `0` | Resume normal processing (remove throttle) |
|
|
434
|
+
* | `-1` | Pause indefinitely (emergency stop) |
|
|
435
|
+
* | `500` | 500ms delay between messages |
|
|
400
436
|
*
|
|
401
437
|
* @example
|
|
402
438
|
* ```typescript
|
|
439
|
+
* // Emergency stop: pause the entire mesh
|
|
403
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
|
+
* });
|
|
404
457
|
* ```
|
|
405
458
|
*/
|
|
406
459
|
throttle(options: ThrottleOptions): Promise<boolean>;
|
|
407
460
|
/**
|
|
408
|
-
*
|
|
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
|
+
* ```
|
|
409
482
|
*/
|
|
410
483
|
pubQuorum(quorumMessage: QuorumMessage): Promise<boolean>;
|
|
411
484
|
/**
|
|
412
|
-
*
|
|
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
|
+
* ```
|
|
413
561
|
*/
|
|
414
562
|
subQuorum(callback: QuorumMessageCallback): Promise<void>;
|
|
415
563
|
/**
|
|
416
|
-
*
|
|
564
|
+
* Unsubscribes a callback previously registered with `subQuorum()`.
|
|
417
565
|
*/
|
|
418
566
|
unsubQuorum(callback: QuorumMessageCallback): Promise<void>;
|
|
419
567
|
/**
|
|
@@ -423,37 +571,72 @@ declare class HotMesh {
|
|
|
423
571
|
*/
|
|
424
572
|
plan(path: string): Promise<HotMeshManifest>;
|
|
425
573
|
/**
|
|
426
|
-
*
|
|
427
|
-
*
|
|
428
|
-
*
|
|
429
|
-
*
|
|
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
|
+
* `);
|
|
430
598
|
*
|
|
431
|
-
*
|
|
599
|
+
* // Deploy from a file path (resolves $ref references)
|
|
600
|
+
* await hotMesh.deploy('./workflows/order.yaml');
|
|
601
|
+
* ```
|
|
432
602
|
*/
|
|
433
603
|
deploy(pathOrYAML: string): Promise<HotMeshManifest>;
|
|
434
604
|
/**
|
|
435
|
-
*
|
|
436
|
-
*
|
|
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.
|
|
613
|
+
*
|
|
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.
|
|
437
617
|
*
|
|
438
|
-
*
|
|
439
|
-
*
|
|
440
|
-
*
|
|
441
|
-
*
|
|
442
|
-
* call is processed. This ensures that all engines are running the same version
|
|
443
|
-
* of the app, switching over at the same moment and then enabling `cache` mode
|
|
444
|
-
* to improve performance.
|
|
618
|
+
* @example
|
|
619
|
+
* ```typescript
|
|
620
|
+
* // Simple activation
|
|
621
|
+
* await hotMesh.activate('2');
|
|
445
622
|
*
|
|
446
|
-
*
|
|
447
|
-
*
|
|
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
|
+
* ```
|
|
448
628
|
*/
|
|
449
629
|
activate(version: string, delay?: number): Promise<boolean>;
|
|
450
630
|
/**
|
|
451
|
-
*
|
|
452
|
-
*
|
|
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.
|
|
453
634
|
*/
|
|
454
635
|
export(jobId: string): Promise<JobExport>;
|
|
455
636
|
/**
|
|
456
|
-
* Returns all
|
|
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.
|
|
457
640
|
*/
|
|
458
641
|
getRaw(jobId: string): Promise<StringStringType>;
|
|
459
642
|
/**
|
|
@@ -462,32 +645,38 @@ declare class HotMesh {
|
|
|
462
645
|
*/
|
|
463
646
|
getStats(topic: string, query: JobStatsInput): Promise<StatsResponse>;
|
|
464
647
|
/**
|
|
465
|
-
* Returns the status
|
|
466
|
-
*
|
|
467
|
-
*
|
|
468
|
-
*
|
|
469
|
-
*
|
|
470
|
-
*
|
|
471
|
-
*
|
|
472
|
-
*
|
|
473
|
-
* positive value are still running.
|
|
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) |
|
|
474
656
|
*/
|
|
475
657
|
getStatus(jobId: string): Promise<JobStatus>;
|
|
476
658
|
/**
|
|
477
|
-
* Returns the job state (data and metadata) for a job
|
|
659
|
+
* Returns the structured job state (data and metadata) for a job,
|
|
660
|
+
* scoped to the given workflow topic.
|
|
661
|
+
*
|
|
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
|
+
* ```
|
|
478
668
|
*/
|
|
479
669
|
getState(topic: string, jobId: string): Promise<JobOutput>;
|
|
480
670
|
/**
|
|
481
|
-
* Returns searchable
|
|
482
|
-
*
|
|
483
|
-
*
|
|
484
|
-
* it can be read but not written).
|
|
671
|
+
* Returns specific searchable fields from a job's HASH record.
|
|
672
|
+
* Pass field names to retrieve; use `":"` to read the reserved
|
|
673
|
+
* status field.
|
|
485
674
|
*
|
|
486
675
|
* @example
|
|
487
676
|
* ```typescript
|
|
488
|
-
* const fields = ['
|
|
489
|
-
* const
|
|
490
|
-
* //
|
|
677
|
+
* const fields = ['orderId', 'status', '":"'];
|
|
678
|
+
* const data = await hotMesh.getQueryState(jobId, fields);
|
|
679
|
+
* // => { orderId: 'ORD-123', status: 'paid', ':': '0' }
|
|
491
680
|
* ```
|
|
492
681
|
*/
|
|
493
682
|
getQueryState(jobId: string, fields: string[]): Promise<StringAnyType>;
|
|
@@ -500,35 +689,81 @@ declare class HotMesh {
|
|
|
500
689
|
*/
|
|
501
690
|
resolveQuery(topic: string, query: JobStatsInput): Promise<GetStatsOptions>;
|
|
502
691
|
/**
|
|
503
|
-
*
|
|
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.
|
|
695
|
+
*
|
|
696
|
+
* @example
|
|
697
|
+
* ```typescript
|
|
698
|
+
* await hotMesh.interrupt('order.placed', jobId, {
|
|
699
|
+
* reason: 'Customer cancelled',
|
|
700
|
+
* descend: true, // also interrupt child workflows
|
|
701
|
+
* });
|
|
702
|
+
* ```
|
|
504
703
|
*/
|
|
505
704
|
interrupt(topic: string, jobId: string, options?: JobInterruptOptions): Promise<string>;
|
|
506
705
|
/**
|
|
507
|
-
* Immediately deletes
|
|
508
|
-
*
|
|
509
|
-
*
|
|
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.
|
|
510
709
|
*/
|
|
511
710
|
scrub(jobId: string): Promise<void>;
|
|
512
711
|
/**
|
|
513
|
-
*
|
|
514
|
-
*
|
|
515
|
-
*
|
|
516
|
-
*
|
|
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.
|
|
517
716
|
*
|
|
518
|
-
*
|
|
519
|
-
*
|
|
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
|
+
* ```
|
|
520
739
|
*/
|
|
521
|
-
|
|
740
|
+
signal(topic: string, data: JobData, status?: StreamStatus, code?: StreamCode): Promise<string>;
|
|
522
741
|
/**
|
|
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.
|
|
745
|
+
*
|
|
523
746
|
* @private
|
|
524
747
|
*/
|
|
525
|
-
|
|
748
|
+
signalAll(hookTopic: string, data: JobData, query: JobStatsInput, queryFacets?: string[]): Promise<string[]>;
|
|
526
749
|
/**
|
|
527
|
-
*
|
|
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
|
+
* ```
|
|
528
761
|
*/
|
|
529
762
|
static stop(): Promise<void>;
|
|
530
763
|
/**
|
|
531
|
-
*
|
|
764
|
+
* Stops this specific HotMesh instance — its engine, quorum
|
|
765
|
+
* membership, and all attached workers. Other instances in the
|
|
766
|
+
* same process are unaffected.
|
|
532
767
|
*/
|
|
533
768
|
stop(): void;
|
|
534
769
|
/**
|