@supergrowthai/tq 1.0.13 → 1.1.1

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.
Files changed (38) hide show
  1. package/README.md +149 -8
  2. package/dist/{AsyncActions-CZYO8ShR.js → AsyncActions-B8ImDgTo.js} +39 -3
  3. package/dist/AsyncActions-B8ImDgTo.js.map +1 -0
  4. package/dist/{AsyncActions-BOO1ikWz.cjs → AsyncActions-BsxMX_Ib.cjs} +39 -3
  5. package/dist/AsyncActions-BsxMX_Ib.cjs.map +1 -0
  6. package/dist/core/Actions.cjs +23 -1
  7. package/dist/core/Actions.cjs.map +1 -1
  8. package/dist/core/Actions.mjs +23 -1
  9. package/dist/core/Actions.mjs.map +1 -1
  10. package/dist/core/async/AsyncActions.cjs +1 -1
  11. package/dist/core/async/AsyncActions.mjs +1 -1
  12. package/dist/index.cjs +459 -226
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.mjs +459 -226
  15. package/dist/index.mjs.map +1 -1
  16. package/dist/src/core/Actions.d.cts +5 -1
  17. package/dist/src/core/Actions.d.ts +5 -1
  18. package/dist/src/core/TaskHandler.d.cts +6 -0
  19. package/dist/src/core/TaskHandler.d.ts +6 -0
  20. package/dist/src/core/TaskRunner.d.cts +22 -5
  21. package/dist/src/core/TaskRunner.d.ts +22 -5
  22. package/dist/src/core/async/AsyncActions.d.cts +1 -0
  23. package/dist/src/core/async/AsyncActions.d.ts +1 -0
  24. package/dist/src/core/flow/FlowMiddleware.d.cts +6 -1
  25. package/dist/src/core/flow/FlowMiddleware.d.ts +6 -1
  26. package/dist/src/core/flow/IFlowBarrierProvider.d.cts +4 -0
  27. package/dist/src/core/flow/IFlowBarrierProvider.d.ts +4 -0
  28. package/dist/src/core/flow/InMemoryFlowBarrierProvider.d.cts +1 -0
  29. package/dist/src/core/flow/InMemoryFlowBarrierProvider.d.ts +1 -0
  30. package/dist/src/core/lifecycle.d.cts +98 -3
  31. package/dist/src/core/lifecycle.d.ts +98 -3
  32. package/dist/src/providers/ConsoleHealthProvider.d.cts +42 -2
  33. package/dist/src/providers/ConsoleHealthProvider.d.ts +42 -2
  34. package/dist/src/test/lifecycle-events.test.d.cts +31 -0
  35. package/dist/src/test/lifecycle-events.test.d.ts +31 -0
  36. package/package.json +2 -2
  37. package/dist/AsyncActions-BOO1ikWz.cjs.map +0 -1
  38. package/dist/AsyncActions-CZYO8ShR.js.map +0 -1
@@ -3,6 +3,7 @@ import { Logger } from '@supergrowthai/utils';
3
3
  import { CronTask } from '../adapters';
4
4
  import { StartFlowInput } from './flow/types.js';
5
5
  import { EntityTaskProjection } from './entity/IEntityProjectionProvider.js';
6
+ import { IFlowLifecycleProvider } from './lifecycle.js';
6
7
  export interface ActionResults<ID = any> {
7
8
  failedTasks: CronTask<ID>[];
8
9
  successTasks: CronTask<ID>[];
@@ -18,7 +19,10 @@ export declare class Actions<ID = any> implements ExecutorActions<ID> {
18
19
  private readonly _flowProjections;
19
20
  /** Logger for multi-task executors — carries runtime-only context (RFC-005) */
20
21
  readonly log: Logger;
21
- constructor(taskRunnerId: string);
22
+ private readonly flowLifecycleProvider?;
23
+ /** Process identity (hostname-pid-timestamp) for lifecycle events */
24
+ private readonly workerId;
25
+ constructor(taskRunnerId: string, flowLifecycleProvider?: IFlowLifecycleProvider, workerId?: string);
22
26
  /**
23
27
  * Fork execution context for a specific task (for single-task executors)
24
28
  */
@@ -3,6 +3,7 @@ import { Logger } from '@supergrowthai/utils';
3
3
  import { CronTask } from '../adapters';
4
4
  import { StartFlowInput } from './flow/types.js';
5
5
  import { EntityTaskProjection } from './entity/IEntityProjectionProvider.js';
6
+ import { IFlowLifecycleProvider } from './lifecycle.js';
6
7
  export interface ActionResults<ID = any> {
7
8
  failedTasks: CronTask<ID>[];
8
9
  successTasks: CronTask<ID>[];
@@ -18,7 +19,10 @@ export declare class Actions<ID = any> implements ExecutorActions<ID> {
18
19
  private readonly _flowProjections;
19
20
  /** Logger for multi-task executors — carries runtime-only context (RFC-005) */
20
21
  readonly log: Logger;
21
- constructor(taskRunnerId: string);
22
+ private readonly flowLifecycleProvider?;
23
+ /** Process identity (hostname-pid-timestamp) for lifecycle events */
24
+ private readonly workerId;
25
+ constructor(taskRunnerId: string, flowLifecycleProvider?: IFlowLifecycleProvider, workerId?: string);
22
26
  /**
23
27
  * Fork execution context for a specific task (for single-task executors)
24
28
  */
@@ -20,6 +20,7 @@ export declare class TaskHandler<ID> {
20
20
  private matureTaskTimer;
21
21
  private heartbeatTimer;
22
22
  private readonly config;
23
+ private readonly flowMiddleware?;
23
24
  private readonly workerId;
24
25
  private readonly workerStartedAt;
25
26
  private enabledQueues;
@@ -27,6 +28,7 @@ export declare class TaskHandler<ID> {
27
28
  private workerStats;
28
29
  private totalProcessingMs;
29
30
  private readonly queueStats;
31
+ private readonly consumerStatsMap;
30
32
  constructor(messageQueue: IMessageQueue<ID>, taskQueuesManager: TaskQueuesManager<ID>, databaseAdapter: ITaskStorageAdapter<ID>, cacheAdapter: CacheProvider<any>, asyncTaskManager?: IAsyncTaskManager<ID> | undefined, notificationProvider?: ITaskNotificationProvider | undefined, config?: TaskHandlerConfig);
31
33
  private get lifecycleProvider();
32
34
  private get workerProvider();
@@ -54,6 +56,10 @@ export declare class TaskHandler<ID> {
54
56
  private startHeartbeat;
55
57
  private stopHeartbeat;
56
58
  private updateWorkerStats;
59
+ private registerConsumerIfNew;
60
+ private updateConsumerStats;
61
+ private getActiveConsumerStats;
62
+ private emitAllConsumersStopped;
57
63
  private emitLifecycleEvent;
58
64
  processMatureTasks(abortSignal?: AbortSignal): void;
59
65
  private buildTaskContext;
@@ -20,6 +20,7 @@ export declare class TaskHandler<ID> {
20
20
  private matureTaskTimer;
21
21
  private heartbeatTimer;
22
22
  private readonly config;
23
+ private readonly flowMiddleware?;
23
24
  private readonly workerId;
24
25
  private readonly workerStartedAt;
25
26
  private enabledQueues;
@@ -27,6 +28,7 @@ export declare class TaskHandler<ID> {
27
28
  private workerStats;
28
29
  private totalProcessingMs;
29
30
  private readonly queueStats;
31
+ private readonly consumerStatsMap;
30
32
  constructor(messageQueue: IMessageQueue<ID>, taskQueuesManager: TaskQueuesManager<ID>, databaseAdapter: ITaskStorageAdapter<ID>, cacheAdapter: CacheProvider<any>, asyncTaskManager?: IAsyncTaskManager<ID> | undefined, notificationProvider?: ITaskNotificationProvider | undefined, config?: TaskHandlerConfig);
31
33
  private get lifecycleProvider();
32
34
  private get workerProvider();
@@ -54,6 +56,10 @@ export declare class TaskHandler<ID> {
54
56
  private startHeartbeat;
55
57
  private stopHeartbeat;
56
58
  private updateWorkerStats;
59
+ private registerConsumerIfNew;
60
+ private updateConsumerStats;
61
+ private getActiveConsumerStats;
62
+ private emitAllConsumersStopped;
57
63
  private emitLifecycleEvent;
58
64
  processMatureTasks(abortSignal?: AbortSignal): void;
59
65
  private buildTaskContext;
@@ -6,7 +6,7 @@ import { CacheProvider } from 'memoose-js';
6
6
  import { TaskQueuesManager } from './TaskQueuesManager';
7
7
  import { TaskStore } from './TaskStore';
8
8
  import { IAsyncTaskManager } from './async/async-task-manager';
9
- import { ITaskLifecycleProvider, TaskHandlerLifecycleConfig } from './lifecycle.js';
9
+ import { ITaskLifecycleProvider, IFlowLifecycleProvider, TaskHandlerLifecycleConfig } from './lifecycle.js';
10
10
  import { IEntityProjectionProvider, EntityProjectionConfig } from './entity/IEntityProjectionProvider.js';
11
11
  import { FlowMiddleware } from './flow/FlowMiddleware.js';
12
12
  export interface AsyncTask<ID> {
@@ -15,7 +15,25 @@ export interface AsyncTask<ID> {
15
15
  startTime: number;
16
16
  actions: AsyncActions<ID>;
17
17
  }
18
+ export interface TaskRunnerOptions<ID> {
19
+ messageQueue: IMessageQueue<ID>;
20
+ taskQueue: TaskQueuesManager<ID>;
21
+ taskStore: TaskStore<ID>;
22
+ cacheProvider: CacheProvider<any>;
23
+ generateId: () => ID;
24
+ lifecycleProvider?: ITaskLifecycleProvider;
25
+ lifecycleConfig?: TaskHandlerLifecycleConfig;
26
+ entityProjection?: IEntityProjectionProvider<ID>;
27
+ entityProjectionConfig?: EntityProjectionConfig;
28
+ flowMiddleware?: FlowMiddleware<ID>;
29
+ flowLifecycleProvider?: IFlowLifecycleProvider;
30
+ /** Process identity (hostname-pid-timestamp) for lifecycle events */
31
+ workerId?: string;
32
+ }
18
33
  export declare class TaskRunner<ID> {
34
+ private readonly logger;
35
+ private lockManager;
36
+ private readonly taskStartTimes;
19
37
  private messageQueue;
20
38
  private taskQueue;
21
39
  private taskStore;
@@ -25,10 +43,9 @@ export declare class TaskRunner<ID> {
25
43
  private entityProjection?;
26
44
  private entityProjectionConfig?;
27
45
  private flowMiddleware?;
28
- private readonly logger;
29
- private lockManager;
30
- private readonly taskStartTimes;
31
- constructor(messageQueue: IMessageQueue<ID>, taskQueue: TaskQueuesManager<ID>, taskStore: TaskStore<ID>, cacheProvider: CacheProvider<any>, generateId: () => ID, lifecycleProvider?: ITaskLifecycleProvider | undefined, lifecycleConfig?: TaskHandlerLifecycleConfig | undefined, entityProjection?: IEntityProjectionProvider<ID> | undefined, entityProjectionConfig?: EntityProjectionConfig | undefined, flowMiddleware?: FlowMiddleware<ID> | undefined);
46
+ private flowLifecycleProvider?;
47
+ private readonly workerId;
48
+ constructor(opts: TaskRunnerOptions<ID>);
32
49
  /**
33
50
  * Build ALS log store for a single task execution.
34
51
  * Runtime keys (task_id, task_type, worker_id) override user-supplied log_context.
@@ -6,7 +6,7 @@ import { CacheProvider } from 'memoose-js';
6
6
  import { TaskQueuesManager } from './TaskQueuesManager';
7
7
  import { TaskStore } from './TaskStore';
8
8
  import { IAsyncTaskManager } from './async/async-task-manager';
9
- import { ITaskLifecycleProvider, TaskHandlerLifecycleConfig } from './lifecycle.js';
9
+ import { ITaskLifecycleProvider, IFlowLifecycleProvider, TaskHandlerLifecycleConfig } from './lifecycle.js';
10
10
  import { IEntityProjectionProvider, EntityProjectionConfig } from './entity/IEntityProjectionProvider.js';
11
11
  import { FlowMiddleware } from './flow/FlowMiddleware.js';
12
12
  export interface AsyncTask<ID> {
@@ -15,7 +15,25 @@ export interface AsyncTask<ID> {
15
15
  startTime: number;
16
16
  actions: AsyncActions<ID>;
17
17
  }
18
+ export interface TaskRunnerOptions<ID> {
19
+ messageQueue: IMessageQueue<ID>;
20
+ taskQueue: TaskQueuesManager<ID>;
21
+ taskStore: TaskStore<ID>;
22
+ cacheProvider: CacheProvider<any>;
23
+ generateId: () => ID;
24
+ lifecycleProvider?: ITaskLifecycleProvider;
25
+ lifecycleConfig?: TaskHandlerLifecycleConfig;
26
+ entityProjection?: IEntityProjectionProvider<ID>;
27
+ entityProjectionConfig?: EntityProjectionConfig;
28
+ flowMiddleware?: FlowMiddleware<ID>;
29
+ flowLifecycleProvider?: IFlowLifecycleProvider;
30
+ /** Process identity (hostname-pid-timestamp) for lifecycle events */
31
+ workerId?: string;
32
+ }
18
33
  export declare class TaskRunner<ID> {
34
+ private readonly logger;
35
+ private lockManager;
36
+ private readonly taskStartTimes;
19
37
  private messageQueue;
20
38
  private taskQueue;
21
39
  private taskStore;
@@ -25,10 +43,9 @@ export declare class TaskRunner<ID> {
25
43
  private entityProjection?;
26
44
  private entityProjectionConfig?;
27
45
  private flowMiddleware?;
28
- private readonly logger;
29
- private lockManager;
30
- private readonly taskStartTimes;
31
- constructor(messageQueue: IMessageQueue<ID>, taskQueue: TaskQueuesManager<ID>, taskStore: TaskStore<ID>, cacheProvider: CacheProvider<any>, generateId: () => ID, lifecycleProvider?: ITaskLifecycleProvider | undefined, lifecycleConfig?: TaskHandlerLifecycleConfig | undefined, entityProjection?: IEntityProjectionProvider<ID> | undefined, entityProjectionConfig?: EntityProjectionConfig | undefined, flowMiddleware?: FlowMiddleware<ID> | undefined);
46
+ private flowLifecycleProvider?;
47
+ private readonly workerId;
48
+ constructor(opts: TaskRunnerOptions<ID>);
32
49
  /**
33
50
  * Build ALS log store for a single task execution.
34
51
  * Runtime keys (task_id, task_type, worker_id) override user-supplied log_context.
@@ -12,6 +12,7 @@ import { FlowMiddleware } from '../flow/FlowMiddleware.js';
12
12
  export interface AsyncLifecycleEmitter {
13
13
  onCompleted(task: CronTask<any>, result?: unknown): void;
14
14
  onFailed(task: CronTask<any>, error: Error, willRetry: boolean): void;
15
+ onScheduled?(task: CronTask<any>): void;
15
16
  }
16
17
  export declare class AsyncActions<ID = any> {
17
18
  private messageQueue;
@@ -12,6 +12,7 @@ import { FlowMiddleware } from '../flow/FlowMiddleware.js';
12
12
  export interface AsyncLifecycleEmitter {
13
13
  onCompleted(task: CronTask<any>, result?: unknown): void;
14
14
  onFailed(task: CronTask<any>, error: Error, willRetry: boolean): void;
15
+ onScheduled?(task: CronTask<any>): void;
15
16
  }
16
17
  export declare class AsyncActions<ID = any> {
17
18
  private messageQueue;
@@ -1,6 +1,7 @@
1
1
  import { CronTask } from '../../adapters/types.js';
2
2
  import { IFlowBarrierProvider } from './IFlowBarrierProvider.js';
3
3
  import { EntityTaskProjection } from '../entity/IEntityProjectionProvider.js';
4
+ import { IFlowLifecycleProvider } from '../lifecycle.js';
4
5
  export interface FlowPostProcessInput<ID> {
5
6
  successTasks: CronTask<ID>[];
6
7
  failedTasks: CronTask<ID>[];
@@ -12,7 +13,11 @@ export interface FlowPostProcessResult<ID> {
12
13
  export declare class FlowMiddleware<ID> {
13
14
  private readonly barrierProvider;
14
15
  private readonly generateId;
15
- constructor(barrierProvider: IFlowBarrierProvider, generateId: () => ID);
16
+ private readonly flowLifecycleProvider?;
17
+ private readonly workerId;
18
+ constructor(barrierProvider: IFlowBarrierProvider, generateId: () => ID, flowLifecycleProvider?: IFlowLifecycleProvider | undefined, workerId?: string);
19
+ private emitFlowEvent;
20
+ private buildFlowContext;
16
21
  /**
17
22
  * Process completed tasks for flow orchestration.
18
23
  * Called from TaskHandler.postProcessTasks after markFailed/markSuccess.
@@ -1,6 +1,7 @@
1
1
  import { CronTask } from '../../adapters/types.js';
2
2
  import { IFlowBarrierProvider } from './IFlowBarrierProvider.js';
3
3
  import { EntityTaskProjection } from '../entity/IEntityProjectionProvider.js';
4
+ import { IFlowLifecycleProvider } from '../lifecycle.js';
4
5
  export interface FlowPostProcessInput<ID> {
5
6
  successTasks: CronTask<ID>[];
6
7
  failedTasks: CronTask<ID>[];
@@ -12,7 +13,11 @@ export interface FlowPostProcessResult<ID> {
12
13
  export declare class FlowMiddleware<ID> {
13
14
  private readonly barrierProvider;
14
15
  private readonly generateId;
15
- constructor(barrierProvider: IFlowBarrierProvider, generateId: () => ID);
16
+ private readonly flowLifecycleProvider?;
17
+ private readonly workerId;
18
+ constructor(barrierProvider: IFlowBarrierProvider, generateId: () => ID, flowLifecycleProvider?: IFlowLifecycleProvider | undefined, workerId?: string);
19
+ private emitFlowEvent;
20
+ private buildFlowContext;
16
21
  /**
17
22
  * Process completed tasks for flow orchestration.
18
23
  * Called from TaskHandler.postProcessTasks after markFailed/markSuccess.
@@ -43,4 +43,8 @@ export interface IFlowBarrierProvider {
43
43
  * Check if a flow's barrier has been fully met (remaining = 0).
44
44
  */
45
45
  isComplete(flowId: string): Promise<boolean>;
46
+ /**
47
+ * Get the time when a flow's barrier was initialized.
48
+ */
49
+ getStartedAt(flowId: string): Promise<Date | null>;
46
50
  }
@@ -43,4 +43,8 @@ export interface IFlowBarrierProvider {
43
43
  * Check if a flow's barrier has been fully met (remaining = 0).
44
44
  */
45
45
  isComplete(flowId: string): Promise<boolean>;
46
+ /**
47
+ * Get the time when a flow's barrier was initialized.
48
+ */
49
+ getStartedAt(flowId: string): Promise<Date | null>;
46
50
  }
@@ -7,4 +7,5 @@ export declare class InMemoryFlowBarrierProvider implements IFlowBarrierProvider
7
7
  getStepResults(flowId: string): Promise<FlowStepResult[]>;
8
8
  markAborted(flowId: string): Promise<boolean>;
9
9
  isComplete(flowId: string): Promise<boolean>;
10
+ getStartedAt(flowId: string): Promise<Date | null>;
10
11
  }
@@ -7,4 +7,5 @@ export declare class InMemoryFlowBarrierProvider implements IFlowBarrierProvider
7
7
  getStepResults(flowId: string): Promise<FlowStepResult[]>;
8
8
  markAborted(flowId: string): Promise<boolean>;
9
9
  isComplete(flowId: string): Promise<boolean>;
10
+ getStartedAt(flowId: string): Promise<Date | null>;
10
11
  }
@@ -1,4 +1,5 @@
1
1
  import { EntityProjectionConfig, IEntityProjectionProvider } from './entity/IEntityProjectionProvider.js';
2
+ import { IFlowBarrierProvider } from './flow/IFlowBarrierProvider.js';
2
3
  export interface TaskContext {
3
4
  /** Unique task identifier */
4
5
  task_id: string;
@@ -16,8 +17,10 @@ export interface TaskContext {
16
17
  max_retries: number;
17
18
  /** When task was scheduled */
18
19
  scheduled_at: Date;
19
- /** Worker processing this task */
20
+ /** Worker/server processing this task (hostname-pid-timestamp) */
20
21
  worker_id?: string;
22
+ /** Consumer stream identity (provider:queue or shard ID) — distinguishes M consumers on same worker */
23
+ consumer_id?: string;
21
24
  /** User-provided log correlation context (RFC-005) */
22
25
  log_context?: Record<string, string>;
23
26
  }
@@ -59,6 +62,26 @@ export interface ITaskLifecycleProvider {
59
62
  onTaskCancelled?(ctx: TaskContext & {
60
63
  reason: string;
61
64
  }): void | Promise<void>;
65
+ /** Called when a multi-task (batch) executor starts processing a task group */
66
+ onTaskBatchStarted?(ctx: {
67
+ task_type: string;
68
+ queue_id: string;
69
+ tasks: TaskContext[];
70
+ worker_id: string;
71
+ consumer_id?: string;
72
+ started_at: Date;
73
+ }): void | Promise<void>;
74
+ /** Called when a multi-task (batch) executor finishes processing a task group */
75
+ onTaskBatchCompleted?(ctx: {
76
+ task_type: string;
77
+ queue_id: string;
78
+ tasks: TaskContext[];
79
+ worker_id: string;
80
+ consumer_id?: string;
81
+ succeeded: string[];
82
+ failed: string[];
83
+ duration_ms: number;
84
+ }): void | Promise<void>;
62
85
  }
63
86
  export interface WorkerInfo {
64
87
  /** Unique worker identifier */
@@ -87,6 +110,30 @@ export interface WorkerStats {
87
110
  started_at: Date;
88
111
  };
89
112
  }
113
+ export interface ConsumerInfo {
114
+ /** Consumer stream identity (provider:queue or shard ID) */
115
+ consumer_id: string;
116
+ /** Queue this consumer is bound to */
117
+ queue_id: string;
118
+ /** Worker/server hosting this consumer (hostname-pid-timestamp) */
119
+ worker_id: string;
120
+ /** When this consumer was first seen (first batch arrival) */
121
+ started_at: Date;
122
+ }
123
+ export interface ConsumerStats {
124
+ /** Consumer stream identity */
125
+ consumer_id: string;
126
+ /** Queue this consumer is bound to */
127
+ queue_id: string;
128
+ /** Total tasks processed by this consumer */
129
+ tasks_processed: number;
130
+ /** Successfully completed tasks */
131
+ tasks_succeeded: number;
132
+ /** Failed tasks */
133
+ tasks_failed: number;
134
+ /** When the last task was processed */
135
+ last_task_at?: Date;
136
+ }
90
137
  export interface IWorkerLifecycleProvider {
91
138
  /** Called when a worker starts consuming tasks */
92
139
  onWorkerStarted?(info: WorkerInfo): void | Promise<void>;
@@ -95,6 +142,8 @@ export interface IWorkerLifecycleProvider {
95
142
  stats: WorkerStats;
96
143
  memory_usage_mb: number;
97
144
  cpu_percent?: number;
145
+ /** Per-consumer stats for SRE dashboard — identifies all active consumers on this worker */
146
+ active_consumers: ConsumerStats[];
98
147
  }): void | Promise<void>;
99
148
  /** Called when a worker stops */
100
149
  onWorkerStopped?(info: WorkerInfo & {
@@ -113,6 +162,50 @@ export interface IWorkerLifecycleProvider {
113
162
  failed: number;
114
163
  duration_ms: number;
115
164
  }): void | Promise<void>;
165
+ /** Called lazily on first batch arrival for a consumer — use for SRE consumer→worker mapping */
166
+ onConsumerStarted?(info: ConsumerInfo): void | Promise<void>;
167
+ /** Called when a consumer stops (worker shutdown) */
168
+ onConsumerStopped?(info: ConsumerInfo & {
169
+ reason: 'shutdown' | 'error' | 'idle_timeout';
170
+ stats: ConsumerStats;
171
+ }): void | Promise<void>;
172
+ }
173
+ export interface FlowContext {
174
+ flow_id: string;
175
+ total_steps: number;
176
+ join: {
177
+ type: string;
178
+ queue_id: string;
179
+ };
180
+ failure_policy: 'continue' | 'abort';
181
+ entity?: {
182
+ id: string;
183
+ type: string;
184
+ };
185
+ /** Worker/server that emitted this event — for SRE dashboard correlation */
186
+ worker_id: string;
187
+ /** Consumer stream identity — for multi-consumer-per-worker setups */
188
+ consumer_id?: string;
189
+ }
190
+ export interface IFlowLifecycleProvider {
191
+ onFlowStarted?(ctx: FlowContext & {
192
+ started_at: Date;
193
+ step_types: string[];
194
+ }): void | Promise<void>;
195
+ onFlowCompleted?(ctx: FlowContext & {
196
+ duration_ms: number;
197
+ steps_succeeded: number;
198
+ steps_failed: number;
199
+ }): void | Promise<void>;
200
+ onFlowAborted?(ctx: FlowContext & {
201
+ duration_ms: number;
202
+ steps_completed: number;
203
+ trigger_step_index: number;
204
+ }): void | Promise<void>;
205
+ onFlowTimedOut?(ctx: FlowContext & {
206
+ duration_ms: number;
207
+ steps_completed: number;
208
+ }): void | Promise<void>;
116
209
  }
117
210
  export interface TaskHandlerLifecycleConfig {
118
211
  /** Callback execution mode: 'sync' blocks, 'async' is fire-and-forget */
@@ -133,6 +226,8 @@ export interface TaskHandlerConfig {
133
226
  entityProjection?: IEntityProjectionProvider;
134
227
  /** RFC-003: Entity projection configuration */
135
228
  entityProjectionConfig?: EntityProjectionConfig;
136
- /** RFC-002: Flow middleware for fan-out/fan-in orchestration */
137
- flowMiddleware?: import('./flow/FlowMiddleware.js').FlowMiddleware<any>;
229
+ /** RFC-002: Flow barrier provider TaskHandler assembles FlowMiddleware internally */
230
+ flowBarrierProvider?: IFlowBarrierProvider;
231
+ /** Flow lifecycle event provider */
232
+ flowLifecycleProvider?: IFlowLifecycleProvider;
138
233
  }
@@ -1,4 +1,5 @@
1
1
  import { EntityProjectionConfig, IEntityProjectionProvider } from './entity/IEntityProjectionProvider.js';
2
+ import { IFlowBarrierProvider } from './flow/IFlowBarrierProvider.js';
2
3
  export interface TaskContext {
3
4
  /** Unique task identifier */
4
5
  task_id: string;
@@ -16,8 +17,10 @@ export interface TaskContext {
16
17
  max_retries: number;
17
18
  /** When task was scheduled */
18
19
  scheduled_at: Date;
19
- /** Worker processing this task */
20
+ /** Worker/server processing this task (hostname-pid-timestamp) */
20
21
  worker_id?: string;
22
+ /** Consumer stream identity (provider:queue or shard ID) — distinguishes M consumers on same worker */
23
+ consumer_id?: string;
21
24
  /** User-provided log correlation context (RFC-005) */
22
25
  log_context?: Record<string, string>;
23
26
  }
@@ -59,6 +62,26 @@ export interface ITaskLifecycleProvider {
59
62
  onTaskCancelled?(ctx: TaskContext & {
60
63
  reason: string;
61
64
  }): void | Promise<void>;
65
+ /** Called when a multi-task (batch) executor starts processing a task group */
66
+ onTaskBatchStarted?(ctx: {
67
+ task_type: string;
68
+ queue_id: string;
69
+ tasks: TaskContext[];
70
+ worker_id: string;
71
+ consumer_id?: string;
72
+ started_at: Date;
73
+ }): void | Promise<void>;
74
+ /** Called when a multi-task (batch) executor finishes processing a task group */
75
+ onTaskBatchCompleted?(ctx: {
76
+ task_type: string;
77
+ queue_id: string;
78
+ tasks: TaskContext[];
79
+ worker_id: string;
80
+ consumer_id?: string;
81
+ succeeded: string[];
82
+ failed: string[];
83
+ duration_ms: number;
84
+ }): void | Promise<void>;
62
85
  }
63
86
  export interface WorkerInfo {
64
87
  /** Unique worker identifier */
@@ -87,6 +110,30 @@ export interface WorkerStats {
87
110
  started_at: Date;
88
111
  };
89
112
  }
113
+ export interface ConsumerInfo {
114
+ /** Consumer stream identity (provider:queue or shard ID) */
115
+ consumer_id: string;
116
+ /** Queue this consumer is bound to */
117
+ queue_id: string;
118
+ /** Worker/server hosting this consumer (hostname-pid-timestamp) */
119
+ worker_id: string;
120
+ /** When this consumer was first seen (first batch arrival) */
121
+ started_at: Date;
122
+ }
123
+ export interface ConsumerStats {
124
+ /** Consumer stream identity */
125
+ consumer_id: string;
126
+ /** Queue this consumer is bound to */
127
+ queue_id: string;
128
+ /** Total tasks processed by this consumer */
129
+ tasks_processed: number;
130
+ /** Successfully completed tasks */
131
+ tasks_succeeded: number;
132
+ /** Failed tasks */
133
+ tasks_failed: number;
134
+ /** When the last task was processed */
135
+ last_task_at?: Date;
136
+ }
90
137
  export interface IWorkerLifecycleProvider {
91
138
  /** Called when a worker starts consuming tasks */
92
139
  onWorkerStarted?(info: WorkerInfo): void | Promise<void>;
@@ -95,6 +142,8 @@ export interface IWorkerLifecycleProvider {
95
142
  stats: WorkerStats;
96
143
  memory_usage_mb: number;
97
144
  cpu_percent?: number;
145
+ /** Per-consumer stats for SRE dashboard — identifies all active consumers on this worker */
146
+ active_consumers: ConsumerStats[];
98
147
  }): void | Promise<void>;
99
148
  /** Called when a worker stops */
100
149
  onWorkerStopped?(info: WorkerInfo & {
@@ -113,6 +162,50 @@ export interface IWorkerLifecycleProvider {
113
162
  failed: number;
114
163
  duration_ms: number;
115
164
  }): void | Promise<void>;
165
+ /** Called lazily on first batch arrival for a consumer — use for SRE consumer→worker mapping */
166
+ onConsumerStarted?(info: ConsumerInfo): void | Promise<void>;
167
+ /** Called when a consumer stops (worker shutdown) */
168
+ onConsumerStopped?(info: ConsumerInfo & {
169
+ reason: 'shutdown' | 'error' | 'idle_timeout';
170
+ stats: ConsumerStats;
171
+ }): void | Promise<void>;
172
+ }
173
+ export interface FlowContext {
174
+ flow_id: string;
175
+ total_steps: number;
176
+ join: {
177
+ type: string;
178
+ queue_id: string;
179
+ };
180
+ failure_policy: 'continue' | 'abort';
181
+ entity?: {
182
+ id: string;
183
+ type: string;
184
+ };
185
+ /** Worker/server that emitted this event — for SRE dashboard correlation */
186
+ worker_id: string;
187
+ /** Consumer stream identity — for multi-consumer-per-worker setups */
188
+ consumer_id?: string;
189
+ }
190
+ export interface IFlowLifecycleProvider {
191
+ onFlowStarted?(ctx: FlowContext & {
192
+ started_at: Date;
193
+ step_types: string[];
194
+ }): void | Promise<void>;
195
+ onFlowCompleted?(ctx: FlowContext & {
196
+ duration_ms: number;
197
+ steps_succeeded: number;
198
+ steps_failed: number;
199
+ }): void | Promise<void>;
200
+ onFlowAborted?(ctx: FlowContext & {
201
+ duration_ms: number;
202
+ steps_completed: number;
203
+ trigger_step_index: number;
204
+ }): void | Promise<void>;
205
+ onFlowTimedOut?(ctx: FlowContext & {
206
+ duration_ms: number;
207
+ steps_completed: number;
208
+ }): void | Promise<void>;
116
209
  }
117
210
  export interface TaskHandlerLifecycleConfig {
118
211
  /** Callback execution mode: 'sync' blocks, 'async' is fire-and-forget */
@@ -133,6 +226,8 @@ export interface TaskHandlerConfig {
133
226
  entityProjection?: IEntityProjectionProvider;
134
227
  /** RFC-003: Entity projection configuration */
135
228
  entityProjectionConfig?: EntityProjectionConfig;
136
- /** RFC-002: Flow middleware for fan-out/fan-in orchestration */
137
- flowMiddleware?: import('./flow/FlowMiddleware.js').FlowMiddleware<any>;
229
+ /** RFC-002: Flow barrier provider TaskHandler assembles FlowMiddleware internally */
230
+ flowBarrierProvider?: IFlowBarrierProvider;
231
+ /** Flow lifecycle event provider */
232
+ flowLifecycleProvider?: IFlowLifecycleProvider;
138
233
  }
@@ -1,5 +1,5 @@
1
- import { ITaskLifecycleProvider, IWorkerLifecycleProvider, TaskContext, TaskTiming, WorkerInfo, WorkerStats } from '../core/lifecycle.js';
2
- export declare class ConsoleHealthProvider implements ITaskLifecycleProvider, IWorkerLifecycleProvider {
1
+ import { ITaskLifecycleProvider, IWorkerLifecycleProvider, IFlowLifecycleProvider, FlowContext, TaskContext, TaskTiming, WorkerInfo, WorkerStats, ConsumerInfo, ConsumerStats } from '../core/lifecycle.js';
2
+ export declare class ConsoleHealthProvider implements ITaskLifecycleProvider, IWorkerLifecycleProvider, IFlowLifecycleProvider {
3
3
  private readonly prefix;
4
4
  constructor(prefix?: string);
5
5
  onTaskScheduled(ctx: TaskContext): void;
@@ -29,6 +29,7 @@ export declare class ConsoleHealthProvider implements ITaskLifecycleProvider, IW
29
29
  onWorkerHeartbeat(info: WorkerInfo & {
30
30
  stats: WorkerStats;
31
31
  memory_usage_mb: number;
32
+ active_consumers: ConsumerStats[];
32
33
  }): void;
33
34
  onWorkerStopped(info: WorkerInfo & {
34
35
  reason: 'shutdown' | 'error' | 'idle_timeout';
@@ -44,4 +45,43 @@ export declare class ConsoleHealthProvider implements ITaskLifecycleProvider, IW
44
45
  failed: number;
45
46
  duration_ms: number;
46
47
  }): void;
48
+ onConsumerStarted(info: ConsumerInfo): void;
49
+ onConsumerStopped(info: ConsumerInfo & {
50
+ reason: string;
51
+ stats: ConsumerStats;
52
+ }): void;
53
+ onTaskBatchStarted(ctx: {
54
+ task_type: string;
55
+ queue_id: string;
56
+ tasks: TaskContext[];
57
+ worker_id: string;
58
+ started_at: Date;
59
+ }): void;
60
+ onTaskBatchCompleted(ctx: {
61
+ task_type: string;
62
+ queue_id: string;
63
+ tasks: TaskContext[];
64
+ worker_id: string;
65
+ succeeded: string[];
66
+ failed: string[];
67
+ duration_ms: number;
68
+ }): void;
69
+ onFlowStarted(ctx: FlowContext & {
70
+ started_at: Date;
71
+ step_types: string[];
72
+ }): void;
73
+ onFlowCompleted(ctx: FlowContext & {
74
+ duration_ms: number;
75
+ steps_succeeded: number;
76
+ steps_failed: number;
77
+ }): void;
78
+ onFlowAborted(ctx: FlowContext & {
79
+ duration_ms: number;
80
+ steps_completed: number;
81
+ trigger_step_index: number;
82
+ }): void;
83
+ onFlowTimedOut(ctx: FlowContext & {
84
+ duration_ms: number;
85
+ steps_completed: number;
86
+ }): void;
47
87
  }