@siglo/bullmq 0.0.0-stage → 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 Jerico de guzman
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,232 @@
1
- # Temporary Holding Version
1
+ # @siglo/bullmq Adapter Guide
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ `@siglo/bullmq` provides a high-throughput, Redis-backed job queue consumer and worker processor adapter for `Siglo` workflows. It bridges BullMQ workers with the Siglo execution engine, offering payload unwrapping, distributed idempotency deduplication, timeout enforcement, tenant namespace partitioning, and graceful failure handling.
4
+
5
+ ---
6
+
7
+ ## 1. Overview & Architecture
8
+
9
+ When executing distributed workflows across worker clusters, BullMQ distributes asynchronous jobs backed by Redis. The `@siglo/bullmq` adapter wraps workflow execution within a standard BullMQ worker processor function (`(job: Job) => Promise<any>`).
10
+
11
+ ```mermaid
12
+ flowchart TD
13
+ Queue["Redis Queue (BullMQ)"] -->|Job Polling| Worker["BullMQ Worker"]
14
+ Worker --> Processor["createBullMQProcessor<br/>• Extract job.id / claim<br/>• Input transformation<br/>• Namespace resolution<br/>• Timeout enforcement"]
15
+ Processor --> WF["Siglo Workflow<br/>(Flow&lt;TInput, TOutput&gt;)"]
16
+ WF -->|On Success| Success["Store Result (idempotencyStore)<br/>Return Clean Context"]
17
+ WF -->|On Failure| Failure["Clear/Fail Claim (idempotencyStore)<br/>Re-throw to Worker"]
18
+ ```
19
+
20
+ ---
21
+
22
+ ## 2. Installation & Requirements
23
+
24
+ ### Package Dependencies
25
+
26
+ Install `@siglo/bullmq` alongside `Siglo`. BullMQ and ioredis are declared as optional peer dependencies so you control the exact version:
27
+
28
+ ```bash
29
+ npm install @siglo/core @siglo/bullmq bullmq ioredis
30
+ ```
31
+
32
+ Peer dependency matrix:
33
+ - `Siglo`: `*` (v1.0.0+)
34
+ - `bullmq`: `^5.0.0`
35
+ - `ioredis`: `^5.0.0 || ^6.0.0`
36
+
37
+ ---
38
+
39
+ ## 3. API Reference
40
+
41
+ ### `createBullMQProcessor(workflow, options)`
42
+
43
+ Creates a BullMQ-compliant worker processor function:
44
+
45
+ ```typescript
46
+ function createBullMQProcessor<TInput = any, TOutput = any, TJob = any>(
47
+ workflow: Flow<TInput, TOutput>,
48
+ options?: SigloBullMQOptions<TJob, TInput, TOutput>
49
+ ): (job: any) => Promise<any>;
50
+ ```
51
+
52
+ #### Parameters:
53
+ - `workflow` (`Flow<TInput, TOutput>`): The compiled `Siglo` workflow instance to execute.
54
+ - `options` (`SigloBullMQOptions<TJob, TInput, TOutput>`): Optional configuration dictionary.
55
+
56
+ ---
57
+
58
+ ## 4. Configuration Options (`SigloBullMQOptions`)
59
+
60
+ | Option | Type | Default | Description |
61
+ | :--- | :--- | :--- | :--- |
62
+ | `input` | `(job: TJob) => Promise<TInput> \| TInput` | `(job) => job.data` | Custom mapper to transform the BullMQ `Job` into workflow inputs. |
63
+ | `output` | `(result: any, job: TJob) => Promise<TOutput> \| TOutput` | `(result) => result` | Custom mapper to format or filter the workflow result before returning to BullMQ. |
64
+ | `idempotencyStore` | `IdempotencyStore` | `undefined` | Distributed store (e.g., `RedisIdempotencyStore` or `PostgresIdempotencyStore`) to guarantee exactly-once processing. |
65
+ | `idempotencyTtlMs` | `number` | `86400000` (24h) | Time-to-live for the idempotency claim in milliseconds. |
66
+ | `timeout` | `number` | `undefined` | SLA deadline in milliseconds for workflow execution. Throws `StepTimeoutException` / `FlowTimeoutException` if exceeded. |
67
+ | `namespace` | `string \| ((job: TJob) => string \| undefined)` | `job.data?.namespace` | Target namespace for state partitioning and checkpoint isolation. |
68
+
69
+ ---
70
+
71
+ ## 5. Execution Lifecycle & Data Flow
72
+
73
+ 1. **Job Identification & Idempotency Key**:
74
+ - The adapter generates an idempotency key: `bullmq:job:${job.id || String(Date.now())}`.
75
+ - If `idempotencyStore` is provided, the key is atomically claimed:
76
+ - `'completed'`: Returns cached result immediately via `store.getResult(key)` without re-running the workflow.
77
+ - `'in-progress'`: Throws `Error('Job ... is already in-progress concurrently')`, signaling BullMQ to avoid concurrent race conditions.
78
+ - `'claimed'`: Proceeds to workflow execution.
79
+
80
+ 2. **Input Mapping**:
81
+ - If `options.input` is defined, it is invoked with `job`.
82
+ - Otherwise, `job.data || {}` is passed directly as the initial workflow input parameter.
83
+
84
+ 3. **Namespace Resolution**:
85
+ - If `options.namespace` is a function, `options.namespace(job)` is called.
86
+ - If `options.namespace` is a static string, it is used.
87
+ - Otherwise, the adapter inspects `job.data?.namespace`.
88
+
89
+ 4. **Workflow Execution & Context Unwrapping**:
90
+ - The workflow executes with `{ timeout: options.timeout, namespace }`.
91
+ - Results are automatically unwrapped (`unwrapContext`), removing internal engine properties (keys prefixed with `$`) and resolving getter accessor functions into standard JSON-serializable primitives.
92
+
93
+ 5. **Completion & Failure Handling**:
94
+ - **Success**: If an idempotency store is configured, `store.complete(idempKey, cleanResult)` is called, and `options.output` (if provided) shapes the return value.
95
+ - **Failure**: If an error is thrown, `store.fail(idempKey, err)` is called to release the in-flight lock, enabling BullMQ retry strategies. The error is re-thrown to trigger BullMQ failure handling.
96
+
97
+ ---
98
+
99
+ ## 6. Complete Production Examples
100
+
101
+ ### Basic Media Transcoder Worker
102
+
103
+ ```typescript
104
+ import { Worker, Job } from 'bullmq';
105
+ import { Step, flow } from '@siglo/core';
106
+ import { createBullMQProcessor } from '@siglo/bullmq';
107
+ import { Redis } from 'ioredis';
108
+
109
+ const connection = new Redis(process.env.REDIS_URL || 'redis://localhost:6379', {
110
+ maxRetriesPerRequest: null,
111
+ });
112
+
113
+ // 1. Define workflow steps
114
+ interface VideoJobData {
115
+ videoId: string;
116
+ sourceBucket: string;
117
+ resolutions: ('720p' | '1080p' | '4k')[];
118
+ }
119
+
120
+ const downloadSource = Step.create('downloadSource', async (param: VideoJobData) => {
121
+ console.log(`Downloading video ${param.videoId} from ${param.sourceBucket}`);
122
+ return { localPath: `/tmp/${param.videoId}.mp4` };
123
+ });
124
+
125
+ const transcode = Step.create('transcode', async (param: any) => {
126
+ console.log(`Transcoding ${param.localPath} into ${param.resolutions.join(', ')}`);
127
+ return {
128
+ transcodedFiles: param.resolutions.map((r: string) => `/tmp/${param.videoId}_${r}.mp4`),
129
+ durationSec: 124,
130
+ };
131
+ });
132
+
133
+ const uploadCdn = Step.create('uploadCdn', async (param: any) => {
134
+ console.log(`Uploading ${param.transcodedFiles.length} files to CDN`);
135
+ return {
136
+ cdnUrls: param.transcodedFiles.map((f: string) => `https://cdn.example.com/${param.videoId}`),
137
+ status: 'READY',
138
+ };
139
+ });
140
+
141
+ const transcodeFlow = flow(downloadSource, transcode, uploadCdn);
142
+
143
+ // 2. Create BullMQ worker with processor adapter
144
+ const worker = new Worker<VideoJobData>(
145
+ 'video-processing-queue',
146
+ createBullMQProcessor(transcodeFlow, {
147
+ timeout: 120000, // 2-minute deadline
148
+ input: (job: Job<VideoJobData>) => ({
149
+ videoId: job.data.videoId,
150
+ sourceBucket: job.data.sourceBucket,
151
+ resolutions: job.data.resolutions,
152
+ }),
153
+ output: (result, job) => ({
154
+ jobId: job.id,
155
+ videoId: job.data.videoId,
156
+ cdnUrls: result.cdnUrls,
157
+ durationSec: result.durationSec,
158
+ }),
159
+ }),
160
+ { connection, concurrency: 5 }
161
+ );
162
+
163
+ worker.on('completed', (job, returnvalue) => {
164
+ console.log(`Job ${job.id} completed. Transcoded video ready:`, returnvalue.cdnUrls);
165
+ });
166
+
167
+ worker.on('failed', (job, err) => {
168
+ console.error(`Job ${job?.id} failed: ${err.message}`);
169
+ });
170
+ ```
171
+
172
+ ---
173
+
174
+ ### Distributed Idempotent Worker with `@siglo/redis`
175
+
176
+ In high-concurrency environments with Redis clusters, duplicate job events or worker restarts should never cause duplicate processing:
177
+
178
+ ```typescript
179
+ import { Worker } from 'bullmq';
180
+ import { Step, flow } from '@siglo/core';
181
+ import { createBullMQProcessor } from '@siglo/bullmq';
182
+ import { RedisIdempotencyStore, RedisStorageAdapter } from '@siglo/redis';
183
+ import { Redis } from 'ioredis';
184
+
185
+ const redis = new Redis('redis://localhost:6379');
186
+
187
+ // Configure global storage for checkpoints
188
+ Step.useStorage(new RedisStorageAdapter({ client: redis }));
189
+
190
+ // Configure distributed idempotency store
191
+ const idempotencyStore = new RedisIdempotencyStore({
192
+ client: redis,
193
+ keyPrefix: 'siglo:idemp:bullmq:',
194
+ defaultTtlMs: 3600000, // 1 hour
195
+ });
196
+
197
+ const billingWorkflow = flow(
198
+ Step.create('chargeInvoice', async ({ invoiceId, amount }: any) => {
199
+ // Charging payment gateway
200
+ return { chargeId: `ch_${invoiceId}`, settled: true };
201
+ })
202
+ );
203
+
204
+ const worker = new Worker(
205
+ 'billing-queue',
206
+ createBullMQProcessor(billingWorkflow, {
207
+ idempotencyStore,
208
+ idempotencyTtlMs: 3600000,
209
+ timeout: 10000,
210
+ namespace: (job) => job.data.tenantId, // Multi-tenant namespace
211
+ }),
212
+ { connection: redis, concurrency: 10 }
213
+ );
214
+ ```
215
+
216
+ ---
217
+
218
+ ## 7. Graceful Shutdown & Connection Draining
219
+
220
+ Ensure that ongoing workflow executions finish gracefully when the host process terminates (e.g., during Kubernetes pod evictions):
221
+
222
+ ```typescript
223
+ async function shutdown() {
224
+ console.log('Shutting down BullMQ worker...');
225
+ await worker.close();
226
+ await redis.quit();
227
+ process.exit(0);
228
+ }
229
+
230
+ process.on('SIGTERM', shutdown);
231
+ process.on('SIGINT', shutdown);
232
+ ```
@@ -0,0 +1,15 @@
1
+ import { Flow, IdempotencyStore } from '@siglo/core';
2
+ export interface SigloBullMQOptions<TJob = any, TInput = any, TOutput = any> {
3
+ input?: (job: TJob) => Promise<TInput> | TInput;
4
+ output?: (result: any, job: TJob) => Promise<TOutput> | TOutput;
5
+ idempotencyStore?: IdempotencyStore;
6
+ idempotencyTtlMs?: number;
7
+ timeout?: number;
8
+ namespace?: string | ((job: TJob) => string | undefined);
9
+ }
10
+ /**
11
+ * Creates a BullMQ worker processor function that runs a siglo workflow.
12
+ */
13
+ export declare function createBullMQProcessor<TInput = any, TOutput = any, TJob = any>(workflow: Flow<TInput, TOutput>, options?: SigloBullMQOptions<TJob, TInput, TOutput>): (job: any) => Promise<any>;
14
+ export type RivuletBullMQOptions<TJob = any, TInput = any, TOutput = any> = SigloBullMQOptions<TJob, TInput, TOutput>;
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAoB,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEvE,MAAM,WAAW,kBAAkB,CAAC,IAAI,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,EAAE,OAAO,GAAG,GAAG;IACvE,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC;IAChD,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IAChE,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,KAAK,MAAM,GAAG,SAAS,CAAC,CAAC;CAC5D;AAiBD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,GAAG,GAAG,EAAE,OAAO,GAAG,GAAG,EAAE,IAAI,GAAG,GAAG,EACzE,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,OAAO,GAAE,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAM,SAEpC,GAAG,KAAG,OAAO,CAAC,GAAG,CAAC,CAmDxC;AAGD,MAAM,MAAM,oBAAoB,CAAC,IAAI,GAAG,GAAG,EAAE,MAAM,GAAG,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createBullMQProcessor = createBullMQProcessor;
4
+ function unwrapContext(obj) {
5
+ if (!obj || typeof obj !== 'object') {
6
+ return obj;
7
+ }
8
+ const clean = {};
9
+ for (const key of Object.keys(obj)) {
10
+ if (key.startsWith('$')) {
11
+ continue;
12
+ }
13
+ const val = typeof obj[key] === 'function' ? (obj[key].val !== undefined ? obj[key].val : (obj[key].length === 0 ? obj[key]() : obj[key])) : obj[key];
14
+ clean[key] = val;
15
+ }
16
+ return clean;
17
+ }
18
+ /**
19
+ * Creates a BullMQ worker processor function that runs a siglo workflow.
20
+ */
21
+ function createBullMQProcessor(workflow, options = {}) {
22
+ return async (job) => {
23
+ const jobId = job.id || String(Date.now());
24
+ const idempKey = `bullmq:job:${jobId}`;
25
+ // Idempotency check if store is provided
26
+ if (options.idempotencyStore) {
27
+ const status = await options.idempotencyStore.claim(idempKey, options.idempotencyTtlMs);
28
+ if (status === 'completed') {
29
+ return options.idempotencyStore.getResult?.(idempKey) ?? { alreadyProcessed: true };
30
+ }
31
+ if (status === 'in-progress') {
32
+ throw new Error(`Job ${jobId} is already in-progress concurrently`);
33
+ }
34
+ }
35
+ try {
36
+ const inputData = options.input ? await options.input(job) : (job.data || {});
37
+ let namespace;
38
+ if (typeof options.namespace === 'function') {
39
+ namespace = options.namespace(job);
40
+ }
41
+ else if (options.namespace) {
42
+ namespace = options.namespace;
43
+ }
44
+ else if (job.data?.namespace) {
45
+ namespace = job.data.namespace;
46
+ }
47
+ const execOptions = {
48
+ timeout: options.timeout,
49
+ namespace,
50
+ };
51
+ const rawResult = await workflow.run(inputData, execOptions);
52
+ const cleanResult = unwrapContext(rawResult);
53
+ if (options.idempotencyStore) {
54
+ await options.idempotencyStore.complete(idempKey, cleanResult);
55
+ }
56
+ if (options.output) {
57
+ return await options.output(cleanResult, job);
58
+ }
59
+ return cleanResult;
60
+ }
61
+ catch (err) {
62
+ if (options.idempotencyStore) {
63
+ await options.idempotencyStore.fail(idempKey, err);
64
+ }
65
+ throw err;
66
+ }
67
+ };
68
+ }
69
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,61 @@
1
1
  {
2
2
  "name": "@siglo/bullmq",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.0.0",
4
+ "description": "BullMQ job queue consumer and worker adapter for Siglo workflows",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js",
11
+ "require": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "./package.json": "./package.json"
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "README.md",
19
+ "LICENSE"
20
+ ],
21
+ "publishConfig": {
22
+ "access": "public",
23
+ "registry": "https://registry.npmjs.org/"
24
+ },
25
+ "scripts": {
26
+ "build": "tsc -p tsconfig.json",
27
+ "prepublishOnly": "npm run build",
28
+ "test": "npm run build && mocha -r tsx 'src/**/*.test.ts'"
29
+ },
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/jsoftgem/siglo.git",
33
+ "directory": "packages/bullmq"
34
+ },
35
+ "author": "Jerico de Guzman",
36
+ "license": "MIT",
37
+ "bugs": {
38
+ "url": "https://github.com/jsoftgem/siglo/issues"
39
+ },
40
+ "homepage": "https://github.com/jsoftgem/siglo#readme",
41
+ "dependencies": {
42
+ "@siglo/core": "^1.0.0"
43
+ },
44
+ "peerDependencies": {
45
+ "bullmq": "^5.0.0"
46
+ },
47
+ "peerDependenciesMeta": {
48
+ "bullmq": {
49
+ "optional": true
50
+ }
51
+ },
52
+ "devDependencies": {
53
+ "@types/chai": "^5.2.3",
54
+ "@types/mocha": "^10.0.10",
55
+ "@types/node": "^26.6.5",
56
+ "chai": "^3.5.0",
57
+ "mocha": "^12.0.3",
58
+ "tsx": "^4.23.15",
59
+ "typescript": "~5.7.0"
60
+ }
61
+ }