@gravito/stream 2.0.2 → 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.
- package/README.md +27 -1
- package/dist/BatchConsumer.d.ts +81 -0
- package/dist/Consumer.d.ts +215 -0
- package/dist/DashboardProvider.d.ts +20 -0
- package/dist/Job.d.ts +183 -0
- package/dist/OrbitStream.d.ts +151 -0
- package/dist/QueueManager.d.ts +319 -0
- package/dist/Queueable.d.ts +91 -0
- package/dist/Scheduler.d.ts +214 -0
- package/dist/StreamEventBackend.d.ts +114 -0
- package/dist/SystemEventJob.d.ts +33 -0
- package/dist/Worker.d.ts +139 -0
- package/dist/benchmarks/PerformanceReporter.d.ts +99 -0
- package/dist/consumer/ConcurrencyGate.d.ts +55 -0
- package/dist/consumer/ConsumerStrategy.d.ts +41 -0
- package/dist/consumer/GroupSequencer.d.ts +57 -0
- package/dist/consumer/HeartbeatManager.d.ts +65 -0
- package/dist/consumer/JobExecutor.d.ts +61 -0
- package/dist/consumer/JobSourceGenerator.d.ts +31 -0
- package/dist/consumer/PollingStrategy.d.ts +42 -0
- package/dist/consumer/ReactiveStrategy.d.ts +41 -0
- package/dist/consumer/StreamingConsumer.d.ts +88 -0
- package/dist/consumer/index.d.ts +13 -0
- package/dist/consumer/types.d.ts +102 -0
- package/dist/drivers/BinaryJobFrame.d.ts +78 -0
- package/dist/drivers/BullMQDriver.d.ts +186 -0
- package/dist/drivers/DatabaseDriver.d.ts +131 -0
- package/dist/drivers/GrpcDriver.d.ts +16 -0
- package/dist/drivers/KafkaDriver.d.ts +148 -0
- package/dist/drivers/MemoryDriver.d.ts +108 -0
- package/dist/drivers/QueueDriver.d.ts +250 -0
- package/dist/drivers/RabbitMQDriver.d.ts +102 -0
- package/dist/drivers/RedisDriver.d.ts +294 -0
- package/dist/drivers/SQSDriver.d.ts +111 -0
- package/dist/drivers/kafka/BackpressureController.d.ts +60 -0
- package/dist/drivers/kafka/BatchProcessor.d.ts +50 -0
- package/dist/drivers/kafka/ConsumerLifecycleManager.d.ts +80 -0
- package/dist/drivers/kafka/ErrorCategorizer.d.ts +39 -0
- package/dist/drivers/kafka/ErrorRecoveryManager.d.ts +100 -0
- package/dist/drivers/kafka/HeartbeatManager.d.ts +57 -0
- package/dist/drivers/kafka/KafkaDriver.d.ts +138 -0
- package/dist/drivers/kafka/KafkaMetrics.d.ts +88 -0
- package/dist/drivers/kafka/KafkaNotifier.d.ts +54 -0
- package/dist/drivers/kafka/MessageBuffer.d.ts +71 -0
- package/dist/drivers/kafka/OffsetTracker.d.ts +63 -0
- package/dist/drivers/kafka/PerformanceMonitor.d.ts +88 -0
- package/dist/drivers/kafka/RateLimiter.d.ts +52 -0
- package/dist/drivers/kafka/RebalanceHandler.d.ts +104 -0
- package/dist/drivers/kafka/RingBuffer.d.ts +63 -0
- package/dist/drivers/kafka/index.d.ts +22 -0
- package/dist/drivers/kafka/types.d.ts +553 -0
- package/dist/drivers/prepareJobForTransport.d.ts +10 -0
- package/dist/index.cjs +5644 -5508
- package/dist/index.cjs.map +71 -0
- package/dist/index.d.ts +60 -4378
- package/dist/index.js +5609 -5453
- package/dist/index.js.map +71 -0
- package/dist/locks/DistributedLock.d.ts +175 -0
- package/dist/persistence/BufferedPersistence.d.ts +130 -0
- package/dist/persistence/BunBufferedPersistence.d.ts +173 -0
- package/dist/persistence/MySQLPersistence.d.ts +134 -0
- package/dist/persistence/SQLitePersistence.d.ts +133 -0
- package/dist/serializers/BinarySerializer.d.ts +42 -0
- package/dist/serializers/CachedSerializer.d.ts +38 -0
- package/dist/serializers/CborNativeSerializer.d.ts +56 -0
- package/dist/serializers/ClassNameSerializer.d.ts +58 -0
- package/dist/serializers/JobSerializer.d.ts +33 -0
- package/dist/serializers/JsonSerializer.d.ts +28 -0
- package/dist/serializers/JsonlSerializer.d.ts +90 -0
- package/dist/serializers/MessagePackSerializer.d.ts +29 -0
- package/dist/types.d.ts +653 -0
- package/dist/workers/BinaryWorkerProtocol.d.ts +77 -0
- package/dist/workers/BunWorker.d.ts +179 -0
- package/dist/workers/SandboxedWorker.d.ts +132 -0
- package/dist/workers/WorkerFactory.d.ts +128 -0
- package/dist/workers/WorkerPool.d.ts +186 -0
- package/dist/workers/bun-job-executor.d.ts +14 -0
- package/dist/workers/index.d.ts +13 -0
- package/dist/workers/job-executor.d.ts +9 -0
- package/package.json +6 -4
- package/dist/index.d.cts +0 -4387
package/README.md
CHANGED
|
@@ -11,15 +11,33 @@
|
|
|
11
11
|
|
|
12
12
|
## ✨ Features
|
|
13
13
|
|
|
14
|
-
- 🪐 **Orbit
|
|
14
|
+
- 🪐 **Galaxy-Ready Orbit** - Native integration with PlanetCore micro-kernel and dependency injection.
|
|
15
15
|
- 🔌 **Multi-Broker Support** - Built-in drivers for **Redis**, **SQS**, **Kafka**, **RabbitMQ**, **Database** (SQL), and **Memory**.
|
|
16
16
|
- 🛠️ **Job-Based API** - Clean, class-based job definitions with built-in serialization and failure handling.
|
|
17
17
|
- 🚀 **High Throughput** - Optimized for **Bun**, supporting batch consumption, concurrent processing, and adaptive polling.
|
|
18
|
+
- 📡 **Cross-Satellite Event Streaming** - Enable loosely coupled communication between isolated Satellites.
|
|
18
19
|
- 🛡️ **Reliability** - Built-in exponential backoff retries, Dead Letter Queues (DLQ), and sequential job grouping.
|
|
19
20
|
- 📝 **Audit & Persistence** - Optional SQL-based persistence layer for archiving job history and providing complete audit trails.
|
|
20
21
|
- 🕒 **Scheduler** - Built-in CRON-based task scheduling for recurring jobs.
|
|
21
22
|
- 🏢 **Worker Modes** - Run embedded workers during development or standalone worker processes in production.
|
|
22
23
|
|
|
24
|
+
## 🌌 Role in Galaxy Architecture
|
|
25
|
+
|
|
26
|
+
In the **Gravito Galaxy Architecture**, Stream acts as the **Async Engine (Background Processing)**.
|
|
27
|
+
|
|
28
|
+
- **Satellite Decoupling**: Instead of Satellite A calling Satellite B synchronously and waiting for a response, Satellite A fires an event/job into Stream, and Satellite B consumes it asynchronously.
|
|
29
|
+
- **Resilience Backbone**: Works hand-in-hand with `@gravito/resilience` to ensure that failed web requests or heavy tasks are retried in the background without affecting the user experience.
|
|
30
|
+
- **Distributed State**: Facilitates event-driven architecture (EDA), allowing multiple Satellites to react to the same domain event reliably.
|
|
31
|
+
|
|
32
|
+
```mermaid
|
|
33
|
+
graph TD
|
|
34
|
+
SatA[Satellite: Order] -- "Push Job" --> Stream{Stream Orbit}
|
|
35
|
+
Stream -- "Queue: emails" --> Worker1[Worker Pool]
|
|
36
|
+
Worker1 --> SatB[Satellite: Notification]
|
|
37
|
+
Stream -- "Queue: payments" --> Worker2[Worker Pool]
|
|
38
|
+
Worker2 --> SatC[Satellite: Finance]
|
|
39
|
+
```
|
|
40
|
+
|
|
23
41
|
## 📦 Installation
|
|
24
42
|
|
|
25
43
|
```bash
|
|
@@ -148,6 +166,14 @@ Accessed via `c.get('queue')` or `core.container.make('queue')`.
|
|
|
148
166
|
- **`backoff(seconds, multiplier?)`**: Configure retry strategy.
|
|
149
167
|
- **`withPriority(priority)`**: Set job priority.
|
|
150
168
|
|
|
169
|
+
## 📚 Documentation
|
|
170
|
+
|
|
171
|
+
Detailed guides and references for the Galaxy Architecture:
|
|
172
|
+
|
|
173
|
+
- [🏗️ **Architecture Overview**](./README.md) — Multi-broker queue and job system.
|
|
174
|
+
- [📡 **Event-Driven Architecture**](./doc/EVENT_DRIVEN_ARCHITECTURE.md) — **NEW**: Cross-Satellite communication and pub/sub.
|
|
175
|
+
- [⚙️ **Worker Configuration**](#-worker-modes) — Embedded vs standalone background workers.
|
|
176
|
+
|
|
151
177
|
## 🔌 Supported Drivers
|
|
152
178
|
|
|
153
179
|
- **Redis** - Feature-rich (DLQ, Rate limiting, Priorities).
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { Job } from './Job';
|
|
2
|
+
import type { QueueManager } from './QueueManager';
|
|
3
|
+
/**
|
|
4
|
+
* Configuration options for the BatchConsumer.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* const options: BatchConsumerOptions = {
|
|
9
|
+
* batchSize: 50,
|
|
10
|
+
* autoAck: false
|
|
11
|
+
* };
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export interface BatchConsumerOptions {
|
|
15
|
+
/**
|
|
16
|
+
* The name of the queue to consume from.
|
|
17
|
+
* @default 'default'
|
|
18
|
+
*/
|
|
19
|
+
queue?: string;
|
|
20
|
+
/**
|
|
21
|
+
* The connection name to use.
|
|
22
|
+
* @default The default connection of QueueManager
|
|
23
|
+
*/
|
|
24
|
+
connection?: string;
|
|
25
|
+
/**
|
|
26
|
+
* The number of jobs to try to retrieve in each batch.
|
|
27
|
+
* @default 10
|
|
28
|
+
*/
|
|
29
|
+
batchSize?: number;
|
|
30
|
+
/**
|
|
31
|
+
* The polling interval in milliseconds when the queue is empty.
|
|
32
|
+
* @default 1000
|
|
33
|
+
*/
|
|
34
|
+
pollInterval?: number;
|
|
35
|
+
/**
|
|
36
|
+
* Whether to automatically complete jobs after the handler returns successfully.
|
|
37
|
+
*
|
|
38
|
+
* If set to `false`, the handler function is responsible for calling `manager.complete()`
|
|
39
|
+
* or `manager.fail()` for each job.
|
|
40
|
+
*
|
|
41
|
+
* @default true
|
|
42
|
+
*/
|
|
43
|
+
autoAck?: boolean;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Specialized consumer for processing jobs in bulk.
|
|
47
|
+
*
|
|
48
|
+
* Unlike the standard `Consumer` which processes jobs individually (even if fetched in batches),
|
|
49
|
+
* the `BatchConsumer` passes an array of jobs to a single handler function. This is ideal for
|
|
50
|
+
* operations that benefit from bulk processing, such as database inserts or API calls that support batching.
|
|
51
|
+
*
|
|
52
|
+
* @public
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* const consumer = new BatchConsumer(manager, async (jobs) => {
|
|
56
|
+
* // Process 100 jobs at once
|
|
57
|
+
* await elasticsearch.bulkIndex(jobs.map(j => j.data));
|
|
58
|
+
* }, { batchSize: 100 });
|
|
59
|
+
*
|
|
60
|
+
* consumer.start();
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export declare class BatchConsumer {
|
|
64
|
+
private manager;
|
|
65
|
+
private handler;
|
|
66
|
+
private running;
|
|
67
|
+
private options;
|
|
68
|
+
constructor(manager: QueueManager, handler: (jobs: Job[]) => Promise<void>, options?: BatchConsumerOptions);
|
|
69
|
+
/**
|
|
70
|
+
* Starts the batch consuming loop.
|
|
71
|
+
*
|
|
72
|
+
* Continuously polls for batches of jobs and passes them to the handler.
|
|
73
|
+
*/
|
|
74
|
+
start(): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Stops the consumer loop.
|
|
77
|
+
*
|
|
78
|
+
* Sets the running flag to false. The loop will exit after the current iteration finishes.
|
|
79
|
+
*/
|
|
80
|
+
stop(): void;
|
|
81
|
+
}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { EventEmitter } from 'node:events';
|
|
2
|
+
import type { ConsumerStats } from './consumer/types';
|
|
3
|
+
import type { QueueManager } from './QueueManager';
|
|
4
|
+
import type { WorkerOptions } from './Worker';
|
|
5
|
+
/**
|
|
6
|
+
* Configuration options for the Consumer.
|
|
7
|
+
*
|
|
8
|
+
* Defines which queues to listen to, connection settings, concurrency levels,
|
|
9
|
+
* and advanced behavior like rate limiting and batch processing.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const options: ConsumerOptions = {
|
|
14
|
+
* queues: ['emails', 'notifications'],
|
|
15
|
+
* concurrency: 5,
|
|
16
|
+
* pollInterval: 2000
|
|
17
|
+
* };
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export interface ConsumerOptions {
|
|
21
|
+
/**
|
|
22
|
+
* List of queue names to consume jobs from.
|
|
23
|
+
*
|
|
24
|
+
* The consumer will poll these queues in the order provided or based on driver logic.
|
|
25
|
+
*/
|
|
26
|
+
queues: string[];
|
|
27
|
+
/**
|
|
28
|
+
* The connection name to use (e.g., 'redis', 'sqs').
|
|
29
|
+
*
|
|
30
|
+
* If not provided, uses the default connection from QueueManager.
|
|
31
|
+
*/
|
|
32
|
+
connection?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Configuration options passed to the underlying Worker.
|
|
35
|
+
*/
|
|
36
|
+
workerOptions?: WorkerOptions;
|
|
37
|
+
/**
|
|
38
|
+
* The interval in milliseconds to wait before polling again when the queue is empty.
|
|
39
|
+
*/
|
|
40
|
+
pollInterval?: number;
|
|
41
|
+
/**
|
|
42
|
+
* Whether to keep the process alive when queues are empty.
|
|
43
|
+
*
|
|
44
|
+
* If false, the consumer will exit the loop when no jobs are found (useful for one-off scripts).
|
|
45
|
+
*/
|
|
46
|
+
keepAlive?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Monitoring configuration.
|
|
49
|
+
*
|
|
50
|
+
* Can be a boolean to enable default monitoring, or an object for advanced configuration.
|
|
51
|
+
*/
|
|
52
|
+
monitor?: boolean | {
|
|
53
|
+
/**
|
|
54
|
+
* The interval in milliseconds for sending heartbeat updates.
|
|
55
|
+
* @default 5000
|
|
56
|
+
*/
|
|
57
|
+
interval?: number;
|
|
58
|
+
/**
|
|
59
|
+
* Additional metadata to include in heartbeat payloads.
|
|
60
|
+
*/
|
|
61
|
+
extraInfo?: Record<string, unknown>;
|
|
62
|
+
/**
|
|
63
|
+
* Key prefix for monitoring events (e.g. for Redis Pub/Sub).
|
|
64
|
+
*/
|
|
65
|
+
prefix?: string;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Rate limiting configuration per queue.
|
|
69
|
+
*
|
|
70
|
+
* Defines the maximum number of jobs to process within a given duration.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* { 'emails': { max: 10, duration: 1000 } } // 10 emails per second
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
rateLimits?: Record<string, {
|
|
78
|
+
max: number;
|
|
79
|
+
duration: number;
|
|
80
|
+
}>;
|
|
81
|
+
/**
|
|
82
|
+
* The maximum number of jobs to process concurrently.
|
|
83
|
+
*
|
|
84
|
+
* @default 1
|
|
85
|
+
*/
|
|
86
|
+
concurrency?: number;
|
|
87
|
+
/**
|
|
88
|
+
* Whether to enforce sequential processing for jobs with the same `groupId`.
|
|
89
|
+
*
|
|
90
|
+
* If true, jobs sharing a `groupId` will be processed one after another,
|
|
91
|
+
* even if global concurrency is high.
|
|
92
|
+
*
|
|
93
|
+
* @default true
|
|
94
|
+
*/
|
|
95
|
+
groupJobsSequential?: boolean;
|
|
96
|
+
/**
|
|
97
|
+
* The minimum polling interval in milliseconds for adaptive polling.
|
|
98
|
+
*
|
|
99
|
+
* @default 100
|
|
100
|
+
*/
|
|
101
|
+
minPollInterval?: number;
|
|
102
|
+
/**
|
|
103
|
+
* The maximum polling interval in milliseconds for adaptive polling.
|
|
104
|
+
*
|
|
105
|
+
* @default 5000
|
|
106
|
+
*/
|
|
107
|
+
maxPollInterval?: number;
|
|
108
|
+
/**
|
|
109
|
+
* The multiplier used to increase the polling interval when the queue is empty.
|
|
110
|
+
*
|
|
111
|
+
* @default 1.5
|
|
112
|
+
*/
|
|
113
|
+
backoffMultiplier?: number;
|
|
114
|
+
/**
|
|
115
|
+
* The number of jobs to try to fetch in a single request.
|
|
116
|
+
*
|
|
117
|
+
* If supported by the driver, fetching multiple jobs reduces network round-trips.
|
|
118
|
+
*
|
|
119
|
+
* @default 1
|
|
120
|
+
*/
|
|
121
|
+
batchSize?: number;
|
|
122
|
+
/**
|
|
123
|
+
* Whether to use blocking operations (like BLPOP in Redis) when polling.
|
|
124
|
+
*
|
|
125
|
+
* Significant optimization for low-latency job pickup. Only applies when `batchSize` is 1.
|
|
126
|
+
*
|
|
127
|
+
* @default true
|
|
128
|
+
*/
|
|
129
|
+
useBlocking?: boolean;
|
|
130
|
+
/**
|
|
131
|
+
* The timeout in seconds for blocking operations.
|
|
132
|
+
*
|
|
133
|
+
* @default 5
|
|
134
|
+
*/
|
|
135
|
+
blockingTimeout?: number;
|
|
136
|
+
/**
|
|
137
|
+
* Enable verbose debug logging for consumer activities.
|
|
138
|
+
*
|
|
139
|
+
* @default false
|
|
140
|
+
*/
|
|
141
|
+
debug?: boolean;
|
|
142
|
+
/**
|
|
143
|
+
* 最大處理請求數量。
|
|
144
|
+
*
|
|
145
|
+
* 當 consumer 處理完這個數量的 job 後會自動停止(觸發 max_requests_reached 事件)。
|
|
146
|
+
* 適用於需要定期重啟 worker 的場景(避免記憶體累積、載入最新程式碼等)。
|
|
147
|
+
*
|
|
148
|
+
* @default undefined (無限制)
|
|
149
|
+
*/
|
|
150
|
+
maxRequests?: number;
|
|
151
|
+
/**
|
|
152
|
+
* Optional event callback for external monitoring systems.
|
|
153
|
+
*
|
|
154
|
+
* Called whenever a job lifecycle event occurs (started, processed, failed, etc.).
|
|
155
|
+
*/
|
|
156
|
+
onEvent?: (event: string, payload: unknown) => void;
|
|
157
|
+
/**
|
|
158
|
+
* Enable reactive (push-based) consumption mode.
|
|
159
|
+
*
|
|
160
|
+
* When enabled, the consumer listens for notifications and pulls jobs reactively
|
|
161
|
+
* instead of polling continuously. This reduces latency and resource usage.
|
|
162
|
+
*
|
|
163
|
+
* @default false
|
|
164
|
+
*/
|
|
165
|
+
reactive?: boolean;
|
|
166
|
+
/**
|
|
167
|
+
* Fallback polling interval (ms) when no notifications are received.
|
|
168
|
+
*
|
|
169
|
+
* In reactive mode, if no notifications arrive for this duration,
|
|
170
|
+
* the consumer will fallback to polling to ensure jobs aren't missed.
|
|
171
|
+
* Prevents starvation if the notification system fails.
|
|
172
|
+
*
|
|
173
|
+
* @default 30000 (30 seconds)
|
|
174
|
+
*/
|
|
175
|
+
reactivePollingFallback?: number;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Consumer 門面類別(Facade),提供向後相容的公開 API。
|
|
179
|
+
*
|
|
180
|
+
* 內部委派給 StreamingConsumer 實作,所有事件都通過 passthrough。
|
|
181
|
+
* 公開 API 與原始 Consumer 完全一致,不破壞現有使用者程式碼。
|
|
182
|
+
*
|
|
183
|
+
* @public
|
|
184
|
+
*/
|
|
185
|
+
export declare class Consumer extends EventEmitter {
|
|
186
|
+
readonly queueManager: QueueManager;
|
|
187
|
+
readonly options: ConsumerOptions;
|
|
188
|
+
/** 內部 StreamingConsumer 實例 */
|
|
189
|
+
private streaming;
|
|
190
|
+
constructor(queueManager: QueueManager, options: ConsumerOptions);
|
|
191
|
+
/**
|
|
192
|
+
* 將 StreamingConsumer 的所有事件轉發給 Consumer。
|
|
193
|
+
*/
|
|
194
|
+
private forwardEvents;
|
|
195
|
+
/**
|
|
196
|
+
* Starts the consumer loop.
|
|
197
|
+
*/
|
|
198
|
+
start(): Promise<void>;
|
|
199
|
+
/**
|
|
200
|
+
* Gracefully stops the consumer.
|
|
201
|
+
*/
|
|
202
|
+
stop(): Promise<void>;
|
|
203
|
+
/**
|
|
204
|
+
* Checks if the consumer is currently active.
|
|
205
|
+
*/
|
|
206
|
+
isRunning(): boolean;
|
|
207
|
+
/**
|
|
208
|
+
* Retrieves current operational statistics.
|
|
209
|
+
*/
|
|
210
|
+
getStats(): ConsumerStats;
|
|
211
|
+
/**
|
|
212
|
+
* Resets the internal statistics counters.
|
|
213
|
+
*/
|
|
214
|
+
resetStats(): void;
|
|
215
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { QueueManager } from './QueueManager';
|
|
2
|
+
/**
|
|
3
|
+
* Provides API routes for the Stream Monitoring Dashboard.
|
|
4
|
+
*
|
|
5
|
+
* This class encapsulates the logic for querying queue statistics,
|
|
6
|
+
* browsing archived jobs, and performing management actions like retrying jobs.
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
export declare class DashboardProvider {
|
|
11
|
+
private manager;
|
|
12
|
+
constructor(manager: QueueManager);
|
|
13
|
+
/**
|
|
14
|
+
* Registers dashboard API routes on the provided core adapter.
|
|
15
|
+
*
|
|
16
|
+
* @param core - The PlanetCore instance.
|
|
17
|
+
* @param basePath - The base path for API routes (default: '/_flux').
|
|
18
|
+
*/
|
|
19
|
+
registerRoutes(core: any, basePath?: string): void;
|
|
20
|
+
}
|
package/dist/Job.d.ts
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import type { Queueable } from './Queueable';
|
|
2
|
+
/**
|
|
3
|
+
* Abstract base class for all background jobs.
|
|
4
|
+
*
|
|
5
|
+
* This class serves as the foundation for creating queueable tasks. It implements the `Queueable`
|
|
6
|
+
* interface for fluent configuration and provides the core structure for defining execution logic (`handle`)
|
|
7
|
+
* and failure handling (`failed`).
|
|
8
|
+
*
|
|
9
|
+
* Subclasses must implement the `handle` method.
|
|
10
|
+
*
|
|
11
|
+
* @public
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* export class SendEmailJob extends Job {
|
|
15
|
+
* constructor(private email: string, private subject: string) {
|
|
16
|
+
* super();
|
|
17
|
+
* }
|
|
18
|
+
*
|
|
19
|
+
* async handle(): Promise<void> {
|
|
20
|
+
* await emailService.send(this.email, this.subject);
|
|
21
|
+
* }
|
|
22
|
+
* }
|
|
23
|
+
*
|
|
24
|
+
* // Usage
|
|
25
|
+
* await queue.push(new SendEmailJob('user@example.com', 'Welcome'))
|
|
26
|
+
* .onQueue('emails')
|
|
27
|
+
* .delay(60);
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare abstract class Job implements Queueable {
|
|
31
|
+
/**
|
|
32
|
+
* Unique identifier for the job instance.
|
|
33
|
+
*
|
|
34
|
+
* Assigned automatically when the job is pushed to the queue.
|
|
35
|
+
*/
|
|
36
|
+
id?: string;
|
|
37
|
+
/**
|
|
38
|
+
* The name of the queue where this job will be processed.
|
|
39
|
+
*/
|
|
40
|
+
queueName?: string;
|
|
41
|
+
/**
|
|
42
|
+
* The name of the connection used to transport this job.
|
|
43
|
+
*/
|
|
44
|
+
connectionName?: string;
|
|
45
|
+
/**
|
|
46
|
+
* Delay in seconds before the job becomes available for processing.
|
|
47
|
+
*/
|
|
48
|
+
delaySeconds?: number;
|
|
49
|
+
/**
|
|
50
|
+
* The current attempt number (starts at 1).
|
|
51
|
+
*/
|
|
52
|
+
attempts?: number;
|
|
53
|
+
/**
|
|
54
|
+
* The maximum number of retry attempts allowed.
|
|
55
|
+
*
|
|
56
|
+
* Can be overridden by the worker configuration or per-job using `maxAttempts`.
|
|
57
|
+
*/
|
|
58
|
+
maxAttempts?: number;
|
|
59
|
+
/**
|
|
60
|
+
* Group ID for sequential processing.
|
|
61
|
+
*
|
|
62
|
+
* Jobs with the same `groupId` will be processed in strict order (FIFO)
|
|
63
|
+
* if the consumer supports it.
|
|
64
|
+
*/
|
|
65
|
+
groupId?: string;
|
|
66
|
+
/**
|
|
67
|
+
* Priority level of the job.
|
|
68
|
+
*/
|
|
69
|
+
priority?: string | number;
|
|
70
|
+
/**
|
|
71
|
+
* Initial delay in seconds before the first retry attempt.
|
|
72
|
+
*
|
|
73
|
+
* Used for exponential backoff calculation.
|
|
74
|
+
*/
|
|
75
|
+
retryAfterSeconds?: number;
|
|
76
|
+
/**
|
|
77
|
+
* Multiplier applied to the retry delay for each subsequent attempt.
|
|
78
|
+
*
|
|
79
|
+
* Used for exponential backoff calculation.
|
|
80
|
+
*/
|
|
81
|
+
retryMultiplier?: number;
|
|
82
|
+
/**
|
|
83
|
+
* Sets the target queue for the job.
|
|
84
|
+
*
|
|
85
|
+
* @param queue - The name of the target queue.
|
|
86
|
+
* @returns The job instance for chaining.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```typescript
|
|
90
|
+
* job.onQueue('billing');
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
onQueue(queue: string): this;
|
|
94
|
+
/**
|
|
95
|
+
* Sets the target connection for the job.
|
|
96
|
+
*
|
|
97
|
+
* @param connection - The name of the connection (e.g., 'redis').
|
|
98
|
+
* @returns The job instance for chaining.
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```typescript
|
|
102
|
+
* job.onConnection('sqs-primary');
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
onConnection(connection: string): this;
|
|
106
|
+
/**
|
|
107
|
+
* Sets the priority of the job.
|
|
108
|
+
*
|
|
109
|
+
* @param priority - The priority level (e.g., 'high', 10).
|
|
110
|
+
* @returns The job instance for chaining.
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* ```typescript
|
|
114
|
+
* job.withPriority('high');
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
withPriority(priority: string | number): this;
|
|
118
|
+
/**
|
|
119
|
+
* Delays the job execution.
|
|
120
|
+
*
|
|
121
|
+
* @param delay - Delay in seconds.
|
|
122
|
+
* @returns The job instance for chaining.
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* job.delay(60); // Run after 1 minute
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
delay(delay: number): this;
|
|
130
|
+
/**
|
|
131
|
+
* Configures the exponential backoff strategy for retries.
|
|
132
|
+
*
|
|
133
|
+
* @param seconds - Initial delay in seconds before the first retry.
|
|
134
|
+
* @param multiplier - Factor by which the delay increases for each subsequent attempt (default: 2).
|
|
135
|
+
* @returns The job instance for chaining.
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```typescript
|
|
139
|
+
* // Wait 5s, then 10s, then 20s...
|
|
140
|
+
* job.backoff(5, 2);
|
|
141
|
+
* ```
|
|
142
|
+
*/
|
|
143
|
+
backoff(seconds: number, multiplier?: number): this;
|
|
144
|
+
/**
|
|
145
|
+
* Calculates the delay for the next retry attempt based on the backoff strategy.
|
|
146
|
+
*
|
|
147
|
+
* Uses the formula: `initialDelay * multiplier^(attempt - 1)`, capped at 1 hour.
|
|
148
|
+
*
|
|
149
|
+
* @param attempt - The current attempt number (1-based).
|
|
150
|
+
* @returns The calculated delay in milliseconds.
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```typescript
|
|
154
|
+
* const nextDelay = job.getRetryDelay(2);
|
|
155
|
+
* ```
|
|
156
|
+
*/
|
|
157
|
+
getRetryDelay(attempt: number): number;
|
|
158
|
+
/**
|
|
159
|
+
* Contains the main business logic of the job.
|
|
160
|
+
*
|
|
161
|
+
* This method is called by the worker to process the job.
|
|
162
|
+
* Implementations should be idempotent if possible.
|
|
163
|
+
*
|
|
164
|
+
* @throws {Error} If the job fails and should be retried.
|
|
165
|
+
*/
|
|
166
|
+
abstract handle(): Promise<void>;
|
|
167
|
+
/**
|
|
168
|
+
* Optional handler for when the job has permanently failed.
|
|
169
|
+
*
|
|
170
|
+
* Called when the job has exhausted all retry attempts.
|
|
171
|
+
* Useful for cleaning up resources, sending alerts, or logging.
|
|
172
|
+
*
|
|
173
|
+
* @param _error - The error that caused the final failure.
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* ```typescript
|
|
177
|
+
* async failed(error: Error) {
|
|
178
|
+
* await notifyAdmin(`Job failed: ${error.message}`);
|
|
179
|
+
* }
|
|
180
|
+
* ```
|
|
181
|
+
*/
|
|
182
|
+
failed(_error: Error): Promise<void>;
|
|
183
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import type { GravitoOrbit, PlanetCore } from '@gravito/core';
|
|
2
|
+
import type { ConsumerOptions } from './Consumer';
|
|
3
|
+
import { QueueManager } from './QueueManager';
|
|
4
|
+
import type { QueueConfig } from './types';
|
|
5
|
+
/**
|
|
6
|
+
* Configuration options for the OrbitStream extension.
|
|
7
|
+
*
|
|
8
|
+
* Extends the standard `QueueConfig` with specific options for integration into
|
|
9
|
+
* the Gravito lifecycle, such as auto-starting workers in development environments.
|
|
10
|
+
*
|
|
11
|
+
* @public
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const options: OrbitStreamOptions = {
|
|
15
|
+
* default: 'redis',
|
|
16
|
+
* autoStartWorker: true
|
|
17
|
+
* };
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export interface OrbitStreamOptions extends QueueConfig {
|
|
21
|
+
/**
|
|
22
|
+
* Automatically start an embedded worker process.
|
|
23
|
+
*
|
|
24
|
+
* If set to `true`, a background worker will be spawned within the main process.
|
|
25
|
+
* This is recommended for development or simple deployments but should be
|
|
26
|
+
* avoided in high-scale production to keep web servers stateless.
|
|
27
|
+
*/
|
|
28
|
+
autoStartWorker?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Configuration options for the embedded worker.
|
|
31
|
+
*
|
|
32
|
+
* Only used if `autoStartWorker` is true. Defines concurrency, polling intervals, etc.
|
|
33
|
+
*/
|
|
34
|
+
workerOptions?: ConsumerOptions;
|
|
35
|
+
/**
|
|
36
|
+
* Configuration for the Stream Monitoring Dashboard API.
|
|
37
|
+
*
|
|
38
|
+
* If enabled, registers API routes for monitoring queue health and job history.
|
|
39
|
+
*
|
|
40
|
+
* @default false
|
|
41
|
+
*/
|
|
42
|
+
dashboard?: boolean | {
|
|
43
|
+
/**
|
|
44
|
+
* Base path for the dashboard API routes.
|
|
45
|
+
* @default '/_flux'
|
|
46
|
+
*/
|
|
47
|
+
path?: string;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The Queue Orbit (Plugin) for Gravito Framework.
|
|
52
|
+
*
|
|
53
|
+
* This class acts as the integration layer between the `@gravito/stream` package
|
|
54
|
+
* and the Gravito core system (`PlanetCore`). It registers the `QueueManager`
|
|
55
|
+
* service, injects it into the request context, and manages the lifecycle of
|
|
56
|
+
* embedded workers.
|
|
57
|
+
*
|
|
58
|
+
* @public
|
|
59
|
+
* @example
|
|
60
|
+
* ```typescript
|
|
61
|
+
* const stream = OrbitStream.configure({
|
|
62
|
+
* default: 'redis',
|
|
63
|
+
* connections: {
|
|
64
|
+
* redis: { driver: 'redis', client: redis }
|
|
65
|
+
* }
|
|
66
|
+
* });
|
|
67
|
+
*
|
|
68
|
+
* await PlanetCore.boot({ orbits: [stream] });
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export declare class OrbitStream implements GravitoOrbit {
|
|
72
|
+
private options;
|
|
73
|
+
private queueManager?;
|
|
74
|
+
private consumer?;
|
|
75
|
+
private core?;
|
|
76
|
+
constructor(options?: OrbitStreamOptions);
|
|
77
|
+
/**
|
|
78
|
+
* Factory method for creating and configuring an OrbitStream instance.
|
|
79
|
+
*
|
|
80
|
+
* Provides a fluent way to instantiate the orbit during application bootstrap.
|
|
81
|
+
*
|
|
82
|
+
* @param options - Configuration options.
|
|
83
|
+
* @returns A new OrbitStream instance.
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* const orbit = OrbitStream.configure({ default: 'memory' });
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
static configure(options: OrbitStreamOptions): OrbitStream;
|
|
91
|
+
/**
|
|
92
|
+
* Installs the Queue system into the Gravito PlanetCore.
|
|
93
|
+
*
|
|
94
|
+
* This lifecycle method:
|
|
95
|
+
* 1. Initializes the `QueueManager`.
|
|
96
|
+
* 2. Registers the `queue` service in the dependency injection container.
|
|
97
|
+
* 3. Sets up a global middleware to inject `QueueManager` into the request context (`c.get('queue')`).
|
|
98
|
+
* 4. Automatically detects and registers database connections if available in the context.
|
|
99
|
+
* 5. Starts the embedded worker if configured.
|
|
100
|
+
*
|
|
101
|
+
* @param core - The PlanetCore instance.
|
|
102
|
+
*/
|
|
103
|
+
install(core: PlanetCore): void;
|
|
104
|
+
/**
|
|
105
|
+
* Starts the embedded worker process.
|
|
106
|
+
*
|
|
107
|
+
* Launches a `Consumer` instance to process jobs in the background.
|
|
108
|
+
* Throws an error if `QueueManager` is not initialized or if a worker is already running.
|
|
109
|
+
*
|
|
110
|
+
* @param options - Consumer configuration options.
|
|
111
|
+
* @throws {Error} If QueueManager is missing or worker is already active.
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* ```typescript
|
|
115
|
+
* orbit.startWorker({ queues: ['default'] });
|
|
116
|
+
* ```
|
|
117
|
+
*/
|
|
118
|
+
startWorker(options: ConsumerOptions): void;
|
|
119
|
+
/**
|
|
120
|
+
* Stops the embedded worker process.
|
|
121
|
+
*
|
|
122
|
+
* Gracefully shuts down the consumer, waiting for active jobs to complete.
|
|
123
|
+
*
|
|
124
|
+
* @returns A promise that resolves when the worker has stopped.
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```typescript
|
|
128
|
+
* await orbit.stopWorker();
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
131
|
+
stopWorker(): Promise<void>;
|
|
132
|
+
/**
|
|
133
|
+
* Retrieves the underlying QueueManager instance.
|
|
134
|
+
*
|
|
135
|
+
* @returns The active QueueManager, or undefined if not installed.
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```typescript
|
|
139
|
+
* const manager = orbit.getQueueManager();
|
|
140
|
+
* ```
|
|
141
|
+
*/
|
|
142
|
+
getQueueManager(): QueueManager | undefined;
|
|
143
|
+
}
|
|
144
|
+
declare module '@gravito/core' {
|
|
145
|
+
interface GravitoVariables {
|
|
146
|
+
/** Queue manager for job processing */
|
|
147
|
+
queue?: QueueManager;
|
|
148
|
+
/** Database service (from orbit-db) */
|
|
149
|
+
db?: unknown;
|
|
150
|
+
}
|
|
151
|
+
}
|