@hotmeshio/hotmesh 0.14.9 → 0.14.10
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/build/package.json +1 -1
- package/build/services/durable/exporter.d.ts +103 -11
- package/build/services/durable/exporter.js +103 -11
- package/build/services/durable/handle.d.ts +40 -8
- package/build/services/durable/handle.js +40 -8
- package/build/services/durable/schemas/factory.d.ts +1 -1
- package/build/services/durable/schemas/factory.js +1 -13
- package/build/services/exporter/index.d.ts +56 -17
- package/build/services/exporter/index.js +56 -17
- package/build/types/exporter.d.ts +58 -1
- package/package.json +1 -1
package/build/package.json
CHANGED
|
@@ -41,6 +41,32 @@ declare function isSystemActivity(name: string): boolean;
|
|
|
41
41
|
* both the `done` flag and the semaphore to determine status.
|
|
42
42
|
*/
|
|
43
43
|
declare function mapStatus(rawStatus: number | undefined, isDone?: boolean, hasError?: boolean): WorkflowExecutionStatus;
|
|
44
|
+
/**
|
|
45
|
+
* Exports durable workflow execution data in two formats:
|
|
46
|
+
*
|
|
47
|
+
* ### Raw export (`export()`)
|
|
48
|
+
* Returns a {@link DurableJobExport} with five sections:
|
|
49
|
+
* - **data** — workflow input arguments (what was passed to `workflow.start()`)
|
|
50
|
+
* - **state** — current workflow state: `done` flag, `response`, `$error`, timestamps (`jc`/`ju`)
|
|
51
|
+
* - **status** — HotMesh semaphore (`0` = complete, `> 0` = activities pending, `< 0` = failed)
|
|
52
|
+
* - **timeline** — ordered list of idempotent operations: proxy activities, child workflows,
|
|
53
|
+
* sleeps, signals, and collated (Promise.all) results with per-entry timing and output
|
|
54
|
+
* - **transitions** — activity execution log with `created`/`updated` timestamps per dimension
|
|
55
|
+
*
|
|
56
|
+
* Use `allow`/`block` options to limit which sections are returned (e.g., omit
|
|
57
|
+
* `transitions` to reduce payload size). Use `values: false` to strip result
|
|
58
|
+
* payloads from timeline entries.
|
|
59
|
+
*
|
|
60
|
+
* ### Execution history (`exportExecution()`)
|
|
61
|
+
* Returns a {@link WorkflowExecution} — a Temporal-style event history with
|
|
62
|
+
* typed events (`activity_task_scheduled`, `timer_fired`, `workflow_execution_signaled`, etc.),
|
|
63
|
+
* chronological ordering, back-references between scheduled/completed pairs, and a summary
|
|
64
|
+
* with activity/child/timer/signal counts.
|
|
65
|
+
*
|
|
66
|
+
* Supports **sparse** mode (default, no extra I/O) and **verbose** mode (recursively
|
|
67
|
+
* fetches child workflow histories up to `max_depth`). Use `enrich_inputs` to attach
|
|
68
|
+
* activity and child workflow input arguments to events.
|
|
69
|
+
*/
|
|
44
70
|
declare class ExporterService {
|
|
45
71
|
appId: string;
|
|
46
72
|
logger: ILogger;
|
|
@@ -49,18 +75,72 @@ declare class ExporterService {
|
|
|
49
75
|
private static symbols;
|
|
50
76
|
constructor(appId: string, store: StoreService<ProviderClient, ProviderTransaction>, logger: ILogger);
|
|
51
77
|
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
78
|
+
* Export the raw workflow job as a structured {@link DurableJobExport}.
|
|
79
|
+
*
|
|
80
|
+
* The result contains five sections (filterable via `options.allow` / `options.block`):
|
|
81
|
+
*
|
|
82
|
+
* | Section | Contents |
|
|
83
|
+
* |---|---|
|
|
84
|
+
* | `data` | Workflow input arguments passed to `workflow.start()` |
|
|
85
|
+
* | `state` | Current state: `done`, `response`, `$error`, timestamps |
|
|
86
|
+
* | `status` | Semaphore value: `0` = idle, `> 0` = pending, `< 0` = error |
|
|
87
|
+
* | `timeline` | Ordered idempotent markers: activities, children, sleeps, signals |
|
|
88
|
+
* | `transitions` | Per-activity execution timestamps by dimension |
|
|
89
|
+
*
|
|
90
|
+
* @param jobId - the workflow ID to export
|
|
91
|
+
* @param options - controls which sections to include and whether to include values
|
|
92
|
+
* @returns the exported workflow data
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```typescript
|
|
96
|
+
* // Full export
|
|
97
|
+
* const full = await handle.export();
|
|
98
|
+
*
|
|
99
|
+
* // Timeline only, without result payloads (smaller response)
|
|
100
|
+
* const slim = await handle.export({ allow: ['timeline'], values: false });
|
|
101
|
+
* ```
|
|
54
102
|
*/
|
|
55
103
|
export(jobId: string, options?: ExportOptions): Promise<DurableJobExport>;
|
|
56
104
|
/**
|
|
57
|
-
* Export a workflow execution as a structured event history.
|
|
105
|
+
* Export a workflow execution as a structured event history ({@link WorkflowExecution}).
|
|
106
|
+
*
|
|
107
|
+
* Returns a Temporal-style event list with typed events, chronological ordering,
|
|
108
|
+
* back-references (e.g., `scheduled_event_id` on completed activities), and a
|
|
109
|
+
* {@link WorkflowExecutionSummary} with counts by category.
|
|
110
|
+
*
|
|
111
|
+
* **Event types produced:**
|
|
112
|
+
* - `workflow_execution_started` / `completed` / `failed` — lifecycle bookends
|
|
113
|
+
* - `activity_task_scheduled` / `completed` / `failed` — proxy activity calls
|
|
114
|
+
* - `child_workflow_execution_started` / `completed` / `failed` — child workflows
|
|
115
|
+
* - `timer_started` / `timer_fired` — `workflow.sleep()` calls
|
|
116
|
+
* - `workflow_execution_signaled` — `workflow.condition()` signals received
|
|
117
|
+
*
|
|
118
|
+
* **Modes:**
|
|
119
|
+
* - `sparse` (default) — transforms the workflow's timeline markers into events.
|
|
120
|
+
* No extra database queries beyond the initial job export.
|
|
121
|
+
* - `verbose` — recursively fetches child workflow jobs and attaches their full
|
|
122
|
+
* event histories as nested `children` (up to `max_depth`, default 5).
|
|
123
|
+
*
|
|
124
|
+
* **Options:**
|
|
125
|
+
* - `exclude_system` — omit internal/interceptor activities (names starting with `lt`)
|
|
126
|
+
* - `omit_results` — strip `result` and `input` payloads from event attributes
|
|
127
|
+
* - `enrich_inputs` — attach activity/child workflow input arguments to events
|
|
128
|
+
* - `allow_direct_query` — fallback to raw DB queries for expired/pruned jobs
|
|
58
129
|
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
130
|
+
* @param jobId - the workflow ID
|
|
131
|
+
* @param workflowTopic - the task queue topic (used as `workflow_type`)
|
|
132
|
+
* @param options - controls mode, filtering, and enrichment
|
|
61
133
|
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
134
|
+
* @example
|
|
135
|
+
* ```typescript
|
|
136
|
+
* // Sparse export with system activities filtered out
|
|
137
|
+
* const exec = await handle.exportExecution({ exclude_system: true });
|
|
138
|
+
* console.log(exec.summary.activities.user); // user activity count
|
|
139
|
+
*
|
|
140
|
+
* // Verbose export with full child workflow trees
|
|
141
|
+
* const deep = await handle.exportExecution({ mode: 'verbose', max_depth: 3 });
|
|
142
|
+
* console.log(deep.children); // nested WorkflowExecution[]
|
|
143
|
+
* ```
|
|
64
144
|
*/
|
|
65
145
|
exportExecution(jobId: string, workflowTopic: string, options?: ExecutionExportOptions): Promise<WorkflowExecution>;
|
|
66
146
|
/**
|
|
@@ -88,10 +168,22 @@ declare class ExporterService {
|
|
|
88
168
|
*/
|
|
89
169
|
private fetchChildren;
|
|
90
170
|
/**
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
171
|
+
* Inflate a raw Redis/Postgres job hash into a structured {@link DurableJobExport}.
|
|
172
|
+
*
|
|
173
|
+
* HotMesh stores workflow state as a flat hash with 3-character symbolized keys
|
|
174
|
+
* (e.g., `aBC,0,0` → `worker/output/data`). This method decodes each entry and
|
|
175
|
+
* sorts it into one of four buckets:
|
|
176
|
+
*
|
|
177
|
+
* - **Transitions** (`aBC,0,0` pattern) — activity start/stop timestamps by dimension
|
|
178
|
+
* - **Data** (`_`-prefixed keys) — workflow input arguments
|
|
179
|
+
* - **Timeline** (`-`-prefixed keys) — idempotent operation markers (proxy, child, sleep, etc.)
|
|
180
|
+
* - **State** (3-char keys) — workflow metadata (done flag, response, error, timestamps)
|
|
181
|
+
*
|
|
182
|
+
* Use `options.allow` / `options.block` to limit which sections appear in the result.
|
|
183
|
+
*
|
|
184
|
+
* @param jobHash - the raw key-value hash from the store
|
|
185
|
+
* @param options - filtering and value options
|
|
186
|
+
* @returns structured export with data, state, status, timeline, and transitions
|
|
95
187
|
*/
|
|
96
188
|
inflate(jobHash: StringStringType, options: ExportOptions): DurableJobExport;
|
|
97
189
|
resolveValue(raw: string, withValues: boolean): Record<string, any> | string | number | null;
|
|
@@ -153,6 +153,32 @@ function computeSummary(events) {
|
|
|
153
153
|
return summary;
|
|
154
154
|
}
|
|
155
155
|
// ── Exporter Service ─────────────────────────────────────────────────────────
|
|
156
|
+
/**
|
|
157
|
+
* Exports durable workflow execution data in two formats:
|
|
158
|
+
*
|
|
159
|
+
* ### Raw export (`export()`)
|
|
160
|
+
* Returns a {@link DurableJobExport} with five sections:
|
|
161
|
+
* - **data** — workflow input arguments (what was passed to `workflow.start()`)
|
|
162
|
+
* - **state** — current workflow state: `done` flag, `response`, `$error`, timestamps (`jc`/`ju`)
|
|
163
|
+
* - **status** — HotMesh semaphore (`0` = complete, `> 0` = activities pending, `< 0` = failed)
|
|
164
|
+
* - **timeline** — ordered list of idempotent operations: proxy activities, child workflows,
|
|
165
|
+
* sleeps, signals, and collated (Promise.all) results with per-entry timing and output
|
|
166
|
+
* - **transitions** — activity execution log with `created`/`updated` timestamps per dimension
|
|
167
|
+
*
|
|
168
|
+
* Use `allow`/`block` options to limit which sections are returned (e.g., omit
|
|
169
|
+
* `transitions` to reduce payload size). Use `values: false` to strip result
|
|
170
|
+
* payloads from timeline entries.
|
|
171
|
+
*
|
|
172
|
+
* ### Execution history (`exportExecution()`)
|
|
173
|
+
* Returns a {@link WorkflowExecution} — a Temporal-style event history with
|
|
174
|
+
* typed events (`activity_task_scheduled`, `timer_fired`, `workflow_execution_signaled`, etc.),
|
|
175
|
+
* chronological ordering, back-references between scheduled/completed pairs, and a summary
|
|
176
|
+
* with activity/child/timer/signal counts.
|
|
177
|
+
*
|
|
178
|
+
* Supports **sparse** mode (default, no extra I/O) and **verbose** mode (recursively
|
|
179
|
+
* fetches child workflow histories up to `max_depth`). Use `enrich_inputs` to attach
|
|
180
|
+
* activity and child workflow input arguments to events.
|
|
181
|
+
*/
|
|
156
182
|
class ExporterService {
|
|
157
183
|
constructor(appId, store, logger) {
|
|
158
184
|
this.appId = appId;
|
|
@@ -160,8 +186,30 @@ class ExporterService {
|
|
|
160
186
|
this.store = store;
|
|
161
187
|
}
|
|
162
188
|
/**
|
|
163
|
-
*
|
|
164
|
-
*
|
|
189
|
+
* Export the raw workflow job as a structured {@link DurableJobExport}.
|
|
190
|
+
*
|
|
191
|
+
* The result contains five sections (filterable via `options.allow` / `options.block`):
|
|
192
|
+
*
|
|
193
|
+
* | Section | Contents |
|
|
194
|
+
* |---|---|
|
|
195
|
+
* | `data` | Workflow input arguments passed to `workflow.start()` |
|
|
196
|
+
* | `state` | Current state: `done`, `response`, `$error`, timestamps |
|
|
197
|
+
* | `status` | Semaphore value: `0` = idle, `> 0` = pending, `< 0` = error |
|
|
198
|
+
* | `timeline` | Ordered idempotent markers: activities, children, sleeps, signals |
|
|
199
|
+
* | `transitions` | Per-activity execution timestamps by dimension |
|
|
200
|
+
*
|
|
201
|
+
* @param jobId - the workflow ID to export
|
|
202
|
+
* @param options - controls which sections to include and whether to include values
|
|
203
|
+
* @returns the exported workflow data
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* ```typescript
|
|
207
|
+
* // Full export
|
|
208
|
+
* const full = await handle.export();
|
|
209
|
+
*
|
|
210
|
+
* // Timeline only, without result payloads (smaller response)
|
|
211
|
+
* const slim = await handle.export({ allow: ['timeline'], values: false });
|
|
212
|
+
* ```
|
|
165
213
|
*/
|
|
166
214
|
async export(jobId, options = {}) {
|
|
167
215
|
if (!ExporterService.symbols.has(this.appId)) {
|
|
@@ -173,13 +221,45 @@ class ExporterService {
|
|
|
173
221
|
return jobExport;
|
|
174
222
|
}
|
|
175
223
|
/**
|
|
176
|
-
* Export a workflow execution as a structured event history.
|
|
224
|
+
* Export a workflow execution as a structured event history ({@link WorkflowExecution}).
|
|
225
|
+
*
|
|
226
|
+
* Returns a Temporal-style event list with typed events, chronological ordering,
|
|
227
|
+
* back-references (e.g., `scheduled_event_id` on completed activities), and a
|
|
228
|
+
* {@link WorkflowExecutionSummary} with counts by category.
|
|
229
|
+
*
|
|
230
|
+
* **Event types produced:**
|
|
231
|
+
* - `workflow_execution_started` / `completed` / `failed` — lifecycle bookends
|
|
232
|
+
* - `activity_task_scheduled` / `completed` / `failed` — proxy activity calls
|
|
233
|
+
* - `child_workflow_execution_started` / `completed` / `failed` — child workflows
|
|
234
|
+
* - `timer_started` / `timer_fired` — `workflow.sleep()` calls
|
|
235
|
+
* - `workflow_execution_signaled` — `workflow.condition()` signals received
|
|
236
|
+
*
|
|
237
|
+
* **Modes:**
|
|
238
|
+
* - `sparse` (default) — transforms the workflow's timeline markers into events.
|
|
239
|
+
* No extra database queries beyond the initial job export.
|
|
240
|
+
* - `verbose` — recursively fetches child workflow jobs and attaches their full
|
|
241
|
+
* event histories as nested `children` (up to `max_depth`, default 5).
|
|
242
|
+
*
|
|
243
|
+
* **Options:**
|
|
244
|
+
* - `exclude_system` — omit internal/interceptor activities (names starting with `lt`)
|
|
245
|
+
* - `omit_results` — strip `result` and `input` payloads from event attributes
|
|
246
|
+
* - `enrich_inputs` — attach activity/child workflow input arguments to events
|
|
247
|
+
* - `allow_direct_query` — fallback to raw DB queries for expired/pruned jobs
|
|
177
248
|
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
249
|
+
* @param jobId - the workflow ID
|
|
250
|
+
* @param workflowTopic - the task queue topic (used as `workflow_type`)
|
|
251
|
+
* @param options - controls mode, filtering, and enrichment
|
|
180
252
|
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
253
|
+
* @example
|
|
254
|
+
* ```typescript
|
|
255
|
+
* // Sparse export with system activities filtered out
|
|
256
|
+
* const exec = await handle.exportExecution({ exclude_system: true });
|
|
257
|
+
* console.log(exec.summary.activities.user); // user activity count
|
|
258
|
+
*
|
|
259
|
+
* // Verbose export with full child workflow trees
|
|
260
|
+
* const deep = await handle.exportExecution({ mode: 'verbose', max_depth: 3 });
|
|
261
|
+
* console.log(deep.children); // nested WorkflowExecution[]
|
|
262
|
+
* ```
|
|
183
263
|
*/
|
|
184
264
|
async exportExecution(jobId, workflowTopic, options = {}) {
|
|
185
265
|
let execution;
|
|
@@ -845,10 +925,22 @@ class ExporterService {
|
|
|
845
925
|
return children;
|
|
846
926
|
}
|
|
847
927
|
/**
|
|
848
|
-
*
|
|
849
|
-
*
|
|
850
|
-
*
|
|
851
|
-
*
|
|
928
|
+
* Inflate a raw Redis/Postgres job hash into a structured {@link DurableJobExport}.
|
|
929
|
+
*
|
|
930
|
+
* HotMesh stores workflow state as a flat hash with 3-character symbolized keys
|
|
931
|
+
* (e.g., `aBC,0,0` → `worker/output/data`). This method decodes each entry and
|
|
932
|
+
* sorts it into one of four buckets:
|
|
933
|
+
*
|
|
934
|
+
* - **Transitions** (`aBC,0,0` pattern) — activity start/stop timestamps by dimension
|
|
935
|
+
* - **Data** (`_`-prefixed keys) — workflow input arguments
|
|
936
|
+
* - **Timeline** (`-`-prefixed keys) — idempotent operation markers (proxy, child, sleep, etc.)
|
|
937
|
+
* - **State** (3-char keys) — workflow metadata (done flag, response, error, timestamps)
|
|
938
|
+
*
|
|
939
|
+
* Use `options.allow` / `options.block` to limit which sections appear in the result.
|
|
940
|
+
*
|
|
941
|
+
* @param jobHash - the raw key-value hash from the store
|
|
942
|
+
* @param options - filtering and value options
|
|
943
|
+
* @returns structured export with data, state, status, timeline, and transitions
|
|
852
944
|
*/
|
|
853
945
|
inflate(jobHash, options) {
|
|
854
946
|
const timeline = [];
|
|
@@ -37,19 +37,51 @@ export declare class WorkflowHandleService {
|
|
|
37
37
|
*/
|
|
38
38
|
constructor(hotMesh: HotMesh, workflowTopic: string, workflowId: string);
|
|
39
39
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
40
|
+
* Export the raw workflow state as a {@link DurableJobExport} with five sections:
|
|
41
|
+
*
|
|
42
|
+
* - **data** — workflow input arguments
|
|
43
|
+
* - **state** — done flag, response, error, timestamps
|
|
44
|
+
* - **status** — semaphore (`0` = complete, `> 0` = pending, `< 0` = error)
|
|
45
|
+
* - **timeline** — ordered idempotent markers for activities, children, sleeps, signals
|
|
46
|
+
* - **transitions** — per-activity execution timestamps by dimension
|
|
47
|
+
*
|
|
48
|
+
* Use `allow` / `block` to limit sections and `values: false` to strip payloads.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* const raw = await handle.export();
|
|
53
|
+
* console.log(raw.state); // { done: true, response: '...' }
|
|
54
|
+
* console.log(raw.timeline); // [{ key: '-proxy-1-', value: {...} }, ...]
|
|
55
|
+
*
|
|
56
|
+
* // Lightweight export: timeline keys only, no payloads
|
|
57
|
+
* const slim = await handle.export({ allow: ['timeline'], values: false });
|
|
58
|
+
* ```
|
|
42
59
|
*/
|
|
43
60
|
export(options?: ExportOptions): Promise<DurableJobExport>;
|
|
44
61
|
/**
|
|
45
|
-
*
|
|
62
|
+
* Export the workflow as a structured event history ({@link WorkflowExecution}).
|
|
46
63
|
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
* timer, and signal events.
|
|
64
|
+
* Returns a chronologically ordered event list with Temporal-style typed events,
|
|
65
|
+
* back-references between scheduled/completed pairs, and a summary with counts.
|
|
50
66
|
*
|
|
51
|
-
* **
|
|
52
|
-
*
|
|
67
|
+
* **Event types:** `activity_task_scheduled/completed/failed`,
|
|
68
|
+
* `child_workflow_execution_started/completed/failed`, `timer_started/fired`,
|
|
69
|
+
* `workflow_execution_started/completed/failed/signaled`
|
|
70
|
+
*
|
|
71
|
+
* **Modes:**
|
|
72
|
+
* - `sparse` (default) — single query, transforms timeline markers into events
|
|
73
|
+
* - `verbose` — recursively fetches child workflows as nested `children`
|
|
74
|
+
*
|
|
75
|
+
* **Options:** `exclude_system`, `omit_results`, `enrich_inputs`, `allow_direct_query`
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* ```typescript
|
|
79
|
+
* const exec = await handle.exportExecution({ exclude_system: true });
|
|
80
|
+
* for (const event of exec.events) {
|
|
81
|
+
* console.log(event.event_type, event.attributes);
|
|
82
|
+
* }
|
|
83
|
+
* console.log(exec.summary); // { activities: { total: 5, ... }, timers: 1, ... }
|
|
84
|
+
* ```
|
|
53
85
|
*/
|
|
54
86
|
exportExecution(options?: ExecutionExportOptions): Promise<WorkflowExecution>;
|
|
55
87
|
/**
|
|
@@ -34,21 +34,53 @@ class WorkflowHandleService {
|
|
|
34
34
|
this.exporter = new exporter_1.ExporterService(this.hotMesh.appId, this.hotMesh.engine.store, this.hotMesh.engine.logger);
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
|
-
*
|
|
38
|
-
*
|
|
37
|
+
* Export the raw workflow state as a {@link DurableJobExport} with five sections:
|
|
38
|
+
*
|
|
39
|
+
* - **data** — workflow input arguments
|
|
40
|
+
* - **state** — done flag, response, error, timestamps
|
|
41
|
+
* - **status** — semaphore (`0` = complete, `> 0` = pending, `< 0` = error)
|
|
42
|
+
* - **timeline** — ordered idempotent markers for activities, children, sleeps, signals
|
|
43
|
+
* - **transitions** — per-activity execution timestamps by dimension
|
|
44
|
+
*
|
|
45
|
+
* Use `allow` / `block` to limit sections and `values: false` to strip payloads.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* const raw = await handle.export();
|
|
50
|
+
* console.log(raw.state); // { done: true, response: '...' }
|
|
51
|
+
* console.log(raw.timeline); // [{ key: '-proxy-1-', value: {...} }, ...]
|
|
52
|
+
*
|
|
53
|
+
* // Lightweight export: timeline keys only, no payloads
|
|
54
|
+
* const slim = await handle.export({ allow: ['timeline'], values: false });
|
|
55
|
+
* ```
|
|
39
56
|
*/
|
|
40
57
|
async export(options) {
|
|
41
58
|
return this.exporter.export(this.workflowId, options);
|
|
42
59
|
}
|
|
43
60
|
/**
|
|
44
|
-
*
|
|
61
|
+
* Export the workflow as a structured event history ({@link WorkflowExecution}).
|
|
45
62
|
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
* timer, and signal events.
|
|
63
|
+
* Returns a chronologically ordered event list with Temporal-style typed events,
|
|
64
|
+
* back-references between scheduled/completed pairs, and a summary with counts.
|
|
49
65
|
*
|
|
50
|
-
* **
|
|
51
|
-
*
|
|
66
|
+
* **Event types:** `activity_task_scheduled/completed/failed`,
|
|
67
|
+
* `child_workflow_execution_started/completed/failed`, `timer_started/fired`,
|
|
68
|
+
* `workflow_execution_started/completed/failed/signaled`
|
|
69
|
+
*
|
|
70
|
+
* **Modes:**
|
|
71
|
+
* - `sparse` (default) — single query, transforms timeline markers into events
|
|
72
|
+
* - `verbose` — recursively fetches child workflows as nested `children`
|
|
73
|
+
*
|
|
74
|
+
* **Options:** `exclude_system`, `omit_results`, `enrich_inputs`, `allow_direct_query`
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```typescript
|
|
78
|
+
* const exec = await handle.exportExecution({ exclude_system: true });
|
|
79
|
+
* for (const event of exec.events) {
|
|
80
|
+
* console.log(event.event_type, event.attributes);
|
|
81
|
+
* }
|
|
82
|
+
* console.log(exec.summary); // { activities: { total: 5, ... }, timers: 1, ... }
|
|
83
|
+
* ```
|
|
52
84
|
*/
|
|
53
85
|
async exportExecution(options) {
|
|
54
86
|
return this.exporter.exportExecution(this.workflowId, this.workflowTopic, options);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.APP_ID = exports.APP_VERSION = exports.getWorkflowYAML = void 0;
|
|
4
|
-
const APP_VERSION = '
|
|
4
|
+
const APP_VERSION = '13';
|
|
5
5
|
exports.APP_VERSION = APP_VERSION;
|
|
6
6
|
const APP_ID = 'durable';
|
|
7
7
|
exports.APP_ID = APP_ID;
|
|
@@ -136,10 +136,6 @@ const getWorkflowYAML = (app, version) => {
|
|
|
136
136
|
maps:
|
|
137
137
|
retryCount: 0
|
|
138
138
|
|
|
139
|
-
throttler:
|
|
140
|
-
title: Pass-through hook between cycle_hook and worker
|
|
141
|
-
type: hook
|
|
142
|
-
|
|
143
139
|
worker:
|
|
144
140
|
title: Main Worker - Calls linked Workflow functions
|
|
145
141
|
type: worker
|
|
@@ -895,10 +891,6 @@ const getWorkflowYAML = (app, version) => {
|
|
|
895
891
|
maps:
|
|
896
892
|
retryCount: 0
|
|
897
893
|
|
|
898
|
-
signaler_throttler:
|
|
899
|
-
title: Pass-through hook between signaler_cycle_hook and signaler_worker
|
|
900
|
-
type: hook
|
|
901
|
-
|
|
902
894
|
signaler_worker:
|
|
903
895
|
title: Signal In - Worker
|
|
904
896
|
type: worker
|
|
@@ -1531,8 +1523,6 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1531
1523
|
- ['{@conditional.nullish}']
|
|
1532
1524
|
## MAIN PROCESS TRANSITIONS ##
|
|
1533
1525
|
cycle_hook:
|
|
1534
|
-
- to: throttler
|
|
1535
|
-
throttler:
|
|
1536
1526
|
- to: worker
|
|
1537
1527
|
worker:
|
|
1538
1528
|
- to: ender
|
|
@@ -1605,8 +1595,6 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1605
1595
|
conditions:
|
|
1606
1596
|
code: 202
|
|
1607
1597
|
signaler_cycle_hook:
|
|
1608
|
-
- to: signaler_throttler
|
|
1609
|
-
signaler_throttler:
|
|
1610
1598
|
- to: signaler_worker
|
|
1611
1599
|
signaler_worker:
|
|
1612
1600
|
- to: signaler_sleeper
|
|
@@ -4,8 +4,25 @@ import { ActivityDetail, DependencyExport, ExportOptions, JobActionExport, JobEx
|
|
|
4
4
|
import { ProviderClient, ProviderTransaction } from '../../types/provider';
|
|
5
5
|
import { StringAnyType, StringStringType, Symbols } from '../../types/serializer';
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* System-level exporter for HotMesh job data. Decodes the flat, symbolized
|
|
8
|
+
* hash stored in Redis/Postgres into a human-readable {@link JobExport}
|
|
9
|
+
* with three sections:
|
|
10
|
+
*
|
|
11
|
+
* - **process** — a nested object reflecting the activity execution tree.
|
|
12
|
+
* Each activity's input, output, and metadata are organized by their
|
|
13
|
+
* dimensional path (e.g., `0/0/worker/output/data`).
|
|
14
|
+
* - **dependencies** — list of dependent jobs (child workflows, hooks, signals)
|
|
15
|
+
* spawned during execution.
|
|
16
|
+
* - **status** — the raw semaphore value from the job hash.
|
|
17
|
+
*
|
|
18
|
+
* Optionally, set `enrich_inputs: true` to produce a flat `activities` array
|
|
19
|
+
* ({@link ActivityDetail}[]) that merges stream message history (inputs, timing,
|
|
20
|
+
* retries) with process outputs — useful for dashboards and debugging views.
|
|
21
|
+
*
|
|
22
|
+
* @remarks
|
|
23
|
+
* This is the lower-level exporter used by the HotMesh engine directly.
|
|
24
|
+
* For durable workflow exports, use the `ExporterService` in `services/durable/exporter`
|
|
25
|
+
* which produces structured timeline and execution history formats.
|
|
9
26
|
*/
|
|
10
27
|
declare class ExporterService {
|
|
11
28
|
appId: string;
|
|
@@ -16,22 +33,39 @@ declare class ExporterService {
|
|
|
16
33
|
/** @hidden */
|
|
17
34
|
constructor(appId: string, store: StoreService<ProviderClient, ProviderTransaction>, logger: ILogger);
|
|
18
35
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
36
|
+
* Export a job as a structured {@link JobExport}.
|
|
37
|
+
*
|
|
38
|
+
* Reads the raw job hash from the store, inflates symbolized keys into
|
|
39
|
+
* readable paths, and organizes data into `process`, `dependencies`,
|
|
40
|
+
* and `status` sections.
|
|
41
|
+
*
|
|
42
|
+
* When `enrich_inputs` is true, also fetches stream message history and
|
|
43
|
+
* produces a flat `activities` array with per-activity input/output,
|
|
44
|
+
* timing, retry attempts, and cycle iteration info.
|
|
45
|
+
*
|
|
46
|
+
* @param jobId - the job ID to export
|
|
47
|
+
* @param options - controls enrichment behavior
|
|
22
48
|
*/
|
|
23
49
|
export(jobId: string, options?: ExportOptions): Promise<JobExport>;
|
|
24
50
|
/**
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* tree-like structure of the unidimensional Hash
|
|
51
|
+
* Resolve a 3-character symbol key to its full path (e.g., `aBC` → `worker/output/data`).
|
|
52
|
+
* Returns the key unchanged if no symbol mapping exists.
|
|
28
53
|
*/
|
|
29
54
|
inflateKey(key: string): string;
|
|
30
55
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
56
|
+
* Decode a raw job hash into a structured {@link JobExport}.
|
|
57
|
+
*
|
|
58
|
+
* Walks every key in the flat hash and classifies it:
|
|
59
|
+
* - **3-char + dimension** (`aBC,0,0`) — activity process state, organized into
|
|
60
|
+
* a nested hierarchy by dimension path and symbolized key
|
|
61
|
+
* - **3-char only** (`aBC`) — top-level job state (done, response, error, etc.)
|
|
62
|
+
*
|
|
63
|
+
* The `process` result is a nested tree where dimensions are path segments
|
|
64
|
+
* (e.g., `{ "0": { "0": { "worker": { "output": { "data": ... } } } } }`).
|
|
65
|
+
*
|
|
66
|
+
* @param jobHash - the raw key-value hash from the store
|
|
67
|
+
* @param dependencyList - raw dependency strings from the store
|
|
68
|
+
* @returns structured export with process tree, dependencies, and status
|
|
35
69
|
*/
|
|
36
70
|
inflate(jobHash: StringStringType, dependencyList: string[]): JobExport;
|
|
37
71
|
/**
|
|
@@ -49,11 +83,16 @@ declare class ExporterService {
|
|
|
49
83
|
*/
|
|
50
84
|
buildActivities(process: StringAnyType, streamHistory: StreamHistoryEntry[]): ActivityDetail[];
|
|
51
85
|
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
86
|
+
* Parse raw dependency strings into structured {@link DependencyExport} entries.
|
|
87
|
+
*
|
|
88
|
+
* Each dependency string encodes the action type, topic, group ID, and job ID
|
|
89
|
+
* of a spawned sub-job (child workflow, hook, or signal cleanup). The job ID
|
|
90
|
+
* suffix reveals whether it originated from a hook (dimensional address + counter)
|
|
91
|
+
* or the main flow (counter only).
|
|
92
|
+
*
|
|
93
|
+
* @param data - raw dependency strings from the store
|
|
94
|
+
* @param actions - accumulator for action tracking (hooks vs main flow)
|
|
95
|
+
* @returns structured dependency list
|
|
57
96
|
*/
|
|
58
97
|
inflateDependencyData(data: string[], actions: JobActionExport): DependencyExport[];
|
|
59
98
|
}
|
|
@@ -5,8 +5,25 @@ const key_1 = require("../../modules/key");
|
|
|
5
5
|
const utils_1 = require("../../modules/utils");
|
|
6
6
|
const serializer_1 = require("../serializer");
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* System-level exporter for HotMesh job data. Decodes the flat, symbolized
|
|
9
|
+
* hash stored in Redis/Postgres into a human-readable {@link JobExport}
|
|
10
|
+
* with three sections:
|
|
11
|
+
*
|
|
12
|
+
* - **process** — a nested object reflecting the activity execution tree.
|
|
13
|
+
* Each activity's input, output, and metadata are organized by their
|
|
14
|
+
* dimensional path (e.g., `0/0/worker/output/data`).
|
|
15
|
+
* - **dependencies** — list of dependent jobs (child workflows, hooks, signals)
|
|
16
|
+
* spawned during execution.
|
|
17
|
+
* - **status** — the raw semaphore value from the job hash.
|
|
18
|
+
*
|
|
19
|
+
* Optionally, set `enrich_inputs: true` to produce a flat `activities` array
|
|
20
|
+
* ({@link ActivityDetail}[]) that merges stream message history (inputs, timing,
|
|
21
|
+
* retries) with process outputs — useful for dashboards and debugging views.
|
|
22
|
+
*
|
|
23
|
+
* @remarks
|
|
24
|
+
* This is the lower-level exporter used by the HotMesh engine directly.
|
|
25
|
+
* For durable workflow exports, use the `ExporterService` in `services/durable/exporter`
|
|
26
|
+
* which produces structured timeline and execution history formats.
|
|
10
27
|
*/
|
|
11
28
|
class ExporterService {
|
|
12
29
|
/** @hidden */
|
|
@@ -16,9 +33,18 @@ class ExporterService {
|
|
|
16
33
|
this.store = store;
|
|
17
34
|
}
|
|
18
35
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
36
|
+
* Export a job as a structured {@link JobExport}.
|
|
37
|
+
*
|
|
38
|
+
* Reads the raw job hash from the store, inflates symbolized keys into
|
|
39
|
+
* readable paths, and organizes data into `process`, `dependencies`,
|
|
40
|
+
* and `status` sections.
|
|
41
|
+
*
|
|
42
|
+
* When `enrich_inputs` is true, also fetches stream message history and
|
|
43
|
+
* produces a flat `activities` array with per-activity input/output,
|
|
44
|
+
* timing, retry attempts, and cycle iteration info.
|
|
45
|
+
*
|
|
46
|
+
* @param jobId - the job ID to export
|
|
47
|
+
* @param options - controls enrichment behavior
|
|
22
48
|
*/
|
|
23
49
|
async export(jobId, options = {}) {
|
|
24
50
|
if (!this.symbols) {
|
|
@@ -35,18 +61,26 @@ class ExporterService {
|
|
|
35
61
|
return jobExport;
|
|
36
62
|
}
|
|
37
63
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* tree-like structure of the unidimensional Hash
|
|
64
|
+
* Resolve a 3-character symbol key to its full path (e.g., `aBC` → `worker/output/data`).
|
|
65
|
+
* Returns the key unchanged if no symbol mapping exists.
|
|
41
66
|
*/
|
|
42
67
|
inflateKey(key) {
|
|
43
68
|
return key in this.symbols ? this.symbols[key] : key;
|
|
44
69
|
}
|
|
45
70
|
/**
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
71
|
+
* Decode a raw job hash into a structured {@link JobExport}.
|
|
72
|
+
*
|
|
73
|
+
* Walks every key in the flat hash and classifies it:
|
|
74
|
+
* - **3-char + dimension** (`aBC,0,0`) — activity process state, organized into
|
|
75
|
+
* a nested hierarchy by dimension path and symbolized key
|
|
76
|
+
* - **3-char only** (`aBC`) — top-level job state (done, response, error, etc.)
|
|
77
|
+
*
|
|
78
|
+
* The `process` result is a nested tree where dimensions are path segments
|
|
79
|
+
* (e.g., `{ "0": { "0": { "worker": { "output": { "data": ... } } } } }`).
|
|
80
|
+
*
|
|
81
|
+
* @param jobHash - the raw key-value hash from the store
|
|
82
|
+
* @param dependencyList - raw dependency strings from the store
|
|
83
|
+
* @returns structured export with process tree, dependencies, and status
|
|
50
84
|
*/
|
|
51
85
|
inflate(jobHash, dependencyList) {
|
|
52
86
|
//the list of actions taken in the workflow and hook functions
|
|
@@ -154,11 +188,16 @@ class ExporterService {
|
|
|
154
188
|
return activities;
|
|
155
189
|
}
|
|
156
190
|
/**
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
191
|
+
* Parse raw dependency strings into structured {@link DependencyExport} entries.
|
|
192
|
+
*
|
|
193
|
+
* Each dependency string encodes the action type, topic, group ID, and job ID
|
|
194
|
+
* of a spawned sub-job (child workflow, hook, or signal cleanup). The job ID
|
|
195
|
+
* suffix reveals whether it originated from a hook (dimensional address + counter)
|
|
196
|
+
* or the main flow (counter only).
|
|
197
|
+
*
|
|
198
|
+
* @param data - raw dependency strings from the store
|
|
199
|
+
* @param actions - accumulator for action tracking (hooks vs main flow)
|
|
200
|
+
* @returns structured dependency list
|
|
162
201
|
*/
|
|
163
202
|
inflateDependencyData(data, actions) {
|
|
164
203
|
const hookReg = /([0-9,]+)-(\d+)$/;
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { StringAnyType } from './serializer';
|
|
2
2
|
export type ExportItem = [string | null, string, any];
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
4
|
+
* Selectable sections of a {@link DurableJobExport}. Use with `allow` (allowlist)
|
|
5
|
+
* or `block` (blocklist) in {@link ExportOptions} to control export size.
|
|
6
|
+
*
|
|
7
|
+
* - `data` — workflow input arguments
|
|
8
|
+
* - `state` — current state (done, response, error, timestamps)
|
|
9
|
+
* - `status` — semaphore value
|
|
10
|
+
* - `timeline` — idempotent operation markers (can be large for complex workflows)
|
|
11
|
+
* - `transitions` — activity execution timestamps (can be large with many cycles)
|
|
5
12
|
*/
|
|
6
13
|
export type ExportFields = 'data' | 'state' | 'status' | 'timeline' | 'transitions';
|
|
7
14
|
export interface ExportOptions {
|
|
@@ -74,6 +81,19 @@ export interface TransitionType {
|
|
|
74
81
|
created: string;
|
|
75
82
|
updated: string;
|
|
76
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* Raw export of a durable workflow job, returned by `handle.export()`.
|
|
86
|
+
*
|
|
87
|
+
* Contains five sections (filterable via {@link ExportOptions}):
|
|
88
|
+
*
|
|
89
|
+
* | Section | Type | Description |
|
|
90
|
+
* |---|---|---|
|
|
91
|
+
* | `data` | object | Workflow input arguments passed to `workflow.start()` |
|
|
92
|
+
* | `state` | object | Current state: `done` flag, `response`, `$error`, `jc`/`ju` timestamps |
|
|
93
|
+
* | `status` | number | Semaphore: `0` = idle/complete, `> 0` = pending activities, `< 0` = error |
|
|
94
|
+
* | `timeline` | array | Ordered idempotent markers for each operation (proxy, child, sleep, signal) |
|
|
95
|
+
* | `transitions` | array | Activity start/stop timestamps organized by dimension |
|
|
96
|
+
*/
|
|
77
97
|
export interface DurableJobExport {
|
|
78
98
|
data?: StringAnyType;
|
|
79
99
|
state?: StringAnyType;
|
|
@@ -212,6 +232,20 @@ export interface WorkflowExecutionSummary {
|
|
|
212
232
|
signals: number;
|
|
213
233
|
}
|
|
214
234
|
export type WorkflowExecutionStatus = 'running' | 'completed' | 'failed';
|
|
235
|
+
/**
|
|
236
|
+
* Structured execution history for a durable workflow, returned by
|
|
237
|
+
* `handle.exportExecution()`.
|
|
238
|
+
*
|
|
239
|
+
* Events are chronologically ordered with sequential `event_id` values.
|
|
240
|
+
* Completed/failed events carry `scheduled_event_id` or `initiated_event_id`
|
|
241
|
+
* back-references to their corresponding scheduled/started events.
|
|
242
|
+
*
|
|
243
|
+
* The `summary` provides aggregate counts by category (activities, child
|
|
244
|
+
* workflows, timers, signals) for quick dashboard rendering.
|
|
245
|
+
*
|
|
246
|
+
* In `verbose` mode, `children` contains recursively fetched child workflow
|
|
247
|
+
* executions, each with their own events and summaries.
|
|
248
|
+
*/
|
|
215
249
|
export interface WorkflowExecution {
|
|
216
250
|
workflow_id: string;
|
|
217
251
|
workflow_type: string;
|
|
@@ -226,10 +260,33 @@ export interface WorkflowExecution {
|
|
|
226
260
|
children?: WorkflowExecution[];
|
|
227
261
|
stream_history?: StreamHistoryEntry[];
|
|
228
262
|
}
|
|
263
|
+
/**
|
|
264
|
+
* Options for `handle.exportExecution()`. Controls event filtering, enrichment,
|
|
265
|
+
* and traversal depth for child workflows.
|
|
266
|
+
*/
|
|
229
267
|
export interface ExecutionExportOptions {
|
|
268
|
+
/**
|
|
269
|
+
* `sparse` (default) — single-query export from the workflow's timeline markers.
|
|
270
|
+
* `verbose` — recursively fetches child workflow jobs and attaches their full
|
|
271
|
+
* event histories as nested `children` arrays.
|
|
272
|
+
*/
|
|
230
273
|
mode?: ExportMode;
|
|
274
|
+
/**
|
|
275
|
+
* When true, omits internal/interceptor activities (names starting with `lt`)
|
|
276
|
+
* from the event list. Useful for user-facing dashboards.
|
|
277
|
+
* @default false
|
|
278
|
+
*/
|
|
231
279
|
exclude_system?: boolean;
|
|
280
|
+
/**
|
|
281
|
+
* When true, strips `result` and `input` payloads from event attributes.
|
|
282
|
+
* Reduces response size while preserving event structure and timing.
|
|
283
|
+
* @default false
|
|
284
|
+
*/
|
|
232
285
|
omit_results?: boolean;
|
|
286
|
+
/**
|
|
287
|
+
* Maximum recursion depth for verbose mode child workflow fetching.
|
|
288
|
+
* @default 5
|
|
289
|
+
*/
|
|
233
290
|
max_depth?: number;
|
|
234
291
|
/**
|
|
235
292
|
* When true, enriches activity and child workflow events with their inputs
|