@hotmeshio/hotmesh 0.22.8 → 0.23.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/build/package.json +1 -1
- package/build/services/durable/exporter.js +8 -0
- package/build/services/durable/schemas/factory.d.ts +1 -1
- package/build/services/durable/schemas/factory.js +46 -2
- package/build/services/durable/workflow/condition.js +10 -1
- package/build/services/store/index.d.ts +13 -0
- package/build/services/store/providers/postgres/exporter-sql.d.ts +5 -0
- package/build/services/store/providers/postgres/exporter-sql.js +11 -1
- package/build/services/store/providers/postgres/postgres.d.ts +8 -0
- package/build/services/store/providers/postgres/postgres.js +14 -0
- package/build/types/exporter.d.ts +24 -0
- package/package.json +1 -1
package/build/package.json
CHANGED
|
@@ -285,6 +285,14 @@ class ExporterService {
|
|
|
285
285
|
if (options.enrich_inputs) {
|
|
286
286
|
await this.enrichExecutionInputs(execution, jobId);
|
|
287
287
|
}
|
|
288
|
+
// Opt-in upward lineage pointer — one indexed lookup; surfaces the real
|
|
289
|
+
// spawning parent (not the collator $C job) and the root ancestor.
|
|
290
|
+
if (options.include_lineage && this.store.getJobLineage) {
|
|
291
|
+
const jobKey = `hmsh:${this.appId}:j:${jobId}`;
|
|
292
|
+
const lineage = await this.store.getJobLineage(jobKey);
|
|
293
|
+
execution.parent_workflow_id = lineage?.parent_id ?? null;
|
|
294
|
+
execution.origin_id = lineage?.origin_id ?? null;
|
|
295
|
+
}
|
|
288
296
|
return execution;
|
|
289
297
|
}
|
|
290
298
|
/**
|
|
@@ -6,8 +6,9 @@ exports.APP_ID = exports.APP_VERSION = exports.getWorkflowYAML = void 0;
|
|
|
6
6
|
// schema upgrade and hot-swap to it (see WorkerService.activateWorkflow and
|
|
7
7
|
// ClientService.deployAndActivate). Changing the YAML without a bump leaves
|
|
8
8
|
// every already-deployed database on the old schema forever. Numeric string —
|
|
9
|
-
// compared with `Number()` for ordering. (
|
|
10
|
-
|
|
9
|
+
// compared with `Number()` for ordering. (v17: collator_waiter escalation block —
|
|
10
|
+
// escalation-bearing condition() inside Promise.all writes its hmsh_escalations row.)
|
|
11
|
+
const APP_VERSION = '17';
|
|
11
12
|
exports.APP_VERSION = APP_VERSION;
|
|
12
13
|
const APP_ID = 'durable';
|
|
13
14
|
exports.APP_ID = APP_ID;
|
|
@@ -1944,6 +1945,49 @@ const getWorkflowYAML = (app, version) => {
|
|
|
1944
1945
|
- ['{collator_trigger.output.data.items}', '{collator_cycle_hook.output.data.cur_index}']
|
|
1945
1946
|
- ['{@array.get}', duration]
|
|
1946
1947
|
- ['{@object.get}']
|
|
1948
|
+
# Flatten the CURRENT item's escalation config into this activity's own
|
|
1949
|
+
# output so the escalation block below can address it with flat symbols.
|
|
1950
|
+
# mapOutputData runs before the escalation INSERT in Leg1, so these are
|
|
1951
|
+
# resolved in time. For a plain (non-escalation) collated condition these
|
|
1952
|
+
# resolve to undefined and the INSERT is skipped, just like the inline waiter.
|
|
1953
|
+
output:
|
|
1954
|
+
maps:
|
|
1955
|
+
queueConfig:
|
|
1956
|
+
'@pipe':
|
|
1957
|
+
- ['{collator_trigger.output.data.items}', '{collator_cycle_hook.output.data.cur_index}']
|
|
1958
|
+
- ['{@array.get}', queueConfig]
|
|
1959
|
+
- ['{@object.get}']
|
|
1960
|
+
taskQueue:
|
|
1961
|
+
'@pipe':
|
|
1962
|
+
- ['{collator_trigger.output.data.items}', '{collator_cycle_hook.output.data.cur_index}']
|
|
1963
|
+
- ['{@array.get}', taskQueue]
|
|
1964
|
+
- ['{@object.get}']
|
|
1965
|
+
workflowName:
|
|
1966
|
+
'@pipe':
|
|
1967
|
+
- ['{collator_trigger.output.data.items}', '{collator_cycle_hook.output.data.cur_index}']
|
|
1968
|
+
- ['{@array.get}', workflowName]
|
|
1969
|
+
- ['{@object.get}']
|
|
1970
|
+
# Identical in principle to the inline waiter escalation block, but sourced
|
|
1971
|
+
# from the collated item. The escalation signal_key is auto-derived from this
|
|
1972
|
+
# activity's reentry hook rule (wfs.signal, matching item.signalId), so resolve()
|
|
1973
|
+
# and signal() — which double-fire wfs.signal + wfs.wait — reach it correctly.
|
|
1974
|
+
escalation:
|
|
1975
|
+
type: '{$self.output.data.queueConfig.type}'
|
|
1976
|
+
subtype: '{$self.output.data.queueConfig.subtype}'
|
|
1977
|
+
entity: '{$self.output.data.queueConfig.entity}'
|
|
1978
|
+
description: '{$self.output.data.queueConfig.description}'
|
|
1979
|
+
role: '{$self.output.data.queueConfig.role}'
|
|
1980
|
+
priority: '{$self.output.data.queueConfig.priority}'
|
|
1981
|
+
metadata: '{$self.output.data.queueConfig.metadata}'
|
|
1982
|
+
envelope: '{$self.output.data.queueConfig.envelope}'
|
|
1983
|
+
originId: '{$self.output.data.queueConfig.originId}'
|
|
1984
|
+
parentId: '{$self.output.data.queueConfig.parentId}'
|
|
1985
|
+
initiatedBy: '{$self.output.data.queueConfig.initiatedBy}'
|
|
1986
|
+
traceId: '{$self.output.data.queueConfig.traceId}'
|
|
1987
|
+
spanId: '{$self.output.data.queueConfig.spanId}'
|
|
1988
|
+
expiresAt: '{$self.output.data.queueConfig.expiresAt}'
|
|
1989
|
+
taskQueue: '{$self.output.data.taskQueue}'
|
|
1990
|
+
workflowType: '{$self.output.data.workflowName}'
|
|
1947
1991
|
hook:
|
|
1948
1992
|
type: object
|
|
1949
1993
|
properties:
|
|
@@ -160,7 +160,16 @@ async function condition(signalId, timeoutOrConfig) {
|
|
|
160
160
|
type: 'DurableWaitForError',
|
|
161
161
|
code: common_1.HMSH_CODE_DURABLE_WAIT,
|
|
162
162
|
...(timeout ? { duration: (0, common_1.s)(timeout) } : {}),
|
|
163
|
-
|
|
163
|
+
// taskQueue + workflowName ride along so a collated wait (Promise.all) can
|
|
164
|
+
// write a faithful hmsh_escalations row from inside the collator flow —
|
|
165
|
+
// matching the inline waiter, which sources these from its trigger.
|
|
166
|
+
...(queueConfig
|
|
167
|
+
? {
|
|
168
|
+
queueConfig,
|
|
169
|
+
taskQueue: store.get('taskQueue'),
|
|
170
|
+
workflowName: store.get('workflowName'),
|
|
171
|
+
}
|
|
172
|
+
: {}),
|
|
164
173
|
};
|
|
165
174
|
interruptionRegistry.push(interruptionMessage);
|
|
166
175
|
await (0, common_1.sleepImmediate)();
|
|
@@ -157,5 +157,18 @@ declare abstract class StoreService<Provider extends ProviderClient, Transaction
|
|
|
157
157
|
};
|
|
158
158
|
attributes: Record<string, string>;
|
|
159
159
|
}>;
|
|
160
|
+
/**
|
|
161
|
+
* Fetch just the lineage columns (`parent_id`, `origin_id`) for a job via a
|
|
162
|
+
* single indexed lookup on `key`. Powers the exporter's opt-in
|
|
163
|
+
* `include_lineage` pointer — `parent_id` is the real spawning workflow (never
|
|
164
|
+
* the synthetic collator `$C` job), `origin_id` is the root ancestor.
|
|
165
|
+
*
|
|
166
|
+
* @param jobKey - The job key (e.g., "hmsh:durable:j:workflowId")
|
|
167
|
+
* @returns parent/origin ids (null when absent — a null `parent_id` marks a root)
|
|
168
|
+
*/
|
|
169
|
+
getJobLineage?(jobKey: string): Promise<{
|
|
170
|
+
parent_id: string | null;
|
|
171
|
+
origin_id: string | null;
|
|
172
|
+
} | null>;
|
|
160
173
|
}
|
|
161
174
|
export { StoreService };
|
|
@@ -6,6 +6,11 @@
|
|
|
6
6
|
* Fetch job record by key.
|
|
7
7
|
*/
|
|
8
8
|
export declare const GET_JOB_BY_KEY = "\n SELECT id, key, status, created_at, updated_at, expired_at, is_live\n FROM {schema}.jobs\n WHERE key = $1\n LIMIT 1\n";
|
|
9
|
+
/**
|
|
10
|
+
* Fetch just the lineage columns for a job — a single indexed lookup on `key`.
|
|
11
|
+
* Backs the exporter's opt-in `include_lineage` pointer.
|
|
12
|
+
*/
|
|
13
|
+
export declare const GET_JOB_LINEAGE = "\n SELECT parent_id, origin_id\n FROM {schema}.jobs\n WHERE key = $1\n LIMIT 1\n";
|
|
9
14
|
/**
|
|
10
15
|
* Fetch all attributes for a job.
|
|
11
16
|
*/
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* These queries support the exporter's input enrichment and direct query features.
|
|
5
5
|
*/
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.buildChildWorkflowInputsQuery = exports.GET_STREAM_HISTORY_BY_JID_AND_AID = exports.GET_STREAM_HISTORY_BY_JID_AND_TYPE = exports.GET_STREAM_HISTORY_BY_JID = exports.GET_PROXYER_STREAM_INPUTS = exports.GET_ACTIVITY_INPUTS = exports.GET_JOB_ATTRIBUTES = exports.GET_JOB_BY_KEY = void 0;
|
|
7
|
+
exports.buildChildWorkflowInputsQuery = exports.GET_STREAM_HISTORY_BY_JID_AND_AID = exports.GET_STREAM_HISTORY_BY_JID_AND_TYPE = exports.GET_STREAM_HISTORY_BY_JID = exports.GET_PROXYER_STREAM_INPUTS = exports.GET_ACTIVITY_INPUTS = exports.GET_JOB_ATTRIBUTES = exports.GET_JOB_LINEAGE = exports.GET_JOB_BY_KEY = void 0;
|
|
8
8
|
/**
|
|
9
9
|
* Fetch job record by key.
|
|
10
10
|
*/
|
|
@@ -14,6 +14,16 @@ exports.GET_JOB_BY_KEY = `
|
|
|
14
14
|
WHERE key = $1
|
|
15
15
|
LIMIT 1
|
|
16
16
|
`;
|
|
17
|
+
/**
|
|
18
|
+
* Fetch just the lineage columns for a job — a single indexed lookup on `key`.
|
|
19
|
+
* Backs the exporter's opt-in `include_lineage` pointer.
|
|
20
|
+
*/
|
|
21
|
+
exports.GET_JOB_LINEAGE = `
|
|
22
|
+
SELECT parent_id, origin_id
|
|
23
|
+
FROM {schema}.jobs
|
|
24
|
+
WHERE key = $1
|
|
25
|
+
LIMIT 1
|
|
26
|
+
`;
|
|
17
27
|
/**
|
|
18
28
|
* Fetch all attributes for a job.
|
|
19
29
|
*/
|
|
@@ -216,6 +216,14 @@ declare class PostgresStoreService extends StoreService<ProviderClient, Provider
|
|
|
216
216
|
};
|
|
217
217
|
attributes: Record<string, string>;
|
|
218
218
|
}>;
|
|
219
|
+
/**
|
|
220
|
+
* Single indexed lookup of the lineage columns for a job key. Returns the real
|
|
221
|
+
* spawning parent (never the synthetic collator `$C` job) and the root ancestor.
|
|
222
|
+
*/
|
|
223
|
+
getJobLineage(jobKey: string): Promise<{
|
|
224
|
+
parent_id: string | null;
|
|
225
|
+
origin_id: string | null;
|
|
226
|
+
} | null>;
|
|
219
227
|
/**
|
|
220
228
|
* Fetch stream message history for a job from worker_streams.
|
|
221
229
|
* Returns raw activity input/output data from soft-deleted messages.
|
|
@@ -1338,6 +1338,20 @@ class PostgresStoreService extends __1.StoreService {
|
|
|
1338
1338
|
}
|
|
1339
1339
|
return { job, attributes };
|
|
1340
1340
|
}
|
|
1341
|
+
/**
|
|
1342
|
+
* Single indexed lookup of the lineage columns for a job key. Returns the real
|
|
1343
|
+
* spawning parent (never the synthetic collator `$C` job) and the root ancestor.
|
|
1344
|
+
*/
|
|
1345
|
+
async getJobLineage(jobKey) {
|
|
1346
|
+
const { GET_JOB_LINEAGE } = await Promise.resolve().then(() => __importStar(require('./exporter-sql')));
|
|
1347
|
+
const schemaName = this.kvsql().safeName(this.appId);
|
|
1348
|
+
const sql = GET_JOB_LINEAGE.replace(/{schema}/g, schemaName);
|
|
1349
|
+
const result = await this.pgClient.query(sql, [jobKey]);
|
|
1350
|
+
if (result.rows.length === 0)
|
|
1351
|
+
return null;
|
|
1352
|
+
const { parent_id, origin_id } = result.rows[0];
|
|
1353
|
+
return { parent_id: parent_id ?? null, origin_id: origin_id ?? null };
|
|
1354
|
+
}
|
|
1341
1355
|
/**
|
|
1342
1356
|
* Fetch stream message history for a job from worker_streams.
|
|
1343
1357
|
* Returns raw activity input/output data from soft-deleted messages.
|
|
@@ -265,6 +265,19 @@ export interface WorkflowExecution {
|
|
|
265
265
|
summary: WorkflowExecutionSummary;
|
|
266
266
|
children?: WorkflowExecution[];
|
|
267
267
|
stream_history?: StreamHistoryEntry[];
|
|
268
|
+
/**
|
|
269
|
+
* Upward lineage pointer to the real spawning workflow — never the synthetic
|
|
270
|
+
* collator `$C` job. `null` marks a root. Only present when the export was
|
|
271
|
+
* requested with `include_lineage: true`.
|
|
272
|
+
*/
|
|
273
|
+
parent_workflow_id?: string | null;
|
|
274
|
+
/**
|
|
275
|
+
* Root ancestor of this execution; `null` for a root itself (identify roots
|
|
276
|
+
* via a null `parent_workflow_id`). Every descendant carries the same
|
|
277
|
+
* `origin_id`, so a subtree is recoverable in one query. Only present when the
|
|
278
|
+
* export was requested with `include_lineage: true`.
|
|
279
|
+
*/
|
|
280
|
+
origin_id?: string | null;
|
|
268
281
|
}
|
|
269
282
|
/**
|
|
270
283
|
* Options for `handle.exportExecution()`. Controls event filtering, enrichment,
|
|
@@ -310,6 +323,17 @@ export interface ExecutionExportOptions {
|
|
|
310
323
|
* @default false
|
|
311
324
|
*/
|
|
312
325
|
allow_direct_query?: boolean;
|
|
326
|
+
/**
|
|
327
|
+
* When true, populates the export's `parent_workflow_id` and `origin_id` from
|
|
328
|
+
* the jobs table via a single indexed lookup. `parent_workflow_id` is the real
|
|
329
|
+
* spawning workflow (never the synthetic collator `$C` job); `origin_id` is the
|
|
330
|
+
* root ancestor (a null `parent_workflow_id` marks a root). Opt-in so the extra
|
|
331
|
+
* query is only paid when a UI needs upward lineage. Requires a provider that
|
|
332
|
+
* implements `getJobLineage` (e.g., Postgres); a no-op otherwise.
|
|
333
|
+
*
|
|
334
|
+
* @default false
|
|
335
|
+
*/
|
|
336
|
+
include_lineage?: boolean;
|
|
313
337
|
/**
|
|
314
338
|
* When true, fetches the full stream message history for this workflow
|
|
315
339
|
* from the worker_streams table and attaches it as `stream_history`.
|