@gravito/stream 2.0.1 → 2.1.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.
Files changed (83) hide show
  1. package/README.md +127 -285
  2. package/README.zh-TW.md +146 -13
  3. package/dist/BatchConsumer.d.ts +81 -0
  4. package/dist/Consumer.d.ts +215 -0
  5. package/dist/DashboardProvider.d.ts +20 -0
  6. package/dist/Job.d.ts +183 -0
  7. package/dist/OrbitStream.d.ts +151 -0
  8. package/dist/QueueManager.d.ts +319 -0
  9. package/dist/Queueable.d.ts +91 -0
  10. package/dist/Scheduler.d.ts +214 -0
  11. package/dist/StreamEventBackend.d.ts +114 -0
  12. package/dist/SystemEventJob.d.ts +33 -0
  13. package/dist/Worker.d.ts +139 -0
  14. package/dist/benchmarks/PerformanceReporter.d.ts +99 -0
  15. package/dist/consumer/ConcurrencyGate.d.ts +55 -0
  16. package/dist/consumer/ConsumerStrategy.d.ts +41 -0
  17. package/dist/consumer/GroupSequencer.d.ts +57 -0
  18. package/dist/consumer/HeartbeatManager.d.ts +65 -0
  19. package/dist/consumer/JobExecutor.d.ts +61 -0
  20. package/dist/consumer/JobSourceGenerator.d.ts +31 -0
  21. package/dist/consumer/PollingStrategy.d.ts +42 -0
  22. package/dist/consumer/ReactiveStrategy.d.ts +41 -0
  23. package/dist/consumer/StreamingConsumer.d.ts +88 -0
  24. package/dist/consumer/index.d.ts +13 -0
  25. package/dist/consumer/types.d.ts +102 -0
  26. package/dist/drivers/BinaryJobFrame.d.ts +78 -0
  27. package/dist/drivers/BullMQDriver.d.ts +186 -0
  28. package/dist/drivers/DatabaseDriver.d.ts +131 -0
  29. package/dist/drivers/GrpcDriver.d.ts +16 -0
  30. package/dist/drivers/KafkaDriver.d.ts +148 -0
  31. package/dist/drivers/MemoryDriver.d.ts +108 -0
  32. package/dist/drivers/QueueDriver.d.ts +250 -0
  33. package/dist/drivers/RabbitMQDriver.d.ts +102 -0
  34. package/dist/drivers/RedisDriver.d.ts +294 -0
  35. package/dist/drivers/SQSDriver.d.ts +111 -0
  36. package/dist/drivers/kafka/BackpressureController.d.ts +60 -0
  37. package/dist/drivers/kafka/BatchProcessor.d.ts +50 -0
  38. package/dist/drivers/kafka/ConsumerLifecycleManager.d.ts +80 -0
  39. package/dist/drivers/kafka/ErrorCategorizer.d.ts +39 -0
  40. package/dist/drivers/kafka/ErrorRecoveryManager.d.ts +100 -0
  41. package/dist/drivers/kafka/HeartbeatManager.d.ts +57 -0
  42. package/dist/drivers/kafka/KafkaDriver.d.ts +138 -0
  43. package/dist/drivers/kafka/KafkaMetrics.d.ts +88 -0
  44. package/dist/drivers/kafka/KafkaNotifier.d.ts +54 -0
  45. package/dist/drivers/kafka/MessageBuffer.d.ts +71 -0
  46. package/dist/drivers/kafka/OffsetTracker.d.ts +63 -0
  47. package/dist/drivers/kafka/PerformanceMonitor.d.ts +88 -0
  48. package/dist/drivers/kafka/RateLimiter.d.ts +52 -0
  49. package/dist/drivers/kafka/RebalanceHandler.d.ts +104 -0
  50. package/dist/drivers/kafka/RingBuffer.d.ts +63 -0
  51. package/dist/drivers/kafka/index.d.ts +22 -0
  52. package/dist/drivers/kafka/types.d.ts +553 -0
  53. package/dist/drivers/prepareJobForTransport.d.ts +10 -0
  54. package/dist/index.cjs +6274 -3777
  55. package/dist/index.cjs.map +71 -0
  56. package/dist/index.d.ts +60 -2233
  57. package/dist/index.js +6955 -4446
  58. package/dist/index.js.map +71 -0
  59. package/dist/locks/DistributedLock.d.ts +175 -0
  60. package/dist/persistence/BufferedPersistence.d.ts +130 -0
  61. package/dist/persistence/BunBufferedPersistence.d.ts +173 -0
  62. package/dist/persistence/MySQLPersistence.d.ts +134 -0
  63. package/dist/persistence/SQLitePersistence.d.ts +133 -0
  64. package/dist/serializers/BinarySerializer.d.ts +42 -0
  65. package/dist/serializers/CachedSerializer.d.ts +38 -0
  66. package/dist/serializers/CborNativeSerializer.d.ts +56 -0
  67. package/dist/serializers/ClassNameSerializer.d.ts +58 -0
  68. package/dist/serializers/JobSerializer.d.ts +33 -0
  69. package/dist/serializers/JsonSerializer.d.ts +28 -0
  70. package/dist/serializers/JsonlSerializer.d.ts +90 -0
  71. package/dist/serializers/MessagePackSerializer.d.ts +29 -0
  72. package/dist/types.d.ts +653 -0
  73. package/dist/workers/BinaryWorkerProtocol.d.ts +77 -0
  74. package/dist/workers/BunWorker.d.ts +179 -0
  75. package/dist/workers/SandboxedWorker.d.ts +132 -0
  76. package/dist/workers/WorkerFactory.d.ts +128 -0
  77. package/dist/workers/WorkerPool.d.ts +186 -0
  78. package/dist/workers/bun-job-executor.d.ts +14 -0
  79. package/dist/workers/index.d.ts +13 -0
  80. package/dist/workers/job-executor.d.ts +9 -0
  81. package/package.json +13 -6
  82. package/proto/queue.proto +101 -0
  83. package/dist/index.d.cts +0 -2242
@@ -0,0 +1,114 @@
1
+ import type { EventBackend, EventTask } from '@gravito/core';
2
+ import type { QueueManager } from './QueueManager';
3
+ /**
4
+ * Retry strategy for events.
5
+ *
6
+ * - 'bull': Use Bull Queue's built-in retry mechanism
7
+ * - 'core': Use EventPriorityQueue's retry logic (not implemented in Stream backend)
8
+ * - 'hybrid': Bull retries + Core DLQ fallback (future phase)
9
+ */
10
+ export type RetryStrategy = 'bull' | 'core' | 'hybrid';
11
+ /**
12
+ * Configuration for StreamEventBackend.
13
+ */
14
+ export interface StreamEventBackendConfig {
15
+ /**
16
+ * Retry strategy to use.
17
+ * @default 'bull'
18
+ */
19
+ retryStrategy?: RetryStrategy;
20
+ /**
21
+ * Whether to integrate with CircuitBreaker.
22
+ * @default false
23
+ */
24
+ circuitBreakerIntegration?: boolean;
25
+ /**
26
+ * Optional DLQ (Dead Letter Queue) handler for failed events.
27
+ */
28
+ dlqHandler?: {
29
+ handle(event: EventTask, error: Error, attempt: number): Promise<void>;
30
+ };
31
+ /**
32
+ * CircuitBreaker getter (injected from core)
33
+ */
34
+ getCircuitBreaker?: (hook: string) => any;
35
+ }
36
+ /**
37
+ * Event backend implementation using Gravito Stream (Bull Queue).
38
+ *
39
+ * Provides persistent, distributed event processing with:
40
+ * - Bull Queue persistence (Redis-backed)
41
+ * - Configurable retry strategies
42
+ * - Optional CircuitBreaker integration
43
+ * - DLQ support for failed events
44
+ *
45
+ * @example
46
+ * ```typescript
47
+ * const queueManager = new QueueManager({
48
+ * default: 'bullmq',
49
+ * connections: {
50
+ * bullmq: {
51
+ * driver: 'bullmq',
52
+ * queue: new Queue('gravito-events', { connection: redis })
53
+ * }
54
+ * }
55
+ * })
56
+ *
57
+ * const backend = new StreamEventBackend(queueManager, {
58
+ * retryStrategy: 'bull',
59
+ * circuitBreakerIntegration: true
60
+ * })
61
+ * ```
62
+ */
63
+ export declare class StreamEventBackend implements EventBackend {
64
+ private queueManager;
65
+ private config;
66
+ constructor(queueManager: QueueManager, config?: StreamEventBackendConfig);
67
+ /**
68
+ * Build Job Push Options from EventOptions.
69
+ *
70
+ * Maps EventOptions to Bull Queue JobPushOptions with retry strategy applied.
71
+ */
72
+ private buildJobOptions;
73
+ /**
74
+ * Enqueue an event task to the stream queue.
75
+ *
76
+ * Applies retry strategy and CircuitBreaker checks based on configuration.
77
+ * Supports DLQ routing for failed events.
78
+ */
79
+ enqueue(task: EventTask): Promise<void>;
80
+ /**
81
+ * Apply retry strategy to the job based on configuration.
82
+ */
83
+ private applyRetryStrategy;
84
+ /**
85
+ * Handle job failure and route to DLQ if configured.
86
+ *
87
+ * Called when a job exhausts all retry attempts.
88
+ */
89
+ handleJobFailure(task: EventTask, error: Error, attempt: number): Promise<void>;
90
+ /**
91
+ * Record a job failure for CircuitBreaker state management.
92
+ *
93
+ * Called when a job fails, regardless of retry status.
94
+ */
95
+ recordJobFailure(task: EventTask, error: Error): void;
96
+ /**
97
+ * Record a job success for CircuitBreaker state management.
98
+ *
99
+ * Called when a job completes successfully.
100
+ */
101
+ recordJobSuccess(task: EventTask): void;
102
+ /**
103
+ * Get the retry strategy configuration.
104
+ */
105
+ getRetryStrategy(): RetryStrategy;
106
+ /**
107
+ * Check if CircuitBreaker integration is enabled.
108
+ */
109
+ isCircuitBreakerEnabled(): boolean;
110
+ /**
111
+ * Get the DLQ handler, if configured.
112
+ */
113
+ getDLQHandler(): StreamEventBackendConfig['dlqHandler'] | undefined;
114
+ }
@@ -0,0 +1,33 @@
1
+ import { Job } from './Job';
2
+ /**
3
+ * SystemEventJob - Internal job for processing Gravito async hooks.
4
+ *
5
+ * @internal
6
+ */
7
+ export declare class SystemEventJob extends Job {
8
+ readonly hook: string;
9
+ readonly args: unknown;
10
+ readonly options: Record<string, any>;
11
+ /**
12
+ * Optional failure callback for DLQ handling.
13
+ */
14
+ private onFailedCallback?;
15
+ constructor(hook: string, args: unknown, options?: Record<string, any>);
16
+ /**
17
+ * Set failure callback for DLQ handling.
18
+ *
19
+ * @param callback - Called when job fails permanently
20
+ * @returns Self for chaining
21
+ */
22
+ onFailed(callback: (error: Error, attempt: number) => Promise<void>): this;
23
+ /**
24
+ * Execute the hook listeners in the worker process.
25
+ */
26
+ handle(): Promise<void>;
27
+ /**
28
+ * Called when job fails permanently after all retries.
29
+ *
30
+ * This method is invoked by the worker when job exhausts all retry attempts.
31
+ */
32
+ failed(error: Error, attempt?: number): Promise<void>;
33
+ }
@@ -0,0 +1,139 @@
1
+ import type { Job } from './Job';
2
+ import { type SandboxedWorkerConfig } from './workers/SandboxedWorker';
3
+ /**
4
+ * Configuration options for the Worker.
5
+ *
6
+ * Controls the execution behavior of jobs, including retry limits and timeouts.
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * const options: WorkerOptions = {
11
+ * maxAttempts: 3,
12
+ * timeout: 30
13
+ * };
14
+ * ```
15
+ */
16
+ export interface WorkerOptions {
17
+ /**
18
+ * The maximum number of attempts for a job before it is marked as failed.
19
+ *
20
+ * This value serves as a default fallback if the job itself does not specify `maxAttempts`.
21
+ */
22
+ maxAttempts?: number;
23
+ /**
24
+ * The maximum execution time for a job in seconds.
25
+ *
26
+ * If the job exceeds this duration, it will be timed out and marked as failed.
27
+ */
28
+ timeout?: number;
29
+ /**
30
+ * Callback function triggered when a job permanently fails.
31
+ *
32
+ * This allows for custom error reporting or cleanup logic outside of the job class.
33
+ */
34
+ onFailed?: (job: Job, error: Error) => Promise<void>;
35
+ /**
36
+ * Enable sandboxed execution using Worker Threads.
37
+ *
38
+ * When enabled, jobs are executed in isolated Worker Threads, providing:
39
+ * - Context isolation: Each job runs in a separate execution environment
40
+ * - Crash protection: Worker crashes don't affect the main thread
41
+ * - Memory limits: Prevent memory leaks from affecting the main process
42
+ * - Timeout enforcement: Jobs exceeding the timeout are forcefully terminated
43
+ *
44
+ * @default false
45
+ */
46
+ sandboxed?: boolean;
47
+ /**
48
+ * Sandboxed worker configuration options.
49
+ *
50
+ * Only used when `sandboxed` is true.
51
+ */
52
+ sandboxConfig?: SandboxedWorkerConfig;
53
+ }
54
+ /**
55
+ * Executes background jobs.
56
+ *
57
+ * The Worker is responsible for running the `handle()` method of a job, managing its lifecycle,
58
+ * enforcing timeouts, and handling retries or failures.
59
+ *
60
+ * Supports two execution modes:
61
+ * - **Standard Mode** (default): Executes jobs directly in the current process
62
+ * - **Sandboxed Mode**: Executes jobs in isolated Worker Threads for enhanced security and stability
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * // Standard mode
67
+ * const worker = new Worker({
68
+ * maxAttempts: 3,
69
+ * timeout: 60
70
+ * });
71
+ *
72
+ * // Sandboxed mode
73
+ * const sandboxedWorker = new Worker({
74
+ * maxAttempts: 3,
75
+ * timeout: 60,
76
+ * sandboxed: true,
77
+ * sandboxConfig: {
78
+ * maxExecutionTime: 30000,
79
+ * maxMemory: 512,
80
+ * isolateContexts: true
81
+ * }
82
+ * });
83
+ *
84
+ * await worker.process(job);
85
+ * ```
86
+ */
87
+ export declare class Worker {
88
+ private options;
89
+ private sandboxedWorker?;
90
+ constructor(options?: WorkerOptions);
91
+ /**
92
+ * Processes a single job instance.
93
+ *
94
+ * 1. Checks attempt counts.
95
+ * 2. Enforces execution timeout (if configured).
96
+ * 3. Runs `job.handle()` (either directly or in a sandboxed Worker Thread).
97
+ * 4. Catches errors and invokes failure handlers if max attempts are reached.
98
+ *
99
+ * @param job - The job to process.
100
+ * @throws {Error} If the job execution fails (to trigger retry logic in the consumer).
101
+ */
102
+ process(job: Job): Promise<void>;
103
+ /**
104
+ * Processes a job in standard mode (directly in current process).
105
+ *
106
+ * @param job - The job to process.
107
+ * @param timeout - Optional timeout in seconds.
108
+ */
109
+ private processStandard;
110
+ /**
111
+ * Processes a job in sandboxed mode (in Worker Thread).
112
+ *
113
+ * @param job - The job to process.
114
+ */
115
+ private processSandboxed;
116
+ /**
117
+ * Serializes a Job instance for Worker Thread execution.
118
+ *
119
+ * @param job - The job to serialize.
120
+ * @returns Serialized job data.
121
+ */
122
+ private serializeJob;
123
+ /**
124
+ * Handles the permanent failure of a job.
125
+ *
126
+ * Invokes the job's `failed()` method and any global `onFailed` callback.
127
+ *
128
+ * @param job - The failed job.
129
+ * @param error - The error that caused the failure.
130
+ */
131
+ private handleFailure;
132
+ /**
133
+ * Terminates the sandboxed worker and releases resources.
134
+ *
135
+ * Should be called when the worker is no longer needed.
136
+ * Only applicable when running in sandboxed mode.
137
+ */
138
+ terminate(): Promise<void>;
139
+ }
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Performance Reporter
3
+ *
4
+ * Generates comprehensive performance reports comparing BunWorker and SandboxedWorker
5
+ */
6
+ export interface BenchmarkResult {
7
+ name: string;
8
+ runtime: 'bun' | 'node';
9
+ metric: string;
10
+ value: number;
11
+ unit: string;
12
+ timestamp: number;
13
+ }
14
+ export interface PerformanceReport {
15
+ title: string;
16
+ timestamp: string;
17
+ environment: {
18
+ runtime: string;
19
+ platform: string;
20
+ nodeVersion?: string;
21
+ bunVersion?: string;
22
+ };
23
+ results: BenchmarkResult[];
24
+ comparisons: PerformanceComparison[];
25
+ summary: string;
26
+ }
27
+ export interface PerformanceComparison {
28
+ metric: string;
29
+ bun: {
30
+ value: number;
31
+ unit: string;
32
+ };
33
+ node: {
34
+ value: number;
35
+ unit: string;
36
+ };
37
+ improvement: {
38
+ percentage: number;
39
+ direction: 'faster' | 'slower' | 'equal';
40
+ };
41
+ }
42
+ /**
43
+ * Performance Reporter for generating benchmark reports
44
+ */
45
+ export declare class PerformanceReporter {
46
+ private results;
47
+ /**
48
+ * Record a benchmark result
49
+ */
50
+ recordResult(result: BenchmarkResult): void;
51
+ /**
52
+ * Record multiple results
53
+ */
54
+ recordResults(results: BenchmarkResult[]): void;
55
+ /**
56
+ * Generate a performance comparison report
57
+ */
58
+ generateReport(): PerformanceReport;
59
+ /**
60
+ * Compare results between Bun and Node.js
61
+ */
62
+ private compareResults;
63
+ /**
64
+ * Calculate improvement percentage
65
+ */
66
+ private calculateImprovement;
67
+ /**
68
+ * Get environment information
69
+ */
70
+ private getEnvironmentInfo;
71
+ /**
72
+ * Generate summary text
73
+ */
74
+ private generateSummary;
75
+ /**
76
+ * Generate markdown report
77
+ */
78
+ generateMarkdown(): string;
79
+ /**
80
+ * Generate JSON report
81
+ */
82
+ generateJSON(): string;
83
+ /**
84
+ * Export results to CSV format
85
+ */
86
+ generateCSV(): string;
87
+ /**
88
+ * Clear recorded results
89
+ */
90
+ clear(): void;
91
+ /**
92
+ * Get recorded results
93
+ */
94
+ getResults(): BenchmarkResult[];
95
+ }
96
+ /**
97
+ * Helper function to create a performance reporter with sample data
98
+ */
99
+ export declare function createSampleReport(): PerformanceReport;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Promise-based Semaphore,用於控制並發執行數量。
3
+ *
4
+ * 完全取代原始 Consumer 中的 `stats.active` + `setTimeout(50)` busy-wait 模式。
5
+ * 使用 Promise 等待機制,當並發數達到上限時,後續的 acquire() 會被掛起,
6
+ * 直到有其他任務 release() 後才會被喚醒,不會浪費 CPU 資源。
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * const gate = new ConcurrencyGate(5)
11
+ *
12
+ * await gate.acquire()
13
+ * try {
14
+ * await doWork()
15
+ * } finally {
16
+ * gate.release()
17
+ * }
18
+ * ```
19
+ */
20
+ export declare class ConcurrencyGate {
21
+ private readonly limit;
22
+ private active;
23
+ /** 等待中的 resolve 函數佇列(FIFO) */
24
+ private waiters;
25
+ constructor(limit: number);
26
+ /**
27
+ * 取得並發許可。
28
+ *
29
+ * 若目前 active < limit,立即遞增 active 並回傳。
30
+ * 否則等待直到有 release() 釋放許可後再獲取。
31
+ */
32
+ acquire(): Promise<void>;
33
+ /**
34
+ * 釋放並發許可。
35
+ *
36
+ * 遞減 active 計數,並喚醒下一個等待者(FIFO 順序)。
37
+ */
38
+ release(): void;
39
+ /**
40
+ * 目前可立即取得的許可數量。
41
+ */
42
+ get available(): number;
43
+ /**
44
+ * 目前正在執行的任務數量。
45
+ */
46
+ get activeCount(): number;
47
+ /**
48
+ * 目前等待中的任務數量。
49
+ */
50
+ get waitingCount(): number;
51
+ /**
52
+ * 最大並發數量上限。
53
+ */
54
+ get concurrencyLimit(): number;
55
+ }
@@ -0,0 +1,41 @@
1
+ import type { Job } from '../Job';
2
+ /**
3
+ * ConsumerStrategy defines the contract for different job consumption modes.
4
+ *
5
+ * Implementations handle the scheduling and fetching of jobs from the queue.
6
+ * This allows pluggable consumption strategies: polling, reactive, hybrid, etc.
7
+ *
8
+ * @public
9
+ */
10
+ export interface ConsumerStrategy {
11
+ /**
12
+ * Starts the consumption strategy.
13
+ *
14
+ * Initiates the job fetching loop based on the specific strategy implementation.
15
+ *
16
+ * @returns A promise that resolves when the strategy loop has started.
17
+ */
18
+ start(): Promise<void>;
19
+ /**
20
+ * Stops the consumption strategy gracefully.
21
+ *
22
+ * Signals the strategy to stop accepting new jobs and clean up resources.
23
+ *
24
+ * @returns A promise that resolves when the strategy has fully stopped.
25
+ */
26
+ stop(): Promise<void>;
27
+ /**
28
+ * Checks if the strategy is currently active.
29
+ *
30
+ * @returns True if the strategy loop is running.
31
+ */
32
+ isRunning(): boolean;
33
+ /**
34
+ * Called by the consumer loop to fetch the next batch of jobs.
35
+ *
36
+ * The strategy determines how to fetch jobs (blocking, non-blocking, reactive, etc.).
37
+ *
38
+ * @returns An array of jobs to process, or empty array if no jobs are available.
39
+ */
40
+ fetchJobs(): Promise<Job[]>;
41
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * 管理每個 groupId 的 FIFO 序列執行器。
3
+ *
4
+ * 確保相同 groupId 的 job 按照 FIFO 順序依序執行,
5
+ * 不同 groupId 的 job 則可以並行執行。
6
+ *
7
+ * 使用 pLimit(1) 為每個 group 建立容量為 1 的限制器,
8
+ * 確保同一 group 同時只有一個 job 在執行。
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * const sequencer = new GroupSequencer()
13
+ *
14
+ * // group1 的 job 依序執行
15
+ * sequencer.run('group1', async () => await processJob(jobA))
16
+ * sequencer.run('group1', async () => await processJob(jobB))
17
+ *
18
+ * // group2 與 group1 並行
19
+ * sequencer.run('group2', async () => await processJob(jobC))
20
+ *
21
+ * // 無 group 的 job 直接執行
22
+ * sequencer.run(undefined, async () => await processJob(jobD))
23
+ * ```
24
+ */
25
+ export declare class GroupSequencer {
26
+ /** Group ID 到 pLimit limiter 的映射 */
27
+ private limiters;
28
+ /** Group ID 到最後使用時間(ms)的映射,用於 TTL 清理 */
29
+ private lastUsed;
30
+ /** 定期清理計時器 */
31
+ private cleanupTimer;
32
+ /** Group limiter 存活時間(毫秒),超過且無任務時清理 */
33
+ private static readonly TTL_MS;
34
+ constructor();
35
+ /**
36
+ * 執行一個任務,確保相同 group 內的任務依序執行。
37
+ *
38
+ * @param groupId - 群組 ID,undefined 表示無群組(直接執行)
39
+ * @param fn - 要執行的非同步任務
40
+ * @returns 任務的 Promise
41
+ */
42
+ run<T>(groupId: string | undefined, fn: () => Promise<T>): Promise<T>;
43
+ /**
44
+ * 清理超過 TTL 且沒有 active/pending 任務的 group limiters。
45
+ *
46
+ * 定期呼叫以避免記憶體洩漏。
47
+ */
48
+ cleanup(): void;
49
+ /**
50
+ * 停止時完全清理所有 limiters 和計時器。
51
+ */
52
+ destroy(): void;
53
+ /**
54
+ * 目前管理中的 group 數量(用於診斷)。
55
+ */
56
+ get groupCount(): number;
57
+ }
@@ -0,0 +1,65 @@
1
+ import type { QueueManager } from '../QueueManager';
2
+ import type { ConsumerStats } from './types';
3
+ /**
4
+ * HeartbeatManager 設定選項。
5
+ */
6
+ export interface HeartbeatManagerOptions {
7
+ /** Worker ID */
8
+ workerId: string;
9
+ /** 要監控的佇列列表 */
10
+ queues: string[];
11
+ /** 連線名稱 */
12
+ connectionName: string;
13
+ /** 心跳間隔(毫秒),預設 5000 */
14
+ interval?: number;
15
+ /** 額外資訊,包含在心跳 payload 中 */
16
+ extraInfo?: Record<string, unknown>;
17
+ /** 監控 key prefix */
18
+ prefix?: string;
19
+ }
20
+ /**
21
+ * 管理 Consumer 的心跳與監控日誌。
22
+ *
23
+ * 定時向 driver 發送心跳信號(reportHeartbeat),
24
+ * 並在支援時發送監控日誌(publishLog)。
25
+ * 所有異常均被靜默捕獲,不影響主流程。
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * const heartbeat = new HeartbeatManager(queueManager, options, () => stats)
30
+ * heartbeat.start()
31
+ * // ... consumer running ...
32
+ * heartbeat.stop()
33
+ * ```
34
+ */
35
+ export declare class HeartbeatManager {
36
+ private readonly queueManager;
37
+ private readonly options;
38
+ /** getter 函數,每次心跳時取得最新統計 */
39
+ private readonly getStats;
40
+ private timer;
41
+ private readonly intervalMs;
42
+ constructor(queueManager: QueueManager, options: HeartbeatManagerOptions,
43
+ /** getter 函數,每次心跳時取得最新統計 */
44
+ getStats: () => ConsumerStats);
45
+ /**
46
+ * 啟動心跳定時器。
47
+ */
48
+ start(): void;
49
+ /**
50
+ * 停止心跳定時器。
51
+ */
52
+ stop(): void;
53
+ /**
54
+ * 發送一次心跳。
55
+ */
56
+ sendHeartbeat(): Promise<void>;
57
+ /**
58
+ * 發送監控日誌。
59
+ *
60
+ * @param level - 日誌等級(info, success, warning, error)
61
+ * @param message - 日誌訊息
62
+ * @param jobId - 相關的 job ID(可選)
63
+ */
64
+ publishLog(level: string, message: string, jobId?: string): Promise<void>;
65
+ }
@@ -0,0 +1,61 @@
1
+ import type { EventEmitter } from 'node:events';
2
+ import type { Job } from '../Job';
3
+ import type { QueueManager } from '../QueueManager';
4
+ import type { Worker } from '../Worker';
5
+ import type { HeartbeatManager } from './HeartbeatManager';
6
+ import type { ConsumerStats, ExecutionResult, ExecutorOptions } from './types';
7
+ /**
8
+ * JobExecutor 負責完整的 Job 執行生命週期。
9
+ *
10
+ * 從原始 Consumer.handleJob() 提取,封裝以下邏輯:
11
+ * - 發射生命週期事件(job:started, job:processed, job:failed 等)
12
+ * - 呼叫 worker.process(job)
13
+ * - 成功後呼叫 queueManager.complete()
14
+ * - 失敗後執行重試邏輯(指數退避 + re-push)
15
+ * - 超出 maxAttempts 後發射 job:failed_permanently 並移入 DLQ
16
+ * - maxRequests 達到時設定 shouldStop = true
17
+ *
18
+ * 所有異常均被捕獲,不拋出(確保管線繼續執行)。
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * const executor = new JobExecutor(queueManager, emitter, stats, heartbeat, options)
23
+ * const result = await executor.execute(job, worker)
24
+ *
25
+ * if (result.shouldStop) {
26
+ * // 停止 consumer
27
+ * }
28
+ * ```
29
+ */
30
+ export declare class JobExecutor {
31
+ private readonly queueManager;
32
+ private readonly emitter;
33
+ private readonly stats;
34
+ private readonly heartbeat;
35
+ private readonly options;
36
+ constructor(queueManager: QueueManager, emitter: EventEmitter, stats: ConsumerStats, heartbeat: HeartbeatManager | null, options: ExecutorOptions);
37
+ /**
38
+ * 執行單一 Job 的完整生命週期。
39
+ *
40
+ * @param job - 要執行的 Job
41
+ * @param worker - Worker 實例
42
+ * @returns ExecutionResult,包含成功/失敗狀態、耗時、shouldStop 旗標
43
+ */
44
+ execute(job: Job, worker: Worker): Promise<ExecutionResult>;
45
+ /**
46
+ * 安排 job 重試,使用指數退避策略。
47
+ */
48
+ private scheduleRetry;
49
+ /**
50
+ * 處理永久失敗的 job,移入 DLQ 並發射事件。
51
+ */
52
+ private handlePermanentFailure;
53
+ /**
54
+ * 檢查是否達到 maxRequests,若達到則發射事件並回傳 shouldStop=true。
55
+ */
56
+ private checkMaxRequests;
57
+ /**
58
+ * 輸出 debug 日誌(僅在 debug=true 時)。
59
+ */
60
+ private log;
61
+ }
@@ -0,0 +1,31 @@
1
+ import type { QueueManager } from '../QueueManager';
2
+ import type { FetchResult, JobSourceOptions, StopSignal } from './types';
3
+ /**
4
+ * Async Generator,用於從佇列持續抓取 Job。
5
+ *
6
+ * 封裝所有抓取策略(blocking/batch/sequential),自適應 backoff,
7
+ * 以及 rate limit 過濾邏輯。每次 yield 一個 FetchResult,
8
+ * 包含本輪抓取的 job 列表和是否使用阻塞模式的資訊。
9
+ *
10
+ * 設計原則:
11
+ * - blocking pop 已在 driver 層等待,不再額外 backoff
12
+ * - 自適應退避:空佇列時指數增長,有 job 時重設
13
+ * - rate limit:每輪抓取前過濾掉受限的佇列
14
+ * - 中止信號:每次 yield 前檢查 signal.aborted
15
+ *
16
+ * @param queueManager - QueueManager 實例
17
+ * @param options - 抓取策略選項
18
+ * @param signal - 中止信號(AbortController.signal)
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * const source = jobSourceGenerator(queueManager, options, controller.signal)
23
+ *
24
+ * for await (const result of source) {
25
+ * for (const job of result.jobs) {
26
+ * await processJob(job)
27
+ * }
28
+ * }
29
+ * ```
30
+ */
31
+ export declare function jobSourceGenerator(queueManager: QueueManager, options: JobSourceOptions, signal: StopSignal): AsyncGenerator<FetchResult>;