import { ILogger } from '../logger'; import { StoreService } from '../store'; import { ExportOptions, DurableJobExport, TimelineType, TransitionType, ExportFields, ExecutionExportOptions, WorkflowExecution, WorkflowExecutionStatus } from '../../types/exporter'; import { ProviderClient, ProviderTransaction } from '../../types/provider'; import { StringStringType, Symbols } from '../../types/serializer'; /** * Parse a HotMesh compact timestamp (YYYYMMDDHHmmss.mmm) into ISO 8601. * Also accepts ISO 8601 strings directly. */ declare function parseTimestamp(raw: string | undefined | null): string | null; /** * Compute duration in milliseconds between two HotMesh timestamps. */ declare function computeDuration(ac: string | undefined, au: string | undefined): number | null; /** * Extract the operation type (proxy, child, start, wait, sleep, hook) * from a timeline key like `-proxy,0,0-1-`. */ declare function extractOperation(key: string): string; /** * Extract the activity name from a timeline entry value's job_id. * * Job ID format: `-{workflowId}-$${activityName}{dimension}-{execIndex}` * Examples: * `-wfId-$analyzeContent-5` → `'analyzeContent'` * `-wfId-$processOrder,0,0-3` → `'processOrder'` */ declare function extractActivityName(value: Record | null): string; /** * Check if an activity name is a system (interceptor) operation. */ declare function isSystemActivity(name: string): boolean; /** * Map HotMesh job state to a human-readable execution status. * * HotMesh semaphore: `0` = idle, `> 0` = pending activities, * `< 0` = failed / interrupted. * * A workflow can be "done" (`state.data.done === true`) while the * semaphore is still > 0 (cleanup activities pending). We check * both the `done` flag and the semaphore to determine status. */ declare function mapStatus(rawStatus: number | undefined, isDone?: boolean, hasError?: boolean): WorkflowExecutionStatus; /** * Exports durable workflow execution data in two formats: * * ### Raw export (`export()`) * Returns a {@link DurableJobExport} with five sections: * - **data** — workflow input arguments (what was passed to `workflow.start()`) * - **state** — current workflow state: `done` flag, `response`, `$error`, timestamps (`jc`/`ju`) * - **status** — HotMesh semaphore (`0` = complete, `> 0` = activities pending, `< 0` = failed) * - **timeline** — ordered list of idempotent operations: proxy activities, child workflows, * sleeps, signals, and collated (Promise.all) results with per-entry timing and output * - **transitions** — activity execution log with `created`/`updated` timestamps per dimension * * Use `allow`/`block` options to limit which sections are returned (e.g., omit * `transitions` to reduce payload size). Use `values: false` to strip result * payloads from timeline entries. * * ### Execution history (`exportExecution()`) * Returns a {@link WorkflowExecution} — a Temporal-style event history with * typed events (`activity_task_scheduled`, `timer_fired`, `workflow_execution_signaled`, etc.), * chronological ordering, back-references between scheduled/completed pairs, and a summary * with activity/child/timer/signal counts. * * Supports **sparse** mode (default, no extra I/O) and **verbose** mode (recursively * fetches child workflow histories up to `max_depth`). Use `enrich_inputs` to attach * activity and child workflow input arguments to events. */ declare class ExporterService { appId: string; logger: ILogger; store: StoreService; symbols: Promise | Symbols; private static symbols; constructor(appId: string, store: StoreService, logger: ILogger); /** * Export the raw workflow job as a structured {@link DurableJobExport}. * * The result contains five sections (filterable via `options.allow` / `options.block`): * * | Section | Contents | * |---|---| * | `data` | Workflow input arguments passed to `workflow.start()` | * | `state` | Current state: `done`, `response`, `$error`, timestamps | * | `status` | Semaphore value: `0` = idle, `> 0` = pending, `< 0` = error | * | `timeline` | Ordered idempotent markers: activities, children, sleeps, signals | * | `transitions` | Per-activity execution timestamps by dimension | * * @param jobId - the workflow ID to export * @param options - controls which sections to include and whether to include values * @returns the exported workflow data * * @example * ```typescript * // Full export * const full = await handle.export(); * * // Timeline only, without result payloads (smaller response) * const slim = await handle.export({ allow: ['timeline'], values: false }); * ``` */ export(jobId: string, options?: ExportOptions): Promise; /** * Read the workflow input arguments without a full export. Resolves the * `trigger/output/data/arguments` symbol and reads that single field from * the job hash, so the cost is one symbol lookup (cached) plus a one-field * `hmget` rather than a whole-hash read. * * @param jobId - the workflow ID * @returns the input arguments array, or undefined if unavailable */ getInput(jobId: string): Promise; /** * Export a workflow execution as a structured event history ({@link WorkflowExecution}). * * Returns a Temporal-style event list with typed events, chronological ordering, * back-references (e.g., `scheduled_event_id` on completed activities), and a * {@link WorkflowExecutionSummary} with counts by category. * * **Event types produced:** * - `workflow_execution_started` / `completed` / `failed` — lifecycle bookends * - `activity_task_scheduled` / `completed` / `failed` — proxy activity calls * - `child_workflow_execution_started` / `completed` / `failed` — child workflows * - `timer_started` / `timer_fired` — `workflow.sleep()` calls * - `workflow_execution_signaled` — `workflow.condition()` signals received * * **Modes:** * - `sparse` (default) — transforms the workflow's timeline markers into events. * No extra database queries beyond the initial job export. * - `verbose` — recursively fetches child workflow jobs and attaches their full * event histories as nested `children` (up to `max_depth`, default 5). * * **Options:** * - `exclude_system` — omit internal/interceptor activities (names starting with `lt`) * - `omit_results` — strip `result` and `input` payloads from event attributes * - `enrich_inputs` — attach activity/child workflow input arguments to events * - `allow_direct_query` — fallback to raw DB queries for expired/pruned jobs * * @param jobId - the workflow ID * @param workflowTopic - the task queue topic (used as `workflow_type`) * @param options - controls mode, filtering, and enrichment * * @example * ```typescript * // Sparse export with system activities filtered out * const exec = await handle.exportExecution({ exclude_system: true }); * console.log(exec.summary.activities.user); // user activity count * * // Verbose export with full child workflow trees * const deep = await handle.exportExecution({ mode: 'verbose', max_depth: 3 }); * console.log(deep.children); // nested WorkflowExecution[] * ``` */ exportExecution(jobId: string, workflowTopic: string, options?: ExecutionExportOptions): Promise; /** * Reconstruct a WorkflowExecution from raw database rows when the job * handle has expired or been pruned. Only available if the store provider * implements getJobByKeyDirect. */ private exportExecutionDirect; /** * Enrich execution events with activity and child workflow inputs. * Queries the store for activity arguments and child workflow arguments. */ private enrichExecutionInputs; /** * Resolve a symbol field from stable JSON path using the symbol registry. */ private resolveSymbolField; /** * Pure transformation: convert a raw DurableJobExport into a * WorkflowExecution event history. */ transformToExecution(raw: DurableJobExport, workflowId: string, workflowTopic: string, options: ExecutionExportOptions): WorkflowExecution; /** * Recursively fetch child workflow executions for verbose mode. */ private fetchChildren; /** * Inflate a raw Redis/Postgres job hash into a structured {@link DurableJobExport}. * * HotMesh stores workflow state as a flat hash with 3-character symbolized keys * (e.g., `aBC,0,0` → `worker/output/data`). This method decodes each entry and * sorts it into one of four buckets: * * - **Transitions** (`aBC,0,0` pattern) — activity start/stop timestamps by dimension * - **Data** (`_`-prefixed keys) — workflow input arguments * - **Timeline** (`-`-prefixed keys) — idempotent operation markers (proxy, child, sleep, etc.) * - **State** (3-char keys) — workflow metadata (done flag, response, error, timestamps) * * Use `options.allow` / `options.block` to limit which sections appear in the result. * * @param jobHash - the raw key-value hash from the store * @param options - filtering and value options * @returns structured export with data, state, status, timeline, and transitions */ inflate(jobHash: StringStringType, options: ExportOptions): DurableJobExport; resolveValue(raw: string, withValues: boolean): Record | string | number | null; /** * Inflates the key * into a human-readable JSON path, reflecting the * tree-like structure of the unidimensional Hash * @private */ inflateKey(key: string): string; filterFields(fullObject: DurableJobExport, block?: ExportFields[], allow?: ExportFields[]): Partial; inflateTransition(match: RegExpMatchArray, value: string, transitionsObject: Record): void; sortEntriesByCreated(obj: { [key: string]: TransitionType; }): TransitionType[]; /** * marker names are overloaded with details like sequence, type, etc */ keyToObject(key: string): { index: number; dimension?: string; secondary?: number; }; /** * idem list has a complicated sort order based on indexes and dimensions */ sortParts(parts: TimelineType[]): TimelineType[]; } export { ExporterService, parseTimestamp, computeDuration, extractOperation, extractActivityName, isSystemActivity, mapStatus, };