@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.
- package/README.md +18 -22
- package/build/modules/enums.d.ts +60 -5
- package/build/modules/enums.js +62 -7
- package/build/modules/errors.d.ts +15 -2
- package/build/modules/errors.js +17 -1
- package/build/modules/storage.d.ts +1 -0
- package/build/modules/storage.js +2 -1
- package/build/package.json +8 -2
- package/build/services/activities/activity/context.d.ts +22 -0
- package/build/services/activities/activity/context.js +76 -0
- package/build/services/activities/activity/index.d.ts +116 -0
- package/build/services/activities/activity/index.js +299 -0
- package/build/services/activities/activity/mapping.d.ts +12 -0
- package/build/services/activities/activity/mapping.js +63 -0
- package/build/services/activities/activity/process.d.ts +28 -0
- package/build/services/activities/activity/process.js +100 -0
- package/build/services/activities/activity/protocol.d.ts +39 -0
- package/build/services/activities/activity/protocol.js +151 -0
- package/build/services/activities/activity/state.d.ts +40 -0
- package/build/services/activities/activity/state.js +143 -0
- package/build/services/activities/activity/transition.d.ts +23 -0
- package/build/services/activities/activity/transition.js +71 -0
- package/build/services/activities/activity/verify.d.ts +22 -0
- package/build/services/activities/activity/verify.js +85 -0
- package/build/services/activities/await.d.ts +1 -4
- package/build/services/activities/await.js +2 -36
- package/build/services/activities/cycle.d.ts +1 -11
- package/build/services/activities/cycle.js +3 -46
- package/build/services/activities/hook.d.ts +2 -11
- package/build/services/activities/hook.js +30 -50
- package/build/services/activities/interrupt.d.ts +2 -4
- package/build/services/activities/interrupt.js +4 -38
- package/build/services/activities/signal.d.ts +1 -11
- package/build/services/activities/signal.js +3 -48
- package/build/services/activities/trigger.d.ts +1 -3
- package/build/services/activities/trigger.js +0 -3
- package/build/services/activities/worker.d.ts +3 -6
- package/build/services/activities/worker.js +4 -40
- package/build/services/connector/factory.d.ts +6 -0
- package/build/services/connector/factory.js +24 -0
- package/build/services/dba/index.d.ts +14 -4
- package/build/services/dba/index.js +57 -18
- package/build/services/durable/activity.d.ts +30 -0
- package/build/services/durable/activity.js +46 -0
- package/build/services/durable/client.d.ts +26 -31
- package/build/services/durable/client.js +26 -31
- package/build/services/durable/connection.d.ts +13 -7
- package/build/services/durable/connection.js +13 -7
- package/build/services/durable/exporter.d.ts +2 -2
- package/build/services/durable/exporter.js +27 -12
- package/build/services/durable/handle.d.ts +59 -41
- package/build/services/durable/handle.js +61 -41
- package/build/services/durable/index.d.ts +152 -283
- package/build/services/durable/index.js +161 -289
- package/build/services/durable/interceptor.d.ts +43 -33
- package/build/services/durable/interceptor.js +59 -39
- package/build/services/durable/schemas/factory.d.ts +2 -3
- package/build/services/durable/schemas/factory.js +180 -30
- package/build/services/durable/telemetry.d.ts +80 -0
- package/build/services/durable/telemetry.js +137 -0
- package/build/services/durable/worker.d.ts +100 -21
- package/build/services/durable/worker.js +314 -60
- package/build/services/durable/workflow/all.d.ts +1 -1
- package/build/services/durable/workflow/all.js +1 -1
- package/build/services/durable/workflow/cancellationScope.d.ts +104 -0
- package/build/services/durable/workflow/cancellationScope.js +139 -0
- package/build/services/durable/workflow/common.d.ts +5 -4
- package/build/services/durable/workflow/common.js +6 -1
- package/build/services/durable/workflow/{waitFor.d.ts → condition.d.ts} +9 -8
- package/build/services/durable/workflow/{waitFor.js → condition.js} +44 -11
- package/build/services/durable/workflow/continueAsNew.d.ts +65 -0
- package/build/services/durable/workflow/continueAsNew.js +92 -0
- package/build/services/durable/workflow/didRun.d.ts +2 -2
- package/build/services/durable/workflow/didRun.js +4 -4
- package/build/services/durable/workflow/enrich.d.ts +5 -0
- package/build/services/durable/workflow/enrich.js +5 -0
- package/build/services/durable/workflow/entityMethods.d.ts +7 -0
- package/build/services/durable/workflow/entityMethods.js +7 -0
- package/build/services/durable/workflow/execHook.js +3 -3
- package/build/services/durable/workflow/execHookBatch.js +2 -2
- package/build/services/durable/workflow/{execChild.d.ts → executeChild.d.ts} +4 -40
- package/build/services/durable/workflow/{execChild.js → executeChild.js} +36 -45
- package/build/services/durable/workflow/hook.d.ts +1 -1
- package/build/services/durable/workflow/hook.js +4 -3
- package/build/services/durable/workflow/index.d.ts +45 -50
- package/build/services/durable/workflow/index.js +46 -51
- package/build/services/durable/workflow/interruption.d.ts +7 -6
- package/build/services/durable/workflow/interruption.js +11 -7
- package/build/services/durable/workflow/patched.d.ts +72 -0
- package/build/services/durable/workflow/patched.js +110 -0
- package/build/services/durable/workflow/proxyActivities.d.ts +7 -7
- package/build/services/durable/workflow/proxyActivities.js +51 -15
- package/build/services/durable/workflow/searchMethods.d.ts +7 -0
- package/build/services/durable/workflow/searchMethods.js +7 -0
- package/build/services/durable/workflow/signal.d.ts +4 -4
- package/build/services/durable/workflow/signal.js +4 -4
- package/build/services/durable/workflow/{sleepFor.d.ts → sleep.d.ts} +7 -7
- package/build/services/durable/workflow/{sleepFor.js → sleep.js} +39 -10
- package/build/services/durable/workflow/terminate.d.ts +55 -0
- package/build/services/durable/workflow/{interrupt.js → terminate.js} +21 -21
- package/build/services/durable/workflow/trace.js +2 -2
- package/build/services/durable/workflow/uuid4.d.ts +14 -0
- package/build/services/durable/workflow/uuid4.js +39 -0
- package/build/services/durable/workflow/{context.d.ts → workflowInfo.d.ts} +5 -5
- package/build/services/durable/workflow/{context.js → workflowInfo.js} +7 -7
- package/build/services/engine/compiler.d.ts +19 -0
- package/build/services/engine/compiler.js +20 -0
- package/build/services/engine/completion.d.ts +46 -0
- package/build/services/engine/completion.js +145 -0
- package/build/services/engine/dispatch.d.ts +24 -0
- package/build/services/engine/dispatch.js +98 -0
- package/build/services/engine/index.d.ts +49 -81
- package/build/services/engine/index.js +175 -573
- package/build/services/engine/init.d.ts +42 -0
- package/build/services/engine/init.js +74 -0
- package/build/services/engine/pubsub.d.ts +50 -0
- package/build/services/engine/pubsub.js +118 -0
- package/build/services/engine/reporting.d.ts +20 -0
- package/build/services/engine/reporting.js +38 -0
- package/build/services/engine/schema.d.ts +23 -0
- package/build/services/engine/schema.js +62 -0
- package/build/services/engine/signal.d.ts +57 -0
- package/build/services/engine/signal.js +117 -0
- package/build/services/engine/state.d.ts +35 -0
- package/build/services/engine/state.js +61 -0
- package/build/services/engine/version.d.ts +31 -0
- package/build/services/engine/version.js +73 -0
- package/build/services/hotmesh/deployment.d.ts +21 -0
- package/build/services/hotmesh/deployment.js +25 -0
- package/build/services/hotmesh/index.d.ts +142 -533
- package/build/services/hotmesh/index.js +223 -674
- package/build/services/hotmesh/init.d.ts +42 -0
- package/build/services/hotmesh/init.js +93 -0
- package/build/services/hotmesh/jobs.d.ts +67 -0
- package/build/services/hotmesh/jobs.js +99 -0
- package/build/services/hotmesh/pubsub.d.ts +38 -0
- package/build/services/hotmesh/pubsub.js +54 -0
- package/build/services/hotmesh/quorum.d.ts +30 -0
- package/build/services/hotmesh/quorum.js +62 -0
- package/build/services/hotmesh/validation.d.ts +6 -0
- package/build/services/hotmesh/validation.js +28 -0
- package/build/services/quorum/index.js +1 -0
- package/build/services/router/consumption/index.d.ts +11 -5
- package/build/services/router/consumption/index.js +24 -17
- package/build/services/router/error-handling/index.d.ts +2 -2
- package/build/services/router/error-handling/index.js +14 -14
- package/build/services/router/index.d.ts +1 -1
- package/build/services/router/index.js +2 -2
- package/build/services/serializer/index.d.ts +22 -0
- package/build/services/serializer/index.js +39 -1
- package/build/services/store/index.d.ts +1 -0
- package/build/services/store/providers/postgres/exporter-sql.d.ts +2 -2
- package/build/services/store/providers/postgres/exporter-sql.js +4 -4
- package/build/services/store/providers/postgres/kvtables.js +7 -6
- package/build/services/store/providers/postgres/kvtypes/hash/basic.js +67 -52
- package/build/services/store/providers/postgres/kvtypes/hash/jsonb.js +87 -72
- package/build/services/store/providers/postgres/kvtypes/hash/udata.js +106 -79
- package/build/services/store/providers/postgres/kvtypes/hash/utils.d.ts +16 -0
- package/build/services/store/providers/postgres/kvtypes/hash/utils.js +29 -16
- package/build/services/store/providers/postgres/postgres.d.ts +1 -0
- package/build/services/store/providers/postgres/postgres.js +14 -4
- package/build/services/stream/factory.d.ts +3 -1
- package/build/services/stream/factory.js +2 -2
- package/build/services/stream/index.d.ts +1 -0
- package/build/services/stream/providers/nats/nats.d.ts +1 -0
- package/build/services/stream/providers/nats/nats.js +1 -0
- package/build/services/stream/providers/postgres/credentials.d.ts +56 -0
- package/build/services/stream/providers/postgres/credentials.js +129 -0
- package/build/services/stream/providers/postgres/kvtables.js +18 -0
- package/build/services/stream/providers/postgres/messages.js +7 -7
- package/build/services/stream/providers/postgres/notifications.js +16 -2
- package/build/services/stream/providers/postgres/postgres.d.ts +7 -0
- package/build/services/stream/providers/postgres/postgres.js +35 -4
- package/build/services/stream/providers/postgres/procedures.d.ts +21 -0
- package/build/services/stream/providers/postgres/procedures.js +213 -0
- package/build/services/stream/providers/postgres/secured.d.ts +34 -0
- package/build/services/stream/providers/postgres/secured.js +146 -0
- package/build/services/stream/providers/postgres/stats.d.ts +1 -0
- package/build/services/stream/providers/postgres/stats.js +1 -0
- package/build/services/stream/registry.d.ts +1 -1
- package/build/services/stream/registry.js +5 -2
- package/build/services/telemetry/index.d.ts +10 -1
- package/build/services/telemetry/index.js +40 -7
- package/build/services/worker/credentials.d.ts +51 -0
- package/build/services/worker/credentials.js +87 -0
- package/build/services/worker/index.d.ts +2 -2
- package/build/services/worker/index.js +7 -6
- package/build/types/codec.d.ts +84 -0
- package/build/types/codec.js +2 -0
- package/build/types/dba.d.ts +39 -3
- package/build/types/durable.d.ts +123 -25
- package/build/types/error.d.ts +10 -0
- package/build/types/exporter.d.ts +1 -1
- package/build/types/hotmesh.d.ts +67 -4
- package/build/types/index.d.ts +2 -1
- package/build/types/provider.d.ts +2 -2
- package/build/types/quorum.d.ts +35 -1
- package/build/types/stream.d.ts +12 -6
- package/package.json +8 -2
- package/build/services/activities/activity.d.ts +0 -192
- package/build/services/activities/activity.js +0 -786
- package/build/services/durable/workflow/interrupt.d.ts +0 -55
|
@@ -1,274 +1,93 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { HotMesh } from '../hotmesh';
|
|
2
|
+
import { ContextType, WorkflowInboundCallsInterceptor, WorkflowOutboundCallsInterceptor, ActivityInboundCallsInterceptor } from '../../types/durable';
|
|
2
3
|
import { guid } from '../../modules/utils';
|
|
3
4
|
import { ClientService } from './client';
|
|
4
5
|
import { ConnectionService } from './connection';
|
|
5
6
|
import { Search } from './search';
|
|
6
7
|
import { Entity } from './entity';
|
|
8
|
+
import { ActivityService } from './activity';
|
|
7
9
|
import { WorkerService } from './worker';
|
|
8
10
|
import { WorkflowService } from './workflow';
|
|
9
11
|
import { WorkflowHandleService } from './handle';
|
|
10
12
|
import { didInterrupt } from './workflow/interruption';
|
|
11
13
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
14
|
+
* Durable workflow engine backed by Postgres. Write workflows as plain
|
|
15
|
+
* async functions; the engine handles persistence, replay, retry, and
|
|
16
|
+
* crash recovery automatically.
|
|
15
17
|
*
|
|
16
|
-
* ##
|
|
18
|
+
* ## Architecture
|
|
17
19
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
* // Initialize entity state
|
|
25
|
-
* await agent.set({
|
|
26
|
-
* query,
|
|
27
|
-
* findings: [],
|
|
28
|
-
* status: 'researching'
|
|
29
|
-
* });
|
|
30
|
-
*
|
|
31
|
-
* // Update state atomically
|
|
32
|
-
* await agent.merge({ status: 'analyzing' });
|
|
33
|
-
* await agent.append('findings', newFinding);
|
|
34
|
-
* }
|
|
35
|
-
* ```
|
|
36
|
-
*
|
|
37
|
-
* ### 2. Hook Functions & Workflow Coordination
|
|
38
|
-
* Spawn and coordinate multiple perspectives/phases:
|
|
39
|
-
* ```typescript
|
|
40
|
-
* // Launch parallel research perspectives
|
|
41
|
-
* await Durable.workflow.execHook({
|
|
42
|
-
* taskQueue: 'research',
|
|
43
|
-
* workflowName: 'optimisticView',
|
|
44
|
-
* args: [query],
|
|
45
|
-
* signalId: 'optimistic-complete'
|
|
46
|
-
* });
|
|
47
|
-
*
|
|
48
|
-
* await Durable.workflow.execHook({
|
|
49
|
-
* taskQueue: 'research',
|
|
50
|
-
* workflowName: 'skepticalView',
|
|
51
|
-
* args: [query],
|
|
52
|
-
* signalId: 'skeptical-complete'
|
|
53
|
-
* });
|
|
54
|
-
*
|
|
55
|
-
* // Wait for both perspectives
|
|
56
|
-
* await Promise.all([
|
|
57
|
-
* Durable.workflow.waitFor('optimistic-complete'),
|
|
58
|
-
* Durable.workflow.waitFor('skeptical-complete')
|
|
59
|
-
* ]);
|
|
60
|
-
* ```
|
|
20
|
+
* | Component | Role |
|
|
21
|
+
* |-----------|------|
|
|
22
|
+
* | {@link Worker} | Hosts workflow and activity functions |
|
|
23
|
+
* | {@link Client} | Starts workflows, sends signals, reads results |
|
|
24
|
+
* | {@link workflow} | In-workflow API (`proxyActivities`, `sleep`, `condition`, ...) |
|
|
61
25
|
*
|
|
62
|
-
*
|
|
63
|
-
* Define and execute durable activities with automatic retry:
|
|
64
|
-
* ```typescript
|
|
65
|
-
* // Default: activities use workflow's task queue
|
|
66
|
-
* const activities = Durable.workflow.proxyActivities<{
|
|
67
|
-
* analyzeDocument: typeof analyzeDocument;
|
|
68
|
-
* validateFindings: typeof validateFindings;
|
|
69
|
-
* }>({
|
|
70
|
-
* activities: { analyzeDocument, validateFindings },
|
|
71
|
-
* retryPolicy: {
|
|
72
|
-
* maximumAttempts: 3,
|
|
73
|
-
* backoffCoefficient: 2
|
|
74
|
-
* }
|
|
75
|
-
* });
|
|
26
|
+
* ## Workflow Primitives
|
|
76
27
|
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
* ```
|
|
28
|
+
* All methods below are available as `Durable.workflow.<method>` inside
|
|
29
|
+
* a workflow function. Each call is durable — results are persisted and
|
|
30
|
+
* replayed deterministically on recovery.
|
|
81
31
|
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
32
|
+
* | Primitive | Purpose |
|
|
33
|
+
* |-----------|---------|
|
|
34
|
+
* | `proxyActivities` | Execute side-effectful code with automatic retry |
|
|
35
|
+
* | `sleep` | Durable timer (survives restarts) |
|
|
36
|
+
* | `condition` | Pause until a named signal arrives (with optional timeout) |
|
|
37
|
+
* | `signal` | Deliver data to a waiting `condition` |
|
|
38
|
+
* | `executeChild` | Spawn a child workflow and await its result |
|
|
39
|
+
* | `startChild` | Fire-and-forget child workflow |
|
|
40
|
+
* | `continueAsNew` | Restart the workflow with new args (resets history) |
|
|
41
|
+
* | `patched` / `deprecatePatch` | Safe versioning for in-flight workflow code changes |
|
|
42
|
+
* | `CancellationScope.nonCancellable` | Shield cleanup code from cancellation |
|
|
43
|
+
* | `isCancellation` | Detect cooperative cancellation errors |
|
|
93
44
|
*
|
|
94
|
-
*
|
|
95
|
-
* await Durable.registerActivityWorker({
|
|
96
|
-
* connection: {
|
|
97
|
-
* class: Postgres,
|
|
98
|
-
* options: { connectionString: 'postgresql://usr:pwd@localhost:5432/db' }
|
|
99
|
-
* },
|
|
100
|
-
* taskQueue: 'priority-activities'
|
|
101
|
-
* }, priorityActivities, 'priority-activities');
|
|
102
|
-
* ```
|
|
45
|
+
* ## Quick Start
|
|
103
46
|
*
|
|
104
|
-
* ### 5. Workflow Composition
|
|
105
|
-
* Build complex workflows through composition:
|
|
106
47
|
* ```typescript
|
|
107
|
-
*
|
|
108
|
-
* const childResult = await Durable.workflow.execChild({
|
|
109
|
-
* taskQueue: 'analysis',
|
|
110
|
-
* workflowName: 'detailedAnalysis',
|
|
111
|
-
* args: [data],
|
|
112
|
-
* // Child workflow config
|
|
113
|
-
* config: {
|
|
114
|
-
* maximumAttempts: 5,
|
|
115
|
-
* backoffCoefficient: 2
|
|
116
|
-
* }
|
|
117
|
-
* });
|
|
118
|
-
*
|
|
119
|
-
* // Fire-and-forget child workflow
|
|
120
|
-
* await Durable.workflow.startChild({
|
|
121
|
-
* taskQueue: 'notifications',
|
|
122
|
-
* workflowName: 'sendUpdates',
|
|
123
|
-
* args: [updates]
|
|
124
|
-
* });
|
|
125
|
-
* ```
|
|
126
|
-
*
|
|
127
|
-
* ### 6. Workflow Interceptors
|
|
128
|
-
* Add cross-cutting concerns through interceptors that run as durable functions:
|
|
129
|
-
* ```typescript
|
|
130
|
-
* // First register shared activity worker for interceptors
|
|
131
|
-
* await Durable.registerActivityWorker({
|
|
132
|
-
* connection: {
|
|
133
|
-
* class: Postgres,
|
|
134
|
-
* options: { connectionString: 'postgresql://usr:pwd@localhost:5432/db' }
|
|
135
|
-
* },
|
|
136
|
-
* taskQueue: 'interceptor-activities'
|
|
137
|
-
* }, { auditLog }, 'interceptor-activities');
|
|
138
|
-
*
|
|
139
|
-
* // Add audit interceptor that uses activities with explicit taskQueue
|
|
140
|
-
* Durable.registerInterceptor({
|
|
141
|
-
* async execute(ctx, next) {
|
|
142
|
-
* try {
|
|
143
|
-
* // Interceptors use explicit taskQueue to prevent per-workflow queues
|
|
144
|
-
* const { auditLog } = Durable.workflow.proxyActivities<typeof activities>({
|
|
145
|
-
* activities: { auditLog },
|
|
146
|
-
* taskQueue: 'interceptor-activities', // Explicit shared queue
|
|
147
|
-
* retryPolicy: { maximumAttempts: 3 }
|
|
148
|
-
* });
|
|
149
|
-
*
|
|
150
|
-
* await auditLog(ctx.get('workflowId'), 'started');
|
|
151
|
-
*
|
|
152
|
-
* const result = await next();
|
|
153
|
-
*
|
|
154
|
-
* await auditLog(ctx.get('workflowId'), 'completed');
|
|
155
|
-
*
|
|
156
|
-
* return result;
|
|
157
|
-
* } catch (err) {
|
|
158
|
-
* // CRITICAL: Always check for HotMesh interruptions
|
|
159
|
-
* if (Durable.didInterrupt(err)) {
|
|
160
|
-
* throw err; // Rethrow for replay system
|
|
161
|
-
* }
|
|
162
|
-
* throw err;
|
|
163
|
-
* }
|
|
164
|
-
* }
|
|
165
|
-
* });
|
|
166
|
-
* ```
|
|
167
|
-
*
|
|
168
|
-
* ### 7. Activity Interceptors
|
|
169
|
-
* Wrap individual proxied activity calls with cross-cutting logic.
|
|
170
|
-
* Unlike workflow interceptors (which wrap the entire workflow), activity
|
|
171
|
-
* interceptors execute around each `proxyActivities` call. They run inside
|
|
172
|
-
* the workflow's execution context and have access to all Durable workflow
|
|
173
|
-
* methods (`proxyActivities`, `sleepFor`, `waitFor`, `execChild`, etc.).
|
|
174
|
-
* Multiple activity interceptors execute in onion order (first registered
|
|
175
|
-
* is outermost).
|
|
176
|
-
* ```typescript
|
|
177
|
-
* // Simple logging interceptor
|
|
178
|
-
* Durable.registerActivityInterceptor({
|
|
179
|
-
* async execute(activityCtx, workflowCtx, next) {
|
|
180
|
-
* console.log(`Activity ${activityCtx.activityName} starting`);
|
|
181
|
-
* try {
|
|
182
|
-
* const result = await next();
|
|
183
|
-
* console.log(`Activity ${activityCtx.activityName} completed`);
|
|
184
|
-
* return result;
|
|
185
|
-
* } catch (err) {
|
|
186
|
-
* if (Durable.didInterrupt(err)) throw err;
|
|
187
|
-
* console.error(`Activity ${activityCtx.activityName} failed`);
|
|
188
|
-
* throw err;
|
|
189
|
-
* }
|
|
190
|
-
* }
|
|
191
|
-
* });
|
|
192
|
-
*
|
|
193
|
-
* // Interceptor that calls its own proxy activities
|
|
194
|
-
* await Durable.registerActivityWorker({
|
|
195
|
-
* connection: {
|
|
196
|
-
* class: Postgres,
|
|
197
|
-
* options: { connectionString: 'postgresql://usr:pwd@localhost:5432/db' }
|
|
198
|
-
* },
|
|
199
|
-
* taskQueue: 'audit-activities'
|
|
200
|
-
* }, { auditLog }, 'audit-activities');
|
|
201
|
-
*
|
|
202
|
-
* Durable.registerActivityInterceptor({
|
|
203
|
-
* async execute(activityCtx, workflowCtx, next) {
|
|
204
|
-
* try {
|
|
205
|
-
* const { auditLog } = Durable.workflow.proxyActivities<{
|
|
206
|
-
* auditLog: (id: string, action: string) => Promise<void>;
|
|
207
|
-
* }>({
|
|
208
|
-
* taskQueue: 'audit-activities',
|
|
209
|
-
* retryPolicy: { maximumAttempts: 3 }
|
|
210
|
-
* });
|
|
211
|
-
*
|
|
212
|
-
* await auditLog(workflowCtx.get('workflowId'), `before:${activityCtx.activityName}`);
|
|
213
|
-
* const result = await next();
|
|
214
|
-
* await auditLog(workflowCtx.get('workflowId'), `after:${activityCtx.activityName}`);
|
|
215
|
-
* return result;
|
|
216
|
-
* } catch (err) {
|
|
217
|
-
* if (Durable.didInterrupt(err)) throw err;
|
|
218
|
-
* throw err;
|
|
219
|
-
* }
|
|
220
|
-
* }
|
|
221
|
-
* });
|
|
222
|
-
* ```
|
|
223
|
-
*
|
|
224
|
-
* ## Basic Usage Example
|
|
225
|
-
*
|
|
226
|
-
* ```typescript
|
|
227
|
-
* import { Client, Worker, Durable } from '@hotmeshio/hotmesh';
|
|
48
|
+
* import { Durable } from '@hotmeshio/hotmesh';
|
|
228
49
|
* import { Client as Postgres } from 'pg';
|
|
229
50
|
* import * as activities from './activities';
|
|
230
51
|
*
|
|
231
|
-
* //
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
*
|
|
235
|
-
*
|
|
236
|
-
* }
|
|
237
|
-
* taskQueue: 'shared-activities'
|
|
238
|
-
* }, sharedActivities, 'shared-activities');
|
|
52
|
+
* // 1. Define a workflow
|
|
53
|
+
* async function orderWorkflow(orderId: string): Promise<string> {
|
|
54
|
+
* const { charge, notify } = Durable.workflow.proxyActivities<typeof activities>({
|
|
55
|
+
* activities,
|
|
56
|
+
* retry: { maximumAttempts: 3 },
|
|
57
|
+
* });
|
|
239
58
|
*
|
|
240
|
-
*
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
* },
|
|
246
|
-
* taskQueue: 'default',
|
|
247
|
-
* workflow: workflows.example
|
|
248
|
-
* });
|
|
59
|
+
* const receipt = await charge(orderId);
|
|
60
|
+
* await Durable.workflow.sleep('1 hour');
|
|
61
|
+
* await notify(orderId, receipt);
|
|
62
|
+
* return receipt;
|
|
63
|
+
* }
|
|
249
64
|
*
|
|
250
|
-
* //
|
|
251
|
-
* const
|
|
252
|
-
*
|
|
253
|
-
* class: Postgres,
|
|
254
|
-
* options: { connectionString: 'postgresql://usr:pwd@localhost:5432/db' }
|
|
255
|
-
* }
|
|
256
|
-
* });
|
|
65
|
+
* // 2. Start a worker
|
|
66
|
+
* const connection = { class: Postgres, options: { connectionString: 'postgresql://...' } };
|
|
67
|
+
* await Durable.Worker.create({ connection, taskQueue: 'orders', workflow: orderWorkflow });
|
|
257
68
|
*
|
|
258
|
-
* // Start workflow
|
|
69
|
+
* // 3. Start a workflow from the client
|
|
70
|
+
* const client = new Durable.Client({ connection });
|
|
259
71
|
* const handle = await client.workflow.start({
|
|
260
|
-
* args: ['
|
|
261
|
-
* taskQueue: '
|
|
262
|
-
* workflowName: '
|
|
263
|
-
* workflowId: Durable.guid()
|
|
72
|
+
* args: ['order-123'],
|
|
73
|
+
* taskQueue: 'orders',
|
|
74
|
+
* workflowName: 'orderWorkflow',
|
|
75
|
+
* workflowId: Durable.guid(),
|
|
264
76
|
* });
|
|
265
|
-
*
|
|
266
|
-
* // Get result
|
|
267
77
|
* const result = await handle.result();
|
|
268
|
-
*
|
|
269
|
-
* // Cleanup
|
|
270
|
-
* await Durable.shutdown();
|
|
271
78
|
* ```
|
|
79
|
+
*
|
|
80
|
+
* ## Interceptors
|
|
81
|
+
*
|
|
82
|
+
* Cross-cutting concerns (logging, auth, metrics) attach via interceptors.
|
|
83
|
+
* See {@link registerInboundInterceptor} (wraps workflows) and
|
|
84
|
+
* {@link registerOutboundInterceptor} (wraps individual activity calls).
|
|
85
|
+
*
|
|
86
|
+
* ## Secured Workers
|
|
87
|
+
*
|
|
88
|
+
* For production isolation, workers can connect with scoped Postgres
|
|
89
|
+
* credentials that restrict access to specific task queues via stored
|
|
90
|
+
* procedures. See {@link WorkerService.create} and {@link provisionWorkerRole}.
|
|
272
91
|
*/
|
|
273
92
|
declare class DurableClass {
|
|
274
93
|
/**
|
|
@@ -276,33 +95,30 @@ declare class DurableClass {
|
|
|
276
95
|
*/
|
|
277
96
|
constructor();
|
|
278
97
|
/**
|
|
279
|
-
*
|
|
280
|
-
*
|
|
98
|
+
* Starts workflows, sends signals, and reads results. Instantiate
|
|
99
|
+
* with a connection, then use `client.workflow.start()` to launch
|
|
100
|
+
* a workflow and obtain a {@link Handle}.
|
|
281
101
|
*/
|
|
282
102
|
static Client: typeof ClientService;
|
|
283
103
|
/**
|
|
284
|
-
*
|
|
285
|
-
*
|
|
104
|
+
* Declares connection options (class + config) for Postgres.
|
|
105
|
+
* The actual connection is established lazily when a workflow
|
|
106
|
+
* or worker is started.
|
|
286
107
|
*/
|
|
287
108
|
static Connection: typeof ConnectionService;
|
|
288
|
-
/**
|
|
289
|
-
* @private
|
|
290
|
-
*/
|
|
109
|
+
/** @private */
|
|
291
110
|
static Search: typeof Search;
|
|
292
|
-
/**
|
|
293
|
-
* @private
|
|
294
|
-
*/
|
|
111
|
+
/** @private */
|
|
295
112
|
static Entity: typeof Entity;
|
|
296
113
|
/**
|
|
297
|
-
*
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
* is typically accessed via the Durable.Client class (workflow.getHandle).
|
|
114
|
+
* A handle to a running or completed workflow. Provides methods to
|
|
115
|
+
* read results, send signals, query state, cancel, or interrupt.
|
|
116
|
+
* Obtained via `client.workflow.start()` or `client.workflow.getHandle()`.
|
|
301
117
|
*/
|
|
302
118
|
static Handle: typeof WorkflowHandleService;
|
|
303
119
|
/**
|
|
304
|
-
*
|
|
305
|
-
*
|
|
120
|
+
* Hosts workflow and activity functions. Call `Worker.create()` with
|
|
121
|
+
* a connection, task queue, and workflow function to start processing.
|
|
306
122
|
*/
|
|
307
123
|
static Worker: typeof WorkerService;
|
|
308
124
|
/**
|
|
@@ -332,7 +148,7 @@ declare class DurableClass {
|
|
|
332
148
|
* sendEmail: (to: string, msg: string) => Promise<void>;
|
|
333
149
|
* }>({
|
|
334
150
|
* taskQueue: 'payment',
|
|
335
|
-
*
|
|
151
|
+
* retry: { maximumAttempts: 3 }
|
|
336
152
|
* });
|
|
337
153
|
*
|
|
338
154
|
* const result = await processPayment(amount);
|
|
@@ -349,17 +165,24 @@ declare class DurableClass {
|
|
|
349
165
|
*/
|
|
350
166
|
static registerActivityWorker: typeof WorkerService.registerActivityWorker;
|
|
351
167
|
/**
|
|
352
|
-
*
|
|
353
|
-
*
|
|
354
|
-
*
|
|
355
|
-
|
|
168
|
+
* Activity-side context. Call `Durable.activity.getContext()` inside
|
|
169
|
+
* an activity function to access the activity name, arguments,
|
|
170
|
+
* parent workflow ID, and other execution metadata.
|
|
171
|
+
*/
|
|
172
|
+
static activity: typeof ActivityService;
|
|
173
|
+
/**
|
|
174
|
+
* The workflow-internal API. Every method on this object
|
|
175
|
+
* (`proxyActivities`, `sleep`, `condition`, `signal`, `executeChild`,
|
|
176
|
+
* `continueAsNew`, `patched`, `CancellationScope`, etc.) is designed
|
|
177
|
+
* to be called **inside** a workflow function and participates in
|
|
178
|
+
* deterministic replay.
|
|
356
179
|
*/
|
|
357
180
|
static workflow: typeof WorkflowService;
|
|
358
181
|
/**
|
|
359
|
-
*
|
|
360
|
-
*
|
|
361
|
-
*
|
|
362
|
-
*
|
|
182
|
+
* Returns `true` if the error is an engine control-flow signal (replay
|
|
183
|
+
* suspension) rather than an application error. **Always check this in
|
|
184
|
+
* `catch` blocks inside workflows and interceptors** — swallowing an
|
|
185
|
+
* interruption breaks the replay system.
|
|
363
186
|
*/
|
|
364
187
|
static didInterrupt: typeof didInterrupt;
|
|
365
188
|
private static interceptorService;
|
|
@@ -371,8 +194,8 @@ declare class DurableClass {
|
|
|
371
194
|
* logging, metrics, or tracing.
|
|
372
195
|
*
|
|
373
196
|
* Workflow interceptors run inside the workflow's async local storage context,
|
|
374
|
-
* so all Durable workflow methods (`proxyActivities`, `
|
|
375
|
-
* `
|
|
197
|
+
* so all Durable workflow methods (`proxyActivities`, `sleep`, `condition`,
|
|
198
|
+
* `executeChild`, etc.) are available. When using Durable functions, always check
|
|
376
199
|
* for interruptions with `Durable.didInterrupt(err)` and rethrow them.
|
|
377
200
|
*
|
|
378
201
|
* @param interceptor The interceptor to register
|
|
@@ -380,7 +203,7 @@ declare class DurableClass {
|
|
|
380
203
|
* @example
|
|
381
204
|
* ```typescript
|
|
382
205
|
* // Logging interceptor
|
|
383
|
-
* Durable.
|
|
206
|
+
* Durable.registerInboundInterceptor({
|
|
384
207
|
* async execute(ctx, next) {
|
|
385
208
|
* console.log(`Workflow ${ctx.get('workflowName')} starting`);
|
|
386
209
|
* try {
|
|
@@ -396,28 +219,28 @@ declare class DurableClass {
|
|
|
396
219
|
* });
|
|
397
220
|
* ```
|
|
398
221
|
*/
|
|
399
|
-
static
|
|
222
|
+
static registerInboundInterceptor(interceptor: WorkflowInboundCallsInterceptor): void;
|
|
400
223
|
/**
|
|
401
|
-
* Clear all registered interceptors (both
|
|
224
|
+
* Clear all registered interceptors (both inbound and outbound).
|
|
402
225
|
*/
|
|
403
226
|
static clearInterceptors(): void;
|
|
404
227
|
/**
|
|
405
|
-
* Register an
|
|
228
|
+
* Register an outbound interceptor that wraps individual proxied
|
|
406
229
|
* activity calls within workflows. Interceptors execute in registration
|
|
407
230
|
* order (first registered is outermost) using the onion pattern.
|
|
408
231
|
*
|
|
409
|
-
*
|
|
232
|
+
* Outbound interceptors run inside the workflow's execution context
|
|
410
233
|
* and have access to all Durable workflow methods (`proxyActivities`,
|
|
411
|
-
* `
|
|
234
|
+
* `sleep`, `condition`, `executeChild`, etc.). The `activityCtx` parameter
|
|
412
235
|
* provides `activityName`, `args`, and `options` for the call being
|
|
413
236
|
* intercepted. The `workflowCtx` map provides workflow metadata
|
|
414
237
|
* (`workflowId`, `workflowName`, `namespace`, etc.).
|
|
415
238
|
*
|
|
416
|
-
* @param interceptor The
|
|
239
|
+
* @param interceptor The outbound interceptor to register
|
|
417
240
|
*
|
|
418
241
|
* @example
|
|
419
242
|
* ```typescript
|
|
420
|
-
* Durable.
|
|
243
|
+
* Durable.registerOutboundInterceptor({
|
|
421
244
|
* async execute(activityCtx, workflowCtx, next) {
|
|
422
245
|
* const start = Date.now();
|
|
423
246
|
* try {
|
|
@@ -432,18 +255,64 @@ declare class DurableClass {
|
|
|
432
255
|
* });
|
|
433
256
|
* ```
|
|
434
257
|
*/
|
|
435
|
-
static
|
|
258
|
+
static registerOutboundInterceptor(interceptor: WorkflowOutboundCallsInterceptor): void;
|
|
259
|
+
/**
|
|
260
|
+
* Clear all registered outbound interceptors
|
|
261
|
+
*/
|
|
262
|
+
static clearOutboundInterceptors(): void;
|
|
436
263
|
/**
|
|
437
|
-
*
|
|
264
|
+
* Register an activity inbound interceptor that wraps the actual activity
|
|
265
|
+
* function execution on the activity worker side. This runs inside the
|
|
266
|
+
* activity's `AsyncLocalStorage` context, NOT the workflow context.
|
|
267
|
+
*
|
|
268
|
+
* Use for logging, metrics, auth validation, or error enrichment at
|
|
269
|
+
* the point where the activity actually executes.
|
|
270
|
+
*/
|
|
271
|
+
static registerActivityInboundInterceptor(interceptor: ActivityInboundCallsInterceptor): void;
|
|
272
|
+
/**
|
|
273
|
+
* Clear all registered activity inbound interceptors.
|
|
438
274
|
*/
|
|
439
|
-
static
|
|
275
|
+
static clearActivityInboundInterceptors(): void;
|
|
440
276
|
/**
|
|
441
277
|
* Generate a unique identifier for workflow IDs
|
|
442
278
|
*/
|
|
443
279
|
static guid: typeof guid;
|
|
444
280
|
/**
|
|
445
|
-
*
|
|
446
|
-
*
|
|
281
|
+
* Provision a scoped Postgres role for a worker. The role can only
|
|
282
|
+
* dequeue, ack, and respond on its assigned stream names via stored
|
|
283
|
+
* procedures — zero direct table access.
|
|
284
|
+
*
|
|
285
|
+
* @example
|
|
286
|
+
* ```typescript
|
|
287
|
+
* const cred = await Durable.provisionWorkerRole({
|
|
288
|
+
* connection: { class: Postgres, options: adminOptions },
|
|
289
|
+
* streamNames: ['payment-activity'],
|
|
290
|
+
* });
|
|
291
|
+
*
|
|
292
|
+
* await Worker.create({
|
|
293
|
+
* connection: { class: Postgres, options: pgOptions },
|
|
294
|
+
* taskQueue: 'payment',
|
|
295
|
+
* workflow: paymentWorkflow,
|
|
296
|
+
* workerCredentials: cred,
|
|
297
|
+
* });
|
|
298
|
+
* ```
|
|
299
|
+
*/
|
|
300
|
+
static provisionWorkerRole: typeof import("../worker/credentials").provisionWorkerRole;
|
|
301
|
+
/** Rotate a secured worker role's password. */
|
|
302
|
+
static rotateWorkerPassword: typeof import("../worker/credentials").rotateWorkerPassword;
|
|
303
|
+
/** Revoke a secured worker role (disables login). */
|
|
304
|
+
static revokeWorkerRole: typeof import("../worker/credentials").revokeWorkerRole;
|
|
305
|
+
/** List all provisioned secured worker roles. */
|
|
306
|
+
static listWorkerRoles: typeof import("../worker/credentials").listWorkerRoles;
|
|
307
|
+
/**
|
|
308
|
+
* Register a global payload codec for encrypting/decrypting workflow
|
|
309
|
+
* data at rest. The codec's `encode`/`decode` methods are called
|
|
310
|
+
* automatically on all persisted workflow payloads.
|
|
311
|
+
*/
|
|
312
|
+
static registerCodec: typeof HotMesh.registerCodec;
|
|
313
|
+
/**
|
|
314
|
+
* Gracefully shut down all workers, clients, and connections.
|
|
315
|
+
* Call from your process signal handlers (`SIGTERM`, `SIGINT`).
|
|
447
316
|
*/
|
|
448
317
|
static shutdown(): Promise<void>;
|
|
449
318
|
}
|