@igniter-js/jobs 0.1.13 → 0.1.14
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/AGENTS.md +117 -243
- package/README.md +311 -153
- package/dist/{adapter-CXZxomI9.d.mts → adapter-Cax_40HW.d.mts} +27 -6
- package/dist/{adapter-CXZxomI9.d.ts → adapter-Cax_40HW.d.ts} +27 -6
- package/dist/adapters/bun.d.mts +93 -0
- package/dist/adapters/bun.d.ts +93 -0
- package/dist/adapters/bun.js +914 -0
- package/dist/adapters/bun.js.map +1 -0
- package/dist/adapters/bun.mjs +912 -0
- package/dist/adapters/bun.mjs.map +1 -0
- package/dist/adapters/{memory.adapter.d.ts → mock.d.mts} +1 -3
- package/dist/adapters/{memory.adapter.d.mts → mock.d.ts} +1 -3
- package/dist/adapters/{memory.adapter.js → mock.js} +58 -25
- package/dist/adapters/mock.js.map +1 -0
- package/dist/adapters/{memory.adapter.mjs → mock.mjs} +58 -25
- package/dist/adapters/mock.mjs.map +1 -0
- package/dist/adapters/{bullmq.adapter.d.ts → node.d.mts} +1 -3
- package/dist/adapters/{bullmq.adapter.d.mts → node.d.ts} +1 -3
- package/dist/adapters/{bullmq.adapter.js → node.js} +117 -40
- package/dist/adapters/node.js.map +1 -0
- package/dist/adapters/{bullmq.adapter.mjs → node.mjs} +117 -40
- package/dist/adapters/node.mjs.map +1 -0
- package/dist/index.d.mts +17 -21
- package/dist/index.d.ts +17 -21
- package/dist/index.js +20 -1854
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +21 -1852
- package/dist/index.mjs.map +1 -1
- package/package.json +28 -40
- package/CHANGELOG.md +0 -13
- package/dist/adapters/bullmq.adapter.js.map +0 -1
- package/dist/adapters/bullmq.adapter.mjs.map +0 -1
- package/dist/adapters/index.d.mts +0 -143
- package/dist/adapters/index.d.ts +0 -143
- package/dist/adapters/index.js +0 -1891
- package/dist/adapters/index.js.map +0 -1
- package/dist/adapters/index.mjs +0 -1887
- package/dist/adapters/index.mjs.map +0 -1
- package/dist/adapters/memory.adapter.js.map +0 -1
- package/dist/adapters/memory.adapter.mjs.map +0 -1
package/AGENTS.md
CHANGED
|
@@ -45,7 +45,7 @@ Maintainers must respect the following directory structure and responsibilities:
|
|
|
45
45
|
- `queue.ts`: `IgniterQueue` facade for the queue builder.
|
|
46
46
|
- **`src/adapters/`**: The infrastructure boundary.
|
|
47
47
|
- `memory.adapter.ts`: Production-grade in-memory implementation for tests (non-persistent).
|
|
48
|
-
- `sqlite.adapter.ts`:
|
|
48
|
+
- `bun-sqlite.adapter.ts`: Bun-native SQLite adapter for local, desktop, CLI, and embedded workloads.
|
|
49
49
|
- `bullmq.adapter.ts`: Reference to external `@igniter-js/adapter-bullmq` for production Redis-based queues.
|
|
50
50
|
- **`src/errors/`**: Resiliency definitions.
|
|
51
51
|
- `jobs.error.ts`: `IgniterJobsError`. Extends `IgniterError` with metadata-rich payloads and authoritative error codes.
|
|
@@ -157,7 +157,9 @@ Type Flow:
|
|
|
157
157
|
The package provides organized subpath exports for optimized bundling:
|
|
158
158
|
|
|
159
159
|
- **`@igniter-js/jobs`**: The main entry point. Use for `IgniterJobs` and `IgniterQueue`.
|
|
160
|
-
- **`@igniter-js/jobs/adapters`**:
|
|
160
|
+
- **`@igniter-js/jobs/adapters/node`**: Node.js adapters (`BullMQ` wrapper).
|
|
161
|
+
- **`@igniter-js/jobs/adapters/bun`**: Bun-native SQLite adapter.
|
|
162
|
+
- **`@igniter-js/jobs/adapters/mock`**: In-memory adapter for tests and local mocks.
|
|
161
163
|
- **`@igniter-js/jobs/telemetry`**: Telemetry registry for registration.
|
|
162
164
|
|
|
163
165
|
### 9. Quick Start & Common Patterns
|
|
@@ -168,7 +170,7 @@ Setup your jobs in a central `src/services/jobs.ts` file:
|
|
|
168
170
|
|
|
169
171
|
```typescript
|
|
170
172
|
import { IgniterJobs } from "@igniter-js/jobs";
|
|
171
|
-
import { IgniterJobsBullMQAdapter } from "@igniter-js/jobs/adapters";
|
|
173
|
+
import { IgniterJobsBullMQAdapter } from "@igniter-js/jobs/adapters/node";
|
|
172
174
|
|
|
173
175
|
export const jobs = IgniterJobs.create()
|
|
174
176
|
.withAdapter(IgniterJobsBullMQAdapter.create({ redis }))
|
|
@@ -216,7 +218,7 @@ Prevent permanent failures in external API calls:
|
|
|
216
218
|
#### Case 5: SaaS Multi-Tenant CSV Import
|
|
217
219
|
|
|
218
220
|
- **Scenario:** Process 100k row CSV.
|
|
219
|
-
- **Implementation:** `job.
|
|
221
|
+
- **Implementation:** `job.updateProgress?.(percent)` every 100 rows for real-time progress bar.
|
|
220
222
|
|
|
221
223
|
### 11. Domain-Specific Guidance
|
|
222
224
|
|
|
@@ -457,17 +459,17 @@ All adapters implement the `IgniterJobsAdapter` interface defined in `src/types/
|
|
|
457
459
|
|
|
458
460
|
### 17. Adapter Comparison Matrix
|
|
459
461
|
|
|
460
|
-
| Feature
|
|
461
|
-
|
|
462
|
-
| **Persistence**
|
|
463
|
-
| **Multi-process**
|
|
464
|
-
| **Installation**
|
|
465
|
-
| **Use Case**
|
|
466
|
-
| **Job Limits**
|
|
467
|
-
| **Worker Mechanism**
|
|
468
|
-
| **Cron Jobs**
|
|
469
|
-
| **Distributed Locking** | ❌
|
|
470
|
-
| **Rate Limiting**
|
|
462
|
+
| Feature | Memory | Bun SQLite | BullMQ |
|
|
463
|
+
| ----------------------- | ----------------- | ------------------------ | ----------------- |
|
|
464
|
+
| **Persistence** | ❌ In-memory only | ✅ File-based | ✅ Redis |
|
|
465
|
+
| **Multi-process** | ❌ Single process | ⚠️ Single process/local | ✅ Distributed |
|
|
466
|
+
| **Installation** | Built-in | Bundled with package | `bullmq` + Redis |
|
|
467
|
+
| **Use Case** | Tests, demos | Desktop, CLI, local apps | Production, scale |
|
|
468
|
+
| **Job Limits** | Memory-bound | Disk-bound | Redis-bound |
|
|
469
|
+
| **Worker Mechanism** | Immediate | Embedded worker runtime | Event-driven |
|
|
470
|
+
| **Cron Jobs** | ⚠️ Basic | ✅ Supported | ✅ Supported |
|
|
471
|
+
| **Distributed Locking** | ❌ | ❌ | ✅ |
|
|
472
|
+
| **Rate Limiting** | ⚠️ Basic | ✅ Supported | ✅ Advanced |
|
|
471
473
|
|
|
472
474
|
---
|
|
473
475
|
|
|
@@ -490,7 +492,7 @@ No additional dependencies required. The adapter is built into `@igniter-js/jobs
|
|
|
490
492
|
|
|
491
493
|
```typescript
|
|
492
494
|
import { IgniterJobs } from "@igniter-js/jobs";
|
|
493
|
-
import { IgniterJobsMemoryAdapter } from "@igniter-js/jobs/adapters";
|
|
495
|
+
import { IgniterJobsMemoryAdapter } from "@igniter-js/jobs/adapters/mock";
|
|
494
496
|
|
|
495
497
|
const adapter = IgniterJobsMemoryAdapter.create();
|
|
496
498
|
|
|
@@ -553,47 +555,36 @@ await worker.close();
|
|
|
553
555
|
|
|
554
556
|
---
|
|
555
557
|
|
|
556
|
-
### 19. SQLite Adapter (Desktop, CLI,
|
|
558
|
+
### 19. Bun SQLite Adapter (Desktop, CLI, Local Apps)
|
|
557
559
|
|
|
558
|
-
The `
|
|
560
|
+
The `IgniterJobsBunSQLiteAdapter` is the local persistent adapter for Bun runtimes. It is the recommended choice for desktop applications, embedded tools, local orchestrators, and Bun services that want SQLite-backed jobs without Redis.
|
|
559
561
|
|
|
560
562
|
#### 19.1 When to Use
|
|
561
563
|
|
|
562
|
-
- **Desktop Applications:** Tauri
|
|
563
|
-
- **CLI Tools:** Long-running commands with progress tracking.
|
|
564
|
-
- **
|
|
565
|
-
- **
|
|
566
|
-
- **Local Development:** When you want jobs to survive restarts.
|
|
564
|
+
- **Desktop Applications:** Tauri or Electron apps with a Bun sidecar/runtime.
|
|
565
|
+
- **CLI Tools:** Long-running commands with progress tracking and durable jobs.
|
|
566
|
+
- **Local Services:** Single-node Bun services that need persistence and recurring jobs.
|
|
567
|
+
- **Embedded Workloads:** Sidecar workers, local automation, and job-heavy scripts.
|
|
567
568
|
|
|
568
569
|
#### 19.2 Installation
|
|
569
570
|
|
|
570
|
-
|
|
571
|
-
npm install better-sqlite3
|
|
572
|
-
# or
|
|
573
|
-
bun add better-sqlite3
|
|
574
|
-
```
|
|
575
|
-
|
|
576
|
-
The `better-sqlite3` package is an optional peer dependency.
|
|
571
|
+
No extra adapter package is required. Install `@igniter-js/jobs`, run the app in Bun, and import the adapter from `@igniter-js/jobs/adapters/bun`.
|
|
577
572
|
|
|
578
573
|
#### 19.3 Basic Usage
|
|
579
574
|
|
|
580
575
|
```typescript
|
|
581
576
|
import { IgniterJobs } from "@igniter-js/jobs";
|
|
582
|
-
import {
|
|
577
|
+
import { IgniterJobsBunSQLiteAdapter } from "@igniter-js/jobs/adapters/bun";
|
|
583
578
|
|
|
584
|
-
|
|
585
|
-
const adapter = IgniterJobsSQLiteAdapter.create({
|
|
579
|
+
const adapter = IgniterJobsBunSQLiteAdapter.create({
|
|
586
580
|
path: "./jobs.sqlite",
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
// In-memory (for tests)
|
|
590
|
-
const memoryAdapter = IgniterJobsSQLiteAdapter.create({
|
|
591
|
-
path: ":memory:",
|
|
581
|
+
durable: true,
|
|
592
582
|
});
|
|
593
583
|
|
|
594
584
|
const jobs = IgniterJobs.create()
|
|
595
585
|
.withAdapter(adapter)
|
|
596
586
|
.withService("desktop-app")
|
|
587
|
+
.withEnvironment("production")
|
|
597
588
|
.withContext(async () => ({ settings: loadSettings() }))
|
|
598
589
|
.addQueue(syncQueue)
|
|
599
590
|
.build();
|
|
@@ -602,144 +593,52 @@ const jobs = IgniterJobs.create()
|
|
|
602
593
|
#### 19.4 Configuration Options
|
|
603
594
|
|
|
604
595
|
```typescript
|
|
605
|
-
interface
|
|
606
|
-
/**
|
|
607
|
-
* Path to the SQLite database file.
|
|
608
|
-
* Use ":memory:" for in-memory database.
|
|
609
|
-
* @example "./data/jobs.sqlite"
|
|
610
|
-
*/
|
|
596
|
+
interface IgniterJobsBunSQLiteAdapterOptions {
|
|
611
597
|
path: string;
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
pollingInterval?: number;
|
|
619
|
-
|
|
620
|
-
/**
|
|
621
|
-
* Enable WAL (Write-Ahead Logging) mode for better concurrent performance.
|
|
622
|
-
* Recommended for production use.
|
|
623
|
-
* @default true
|
|
624
|
-
*/
|
|
625
|
-
enableWAL?: boolean;
|
|
598
|
+
durable?: boolean;
|
|
599
|
+
heartbeatInterval?: number;
|
|
600
|
+
pollTimeout?: number;
|
|
601
|
+
batchSize?: number;
|
|
602
|
+
lockDuration?: number;
|
|
603
|
+
maxStalledCount?: number;
|
|
626
604
|
}
|
|
627
605
|
```
|
|
628
606
|
|
|
629
|
-
#### 19.5
|
|
630
|
-
|
|
631
|
-
The adapter automatically creates and manages the following tables:
|
|
632
|
-
|
|
633
|
-
```sql
|
|
634
|
-
-- Main jobs table
|
|
635
|
-
CREATE TABLE IF NOT EXISTS jobs (
|
|
636
|
-
id TEXT PRIMARY KEY,
|
|
637
|
-
queue TEXT NOT NULL,
|
|
638
|
-
name TEXT NOT NULL,
|
|
639
|
-
input TEXT, -- JSON serialized
|
|
640
|
-
result TEXT, -- JSON serialized
|
|
641
|
-
error TEXT,
|
|
642
|
-
status TEXT NOT NULL DEFAULT 'waiting',
|
|
643
|
-
progress INTEGER DEFAULT 0,
|
|
644
|
-
priority INTEGER DEFAULT 0,
|
|
645
|
-
attempts_made INTEGER DEFAULT 0,
|
|
646
|
-
max_attempts INTEGER DEFAULT 1,
|
|
647
|
-
delay_until INTEGER, -- Unix timestamp
|
|
648
|
-
metadata TEXT, -- JSON serialized
|
|
649
|
-
scope_type TEXT,
|
|
650
|
-
scope_id TEXT,
|
|
651
|
-
created_at INTEGER NOT NULL,
|
|
652
|
-
started_at INTEGER,
|
|
653
|
-
completed_at INTEGER
|
|
654
|
-
);
|
|
655
|
-
|
|
656
|
-
-- Indexes for efficient queries
|
|
657
|
-
CREATE INDEX IF NOT EXISTS idx_jobs_queue_status ON jobs(queue, status);
|
|
658
|
-
CREATE INDEX IF NOT EXISTS idx_jobs_status ON jobs(status);
|
|
659
|
-
CREATE INDEX IF NOT EXISTS idx_jobs_priority ON jobs(priority DESC);
|
|
660
|
-
CREATE INDEX IF NOT EXISTS idx_jobs_delay ON jobs(delay_until);
|
|
661
|
-
|
|
662
|
-
-- Job logs table
|
|
663
|
-
CREATE TABLE IF NOT EXISTS job_logs (
|
|
664
|
-
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
665
|
-
job_id TEXT NOT NULL,
|
|
666
|
-
level TEXT NOT NULL,
|
|
667
|
-
message TEXT NOT NULL,
|
|
668
|
-
timestamp INTEGER NOT NULL,
|
|
669
|
-
FOREIGN KEY (job_id) REFERENCES jobs(id) ON DELETE CASCADE
|
|
670
|
-
);
|
|
671
|
-
|
|
672
|
-
-- Paused queues tracking
|
|
673
|
-
CREATE TABLE IF NOT EXISTS paused_queues (
|
|
674
|
-
name TEXT PRIMARY KEY,
|
|
675
|
-
paused_at INTEGER NOT NULL
|
|
676
|
-
);
|
|
677
|
-
```
|
|
607
|
+
#### 19.5 Runtime Characteristics
|
|
678
608
|
|
|
679
|
-
|
|
609
|
+
- Uses an embedded SQLite-backed runtime under Bun.
|
|
610
|
+
- Persists jobs to a local file path.
|
|
611
|
+
- Supports immediate dispatch, `at`, `delay`, `cron`, and `every` scheduling.
|
|
612
|
+
- Provides progress updates, logs, worker lifecycle events, and queue inspection APIs.
|
|
613
|
+
- Designed for local and embedded topologies, not distributed Redis-style clusters.
|
|
680
614
|
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
```
|
|
684
|
-
┌─────────────────────────────────────────────────────────────────┐
|
|
685
|
-
│ Worker Polling Loop │
|
|
686
|
-
├─────────────────────────────────────────────────────────────────┤
|
|
687
|
-
│ │
|
|
688
|
-
│ ┌─────────┐ ┌─────────────┐ ┌─────────────┐ │
|
|
689
|
-
│ │ Wait │────▶│ Check Jobs │────▶│ Process Job │ │
|
|
690
|
-
│ │ Polling │ │ Available? │ │ (if any) │ │
|
|
691
|
-
│ │ Interval│ └─────────────┘ └─────────────┘ │
|
|
692
|
-
│ └─────────┘ │ │ │
|
|
693
|
-
│ ▲ │ No jobs │ Done │
|
|
694
|
-
│ │ │ ▼ │
|
|
695
|
-
│ └────────────────┴───────────────────┘ │
|
|
696
|
-
│ │
|
|
697
|
-
│ Query Priority: │
|
|
698
|
-
│ 1. Delayed jobs ready to run (delay_until <= NOW) │
|
|
699
|
-
│ 2. Waiting jobs, ordered by priority DESC │
|
|
700
|
-
│ 3. Retry jobs (failed but attempts < max_attempts) │
|
|
701
|
-
│ │
|
|
702
|
-
└─────────────────────────────────────────────────────────────────┘
|
|
703
|
-
```
|
|
704
|
-
|
|
705
|
-
#### 19.7 Complete Example
|
|
615
|
+
#### 19.6 Complete Example
|
|
706
616
|
|
|
707
617
|
```typescript
|
|
708
|
-
import {
|
|
618
|
+
import { IgniterJobsBunSQLiteAdapter } from "@igniter-js/jobs/adapters/bun";
|
|
709
619
|
|
|
710
620
|
async function main() {
|
|
711
|
-
|
|
712
|
-
const adapter = IgniterJobsSQLiteAdapter.create({
|
|
621
|
+
const adapter = IgniterJobsBunSQLiteAdapter.create({
|
|
713
622
|
path: "./my-app-jobs.sqlite",
|
|
714
|
-
|
|
715
|
-
|
|
623
|
+
durable: true,
|
|
624
|
+
batchSize: 25,
|
|
716
625
|
});
|
|
717
626
|
|
|
718
|
-
// 2. Register jobs
|
|
719
627
|
adapter.registerJob("sync", "upload", {
|
|
720
|
-
handler: async ({ input }) => {
|
|
628
|
+
handler: async ({ input, job }) => {
|
|
721
629
|
const { fileId } = input as { fileId: string };
|
|
722
|
-
|
|
630
|
+
await job.updateProgress?.(25, "Uploading metadata");
|
|
723
631
|
await uploadFile(fileId);
|
|
632
|
+
await job.updateProgress?.(100, "Upload completed");
|
|
724
633
|
return { uploaded: true };
|
|
725
634
|
},
|
|
726
|
-
onProgress: async ({ progress }) => {
|
|
727
|
-
console.log(`Upload progress: ${progress}%`);
|
|
728
|
-
},
|
|
729
635
|
});
|
|
730
636
|
|
|
731
|
-
// 3. Create worker
|
|
732
637
|
const worker = await adapter.createWorker({
|
|
733
638
|
queues: ["sync"],
|
|
734
639
|
concurrency: 2,
|
|
735
|
-
handlers: {
|
|
736
|
-
onActive: ({ job }) => console.log(`Processing: ${job.id}`),
|
|
737
|
-
onSuccess: ({ job }) => console.log(`Completed: ${job.id}`),
|
|
738
|
-
onFailure: ({ job, error }) => console.error(`Failed: ${job.id}`, error),
|
|
739
|
-
},
|
|
740
640
|
});
|
|
741
641
|
|
|
742
|
-
// 4. Dispatch jobs
|
|
743
642
|
const jobId = await adapter.dispatch({
|
|
744
643
|
queue: "sync",
|
|
745
644
|
jobName: "upload",
|
|
@@ -747,50 +646,26 @@ async function main() {
|
|
|
747
646
|
priority: 10,
|
|
748
647
|
});
|
|
749
648
|
|
|
750
|
-
console.log(
|
|
751
|
-
|
|
752
|
-
// 5. Monitor status
|
|
753
|
-
const counts = await adapter.getQueueJobCounts("sync");
|
|
754
|
-
console.log(`Queue status:`, counts);
|
|
649
|
+
console.log(jobId);
|
|
755
650
|
|
|
756
|
-
// 6. Graceful shutdown
|
|
757
651
|
process.on("SIGINT", async () => {
|
|
758
652
|
await worker.close();
|
|
759
653
|
await adapter.shutdown();
|
|
760
|
-
process.exit(0);
|
|
761
654
|
});
|
|
762
655
|
}
|
|
763
|
-
|
|
764
|
-
main().catch(console.error);
|
|
765
656
|
```
|
|
766
657
|
|
|
767
|
-
#### 19.
|
|
658
|
+
#### 19.7 Persistence & Recovery
|
|
768
659
|
|
|
769
|
-
Jobs
|
|
660
|
+
- Jobs remain on disk across process restarts.
|
|
661
|
+
- Delayed and recurring work is persisted in the local SQLite backend.
|
|
662
|
+
- Worker shutdown should always call `adapter.shutdown()` during graceful exits.
|
|
770
663
|
|
|
771
|
-
|
|
772
|
-
// Session 1: Dispatch job and exit
|
|
773
|
-
const adapter = IgniterJobsSQLiteAdapter.create({ path: "./jobs.sqlite" });
|
|
774
|
-
await adapter.dispatch({
|
|
775
|
-
queue: "emails",
|
|
776
|
-
jobName: "send",
|
|
777
|
-
input: { to: "user@example.com" },
|
|
778
|
-
});
|
|
779
|
-
await adapter.shutdown();
|
|
780
|
-
// Process exits
|
|
781
|
-
|
|
782
|
-
// Session 2: Jobs are still there
|
|
783
|
-
const adapter2 = IgniterJobsSQLiteAdapter.create({ path: "./jobs.sqlite" });
|
|
784
|
-
const jobs = await adapter2.searchJobs({ queue: "emails", status: ["waiting"] });
|
|
785
|
-
console.log(jobs); // Shows the pending job from session 1
|
|
786
|
-
```
|
|
787
|
-
|
|
788
|
-
#### 19.9 Limitations
|
|
664
|
+
#### 19.8 Limitations
|
|
789
665
|
|
|
790
|
-
- **
|
|
791
|
-
- **
|
|
792
|
-
- **
|
|
793
|
-
- **Limited Cron:** Basic cron support without advanced scheduling features.
|
|
666
|
+
- **Local Topology:** The adapter is intended for Bun-local deployments and desktop-class runtimes.
|
|
667
|
+
- **No Redis-style Distribution:** Use BullMQ when you need multi-node horizontal workers.
|
|
668
|
+
- **Runtime Requirement:** This adapter runs only under Bun.
|
|
794
669
|
|
|
795
670
|
---
|
|
796
671
|
|
|
@@ -863,8 +738,9 @@ See `src/types/adapter.ts` for the complete interface definition.
|
|
|
863
738
|
#### 21.2 Testing Custom Adapters
|
|
864
739
|
|
|
865
740
|
Use the existing test suites as a reference:
|
|
741
|
+
|
|
866
742
|
- `src/adapters/memory.adapter.spec.ts`
|
|
867
|
-
- `src/
|
|
743
|
+
- `src/core/telemetry.spec.ts`
|
|
868
744
|
|
|
869
745
|
---
|
|
870
746
|
|
|
@@ -877,18 +753,19 @@ The `examples/` directory contains runnable examples:
|
|
|
877
753
|
```
|
|
878
754
|
packages/jobs/examples/
|
|
879
755
|
├── README.md # Example documentation
|
|
880
|
-
└── sqlite-example.ts
|
|
756
|
+
└── bun-sqlite-example.ts # Complete Bun SQLite adapter demo
|
|
881
757
|
```
|
|
882
758
|
|
|
883
|
-
### 23. Running the SQLite Example
|
|
759
|
+
### 23. Running the Bun SQLite Example
|
|
884
760
|
|
|
885
761
|
```bash
|
|
886
762
|
cd packages/jobs
|
|
887
|
-
|
|
763
|
+
bun run examples/bun-sqlite-example.ts
|
|
888
764
|
```
|
|
889
765
|
|
|
890
766
|
This example demonstrates:
|
|
891
|
-
|
|
767
|
+
|
|
768
|
+
- Creating a Bun SQLite adapter with file persistence
|
|
892
769
|
- Registering multiple job types
|
|
893
770
|
- Priority-based job processing
|
|
894
771
|
- Delayed job scheduling
|
|
@@ -900,32 +777,32 @@ This example demonstrates:
|
|
|
900
777
|
|
|
901
778
|
## VI. MIGRATION GUIDE
|
|
902
779
|
|
|
903
|
-
### 24. Migrating from Memory to SQLite
|
|
780
|
+
### 24. Migrating from Memory to Bun SQLite
|
|
904
781
|
|
|
905
782
|
For development to production-like local testing:
|
|
906
783
|
|
|
907
784
|
```typescript
|
|
908
785
|
// Before: Memory adapter
|
|
909
|
-
import { IgniterJobsMemoryAdapter } from "@igniter-js/jobs/adapters";
|
|
786
|
+
import { IgniterJobsMemoryAdapter } from "@igniter-js/jobs/adapters/mock";
|
|
910
787
|
const adapter = IgniterJobsMemoryAdapter.create();
|
|
911
788
|
|
|
912
|
-
// After: SQLite adapter
|
|
913
|
-
import {
|
|
914
|
-
const adapter =
|
|
789
|
+
// After: Bun SQLite adapter
|
|
790
|
+
import { IgniterJobsBunSQLiteAdapter } from "@igniter-js/jobs/adapters/bun";
|
|
791
|
+
const adapter = IgniterJobsBunSQLiteAdapter.create({
|
|
915
792
|
path: "./dev-jobs.sqlite",
|
|
916
793
|
});
|
|
917
794
|
|
|
918
795
|
// Rest of the code remains identical!
|
|
919
796
|
```
|
|
920
797
|
|
|
921
|
-
### 25. Migrating from SQLite to BullMQ
|
|
798
|
+
### 25. Migrating from Bun SQLite to BullMQ
|
|
922
799
|
|
|
923
800
|
For local development to production:
|
|
924
801
|
|
|
925
802
|
```typescript
|
|
926
|
-
// Before: SQLite adapter
|
|
927
|
-
import {
|
|
928
|
-
const adapter =
|
|
803
|
+
// Before: Bun SQLite adapter
|
|
804
|
+
import { IgniterJobsBunSQLiteAdapter } from "@igniter-js/jobs/adapters/bun";
|
|
805
|
+
const adapter = IgniterJobsBunSQLiteAdapter.create({
|
|
929
806
|
path: "./jobs.sqlite",
|
|
930
807
|
});
|
|
931
808
|
|
|
@@ -944,11 +821,9 @@ const adapter = IgniterJobsBullMQAdapter.create({
|
|
|
944
821
|
|
|
945
822
|
### Version 0.2.0 (2026-01-17)
|
|
946
823
|
|
|
947
|
-
- **Added:** `
|
|
948
|
-
- **Added:** SQLite adapter comprehensive test suite (71 tests)
|
|
824
|
+
- **Added:** `IgniterJobsBunSQLiteAdapter` for persistent local Bun job queues
|
|
949
825
|
- **Added:** `examples/` directory with runnable examples
|
|
950
|
-
- **
|
|
951
|
-
- **Updated:** Adapter exports to include SQLite adapter
|
|
826
|
+
- **Updated:** Adapter exports to include Bun SQLite adapter
|
|
952
827
|
- **Updated:** AGENTS.md with comprehensive adapter documentation
|
|
953
828
|
|
|
954
829
|
### Version 0.1.2 (2025-12-23)
|
|
@@ -965,16 +840,16 @@ const adapter = IgniterJobsBullMQAdapter.create({
|
|
|
965
840
|
|
|
966
841
|
#### Q: Which adapter should I choose?
|
|
967
842
|
|
|
968
|
-
| Environment
|
|
969
|
-
|
|
970
|
-
| Unit/Integration Tests
|
|
971
|
-
| Desktop App (Tauri/Electron) | SQLite Adapter
|
|
972
|
-
| CLI Tool
|
|
973
|
-
| MCP Server
|
|
974
|
-
| Local Development
|
|
975
|
-
| Production (Single Node)
|
|
976
|
-
| Production (Multi Node)
|
|
977
|
-
| Serverless
|
|
843
|
+
| Environment | Recommended Adapter |
|
|
844
|
+
| ---------------------------- | -------------------- |
|
|
845
|
+
| Unit/Integration Tests | Memory Adapter |
|
|
846
|
+
| Desktop App (Tauri/Electron) | Bun SQLite Adapter |
|
|
847
|
+
| CLI Tool | Bun SQLite Adapter |
|
|
848
|
+
| MCP Server | Bun SQLite Adapter |
|
|
849
|
+
| Local Development | Bun SQLite Adapter |
|
|
850
|
+
| Production (Single Node) | Bun SQLite or BullMQ |
|
|
851
|
+
| Production (Multi Node) | BullMQ Adapter |
|
|
852
|
+
| Serverless | BullMQ Adapter |
|
|
978
853
|
|
|
979
854
|
#### Q: Can I switch adapters without changing business logic?
|
|
980
855
|
|
|
@@ -1003,14 +878,14 @@ adapter.registerJob("email", "send", {
|
|
|
1003
878
|
adapter.registerJob("import", "csv", {
|
|
1004
879
|
handler: async ({ input, job }) => {
|
|
1005
880
|
const rows = await parseCSV(input.file);
|
|
1006
|
-
|
|
881
|
+
|
|
1007
882
|
for (let i = 0; i < rows.length; i++) {
|
|
1008
883
|
await processRow(rows[i]);
|
|
1009
|
-
|
|
884
|
+
|
|
1010
885
|
// Update progress
|
|
1011
|
-
await
|
|
886
|
+
await job.updateProgress?.(Math.floor((i / rows.length) * 100));
|
|
1012
887
|
}
|
|
1013
|
-
|
|
888
|
+
|
|
1014
889
|
return { processed: rows.length };
|
|
1015
890
|
},
|
|
1016
891
|
onProgress: async ({ progress, message }) => {
|
|
@@ -1019,28 +894,24 @@ adapter.registerJob("import", "csv", {
|
|
|
1019
894
|
});
|
|
1020
895
|
```
|
|
1021
896
|
|
|
1022
|
-
#### Q: Can SQLite handle high throughput?
|
|
897
|
+
#### Q: Can Bun SQLite handle high throughput?
|
|
1023
898
|
|
|
1024
|
-
SQLite
|
|
899
|
+
The Bun SQLite adapter handles local persistent workloads very well, especially for desktop, CLI, and embedded apps. For distributed workers or multi-node scale, use BullMQ.
|
|
1025
900
|
|
|
1026
901
|
### 27. Common Issues & Solutions
|
|
1027
902
|
|
|
1028
|
-
#### Issue:
|
|
903
|
+
#### Issue: Bun SQLite adapter throws a runtime error in Node.js
|
|
1029
904
|
|
|
1030
|
-
**Cause:** The
|
|
905
|
+
**Cause:** The Bun SQLite adapter only runs inside Bun.
|
|
1031
906
|
|
|
1032
|
-
**Solution:**
|
|
1033
|
-
```bash
|
|
1034
|
-
npm install better-sqlite3
|
|
1035
|
-
# If compilation fails on macOS:
|
|
1036
|
-
npm install better-sqlite3 --build-from-source
|
|
1037
|
-
```
|
|
907
|
+
**Solution:** Use the BullMQ adapter in Node.js runtimes, or run the local adapter from Bun.
|
|
1038
908
|
|
|
1039
909
|
#### Issue: Jobs stuck in "active" status after restart
|
|
1040
910
|
|
|
1041
911
|
**Cause:** Process crashed while job was processing.
|
|
1042
912
|
|
|
1043
913
|
**Solution:**
|
|
914
|
+
|
|
1044
915
|
```typescript
|
|
1045
916
|
// On startup, reset stale active jobs
|
|
1046
917
|
const staleJobs = await adapter.searchJobs({
|
|
@@ -1058,6 +929,7 @@ for (const job of staleJobs) {
|
|
|
1058
929
|
**Cause:** Worker queues don't match job queue names.
|
|
1059
930
|
|
|
1060
931
|
**Solution:**
|
|
932
|
+
|
|
1061
933
|
```typescript
|
|
1062
934
|
// Ensure queue names match
|
|
1063
935
|
adapter.registerJob("email", "send", { ... }); // Queue: "email"
|
|
@@ -1069,40 +941,43 @@ const worker = await adapter.createWorker({
|
|
|
1069
941
|
});
|
|
1070
942
|
```
|
|
1071
943
|
|
|
1072
|
-
#### Issue: SQLite database locked
|
|
944
|
+
#### Issue: Bun SQLite database locked
|
|
1073
945
|
|
|
1074
946
|
**Cause:** Multiple processes trying to write simultaneously.
|
|
1075
947
|
|
|
1076
948
|
**Solution:**
|
|
1077
|
-
|
|
1078
|
-
- Ensure
|
|
1079
|
-
-
|
|
949
|
+
|
|
950
|
+
- Ensure the local runtime is the primary writer to the database path.
|
|
951
|
+
- Avoid multiple unrelated Bun processes sharing the same local queue file.
|
|
952
|
+
- Consider BullMQ for multi-process or multi-node scenarios.
|
|
1080
953
|
|
|
1081
954
|
---
|
|
1082
955
|
|
|
1083
956
|
## IX. PERFORMANCE CONSIDERATIONS
|
|
1084
957
|
|
|
1085
|
-
### 28. SQLite Adapter Performance Tips
|
|
958
|
+
### 28. Bun SQLite Adapter Performance Tips
|
|
1086
959
|
|
|
1087
|
-
1. **Use
|
|
960
|
+
1. **Use durable mode only for critical jobs:** durable writes trade throughput for stronger persistence.
|
|
1088
961
|
|
|
1089
|
-
2. **Tune
|
|
1090
|
-
- Lower interval (100ms) = more responsive, higher CPU
|
|
1091
|
-
- Higher interval (1000ms) = less responsive, lower CPU
|
|
962
|
+
2. **Tune worker batch settings:** `batchSize`, `pollTimeout`, and `heartbeatInterval` affect local throughput.
|
|
1092
963
|
|
|
1093
964
|
3. **Batch Operations:** When dispatching many jobs, consider batching:
|
|
965
|
+
|
|
1094
966
|
```typescript
|
|
1095
967
|
const jobIds = [];
|
|
1096
968
|
for (const item of items) {
|
|
1097
|
-
jobIds.push(
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
969
|
+
jobIds.push(
|
|
970
|
+
await adapter.dispatch({
|
|
971
|
+
queue: "process",
|
|
972
|
+
jobName: "item",
|
|
973
|
+
input: item,
|
|
974
|
+
}),
|
|
975
|
+
);
|
|
1102
976
|
}
|
|
1103
977
|
```
|
|
1104
978
|
|
|
1105
979
|
4. **Clean Old Jobs:** Periodically clean completed/failed jobs:
|
|
980
|
+
|
|
1106
981
|
```typescript
|
|
1107
982
|
await adapter.cleanQueue("email", {
|
|
1108
983
|
status: ["completed", "failed"],
|
|
@@ -1110,12 +985,12 @@ await adapter.cleanQueue("email", {
|
|
|
1110
985
|
});
|
|
1111
986
|
```
|
|
1112
987
|
|
|
1113
|
-
5. **
|
|
988
|
+
5. **Split high-volume workloads into dedicated queues:** local SQLite workloads benefit from clear queue boundaries.
|
|
1114
989
|
|
|
1115
990
|
### 29. Memory Considerations
|
|
1116
991
|
|
|
1117
992
|
- **Memory Adapter:** All jobs stored in RAM; limit maxJobHistory.
|
|
1118
|
-
- **SQLite Adapter:** Disk-based; memory usage scales with active
|
|
993
|
+
- **Bun SQLite Adapter:** Disk-based; memory usage scales with active workers and buffered operations.
|
|
1119
994
|
- **BullMQ Adapter:** Redis memory; configure maxmemory policy.
|
|
1120
995
|
|
|
1121
996
|
---
|
|
@@ -1150,4 +1025,3 @@ const emailQueue = IgniterQueue.create("email")
|
|
|
1150
1025
|
- **Encrypt at rest** if storing sensitive metadata.
|
|
1151
1026
|
|
|
1152
1027
|
---
|
|
1153
|
-
|