@stacksjs/bun-queue 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/LICENSE.md +21 -0
  3. package/README.md +231 -0
  4. package/dist/batch.d.ts +18 -0
  5. package/dist/bin/cli.js +1914 -0
  6. package/dist/cleanup.d.ts +22 -0
  7. package/dist/commands/index.d.ts +6 -0
  8. package/dist/commands/script-loader.d.ts +44 -0
  9. package/dist/config.d.ts +4 -0
  10. package/dist/cron-scheduler.d.ts +37 -0
  11. package/dist/dead-letter-queue.d.ts +16 -0
  12. package/dist/dispatch.d.ts +84 -0
  13. package/dist/distributed-lock.d.ts +25 -0
  14. package/dist/events.d.ts +27 -0
  15. package/dist/failed/failed-job-manager.d.ts +17 -0
  16. package/dist/failed/failed-job-provider.d.ts +37 -0
  17. package/dist/failed/index.d.ts +7 -0
  18. package/dist/group.d.ts +22 -0
  19. package/dist/index.d.ts +72 -0
  20. package/dist/job-base.d.ts +95 -0
  21. package/dist/job-processor.d.ts +21 -0
  22. package/dist/job.d.ts +27 -0
  23. package/dist/jobs/bus.d.ts +60 -0
  24. package/dist/jobs/index.d.ts +14 -0
  25. package/dist/jobs/middleware.d.ts +37 -0
  26. package/dist/leader-election.d.ts +39 -0
  27. package/dist/logger.d.ts +14 -0
  28. package/dist/metrics.d.ts +22 -0
  29. package/dist/middleware.d.ts +61 -0
  30. package/dist/observable.d.ts +23 -0
  31. package/dist/priority-queue.d.ts +40 -0
  32. package/dist/queue-manager.d.ts +24 -0
  33. package/dist/queue.d.ts +114 -0
  34. package/dist/rate-limiter.d.ts +13 -0
  35. package/dist/src/index.js +17057 -0
  36. package/dist/stalled-checker.d.ts +14 -0
  37. package/dist/types.d.ts +180 -0
  38. package/dist/utils.d.ts +26 -0
  39. package/dist/work-coordinator.d.ts +35 -0
  40. package/dist/worker.d.ts +19 -0
  41. package/dist/workers/index.d.ts +6 -0
  42. package/dist/workers/queue-worker.d.ts +62 -0
  43. package/dist/workers/worker-manager.d.ts +22 -0
  44. package/package.json +75 -0
@@ -0,0 +1,14 @@
1
+ import type { Queue } from './queue';
2
+ declare class StalledJobChecker {
3
+ readonly private queue: Queue;
4
+ readonly private logger: any;
5
+ private timer: NodeJS.Timeout | null;
6
+ private running: any;
7
+ readonly private interval: number;
8
+ readonly private maxRetries: number;
9
+ constructor(queue: Queue, interval?: number, maxRetries?: number);
10
+ start(): void;
11
+ stop(): void;
12
+ private checkStalledJobs(): Promise<void>;
13
+ }
14
+ export { StalledJobChecker };
@@ -0,0 +1,180 @@
1
+ import type { RedisClient } from 'bun';
2
+ export type { RedisClient };
3
+ export declare const DEFAULT_PRIORITY_LEVEL: 0;
4
+ export declare const MAX_PRIORITY_LEVELS: 10;
5
+ export declare interface QueueConfig {
6
+ verbose?: boolean
7
+ logLevel?: LogLevel
8
+ redis?: {
9
+ url?: string
10
+ client?: RedisClient
11
+ }
12
+ prefix?: string
13
+ defaultJobOptions?: JobOptions
14
+ limiter?: RateLimiter
15
+ metrics?: {
16
+ enabled: boolean
17
+ collectInterval?: number
18
+ }
19
+ stalledJobCheckInterval?: number
20
+ maxStalledJobRetries?: number
21
+ distributedLock?: boolean
22
+ defaultDeadLetterOptions?: DeadLetterQueueOptions
23
+ horizontalScaling?: {
24
+ enabled?: boolean
25
+ instanceId?: string
26
+ maxWorkersPerInstance?: number
27
+ jobsPerWorker?: number
28
+ leaderElection?: {
29
+ heartbeatInterval?: number
30
+ leaderTimeout?: number
31
+ }
32
+ workCoordination?: {
33
+ pollInterval?: number
34
+ keyPrefix?: string
35
+ }
36
+ }
37
+ }
38
+ export declare interface QueueManagerConfig {
39
+ default?: string
40
+ connections?: Record<string, QueueConnectionConfig>
41
+ failed?: {
42
+ driver: 'redis' | 'database'
43
+ table?: string
44
+ prefix?: string
45
+ }
46
+ batching?: {
47
+ driver: 'redis' | 'database'
48
+ table?: string
49
+ prefix?: string
50
+ }
51
+ }
52
+ export declare interface QueueConnectionConfig extends QueueConfig {
53
+ driver: 'redis' | 'memory' | 'database'
54
+ table?: string
55
+ }
56
+ export declare interface JobOptions {
57
+ delay?: number
58
+ attempts?: number
59
+ backoff?: {
60
+ type: 'fixed' | 'exponential'
61
+ delay: number
62
+ }
63
+ removeOnComplete?: boolean | number
64
+ removeOnFail?: boolean | number
65
+ priority?: number
66
+ lifo?: boolean
67
+ timeout?: number
68
+ jobId?: string
69
+ repeat?: {
70
+ every: number
71
+ limit?: number
72
+ count?: number
73
+ cron?: string
74
+ tz?: string
75
+ startDate?: Date | number
76
+ endDate?: Date | number
77
+ }
78
+ dependsOn?: string | string[]
79
+ keepJobs?: boolean
80
+ deadLetter?: boolean | DeadLetterQueueOptions
81
+ }
82
+ export declare interface RateLimiter {
83
+ max: number
84
+ duration: number
85
+ keyPrefix?: string | ((data: any) => string)
86
+ }
87
+ export declare interface Job<T = any> {
88
+ id: string
89
+ name: string
90
+ data: T
91
+ opts: JobOptions
92
+ progress: number
93
+ delay: number
94
+ timestamp: number
95
+ attemptsMade: number
96
+ stacktrace: string[]
97
+ returnvalue: any
98
+ finishedOn?: number
99
+ processedOn?: number
100
+ failedReason?: string
101
+ dependencies?: string[]
102
+ }
103
+ export declare interface QueueEvents {
104
+ jobAdded: (jobId: string, name: string) => void
105
+ jobRemoved: (jobId: string) => void
106
+ jobCompleted: (jobId: string, result: any) => void
107
+ jobFailed: (jobId: string, error: Error) => void
108
+ jobProgress: (jobId: string, progress: number) => void
109
+ jobActive: (jobId: string) => void
110
+ jobStalled: (jobId: string) => void
111
+ jobDelayed: (jobId: string, delay: number) => void
112
+ ready: () => void
113
+ error: (error: Error) => void
114
+ batchAdded: (batchId: string, jobIds: string[]) => void
115
+ batchCompleted: (batchId: string, results: any[]) => void
116
+ batchFailed: (batchId: string, errors: Error[]) => void
117
+ batchProgress: (batchId: string, progress: number) => void
118
+ groupCreated: (groupName: string) => void
119
+ groupRemoved: (groupName: string) => void
120
+ observableStarted: (observableId: string) => void
121
+ observableStopped: (observableId: string) => void
122
+ jobMovedToDeadLetter: (jobId: string, deadLetterQueueName: string, reason: string) => void
123
+ jobRepublishedFromDeadLetter: (jobId: string, originalQueueName: string) => void
124
+ }
125
+ // Batch processing types
126
+ export declare interface BatchOptions extends JobOptions {
127
+ batchSize?: number
128
+ processTimeout?: number
129
+ }
130
+ export declare interface Batch<T = any> {
131
+ id: string
132
+ jobs: Job<T>[]
133
+ opts: BatchOptions
134
+ timestamp: number
135
+ status: JobStatus
136
+ processingAt?: number
137
+ finishedAt?: number
138
+ }
139
+ // Group types
140
+ export declare interface GroupOptions {
141
+ name: string
142
+ limit?: number
143
+ maxConcurrency?: number
144
+ }
145
+ export declare interface Group {
146
+ name: string
147
+ limit: number
148
+ maxConcurrency: number
149
+ queues: string[]
150
+ }
151
+ // Observable types
152
+ export declare interface ObservableOptions {
153
+ interval?: number
154
+ autoStart?: boolean
155
+ }
156
+ export declare interface Observable {
157
+ id: string
158
+ queues: string[]
159
+ interval: number
160
+ running: boolean
161
+ }
162
+ // Support 0-9 priority levels by default
163
+ export declare interface PriorityQueueOptions {
164
+ levels?: number
165
+ defaultLevel?: number
166
+ dynamicReordering?: boolean
167
+ reorderInterval?: number
168
+ }
169
+ // Dead Letter Queue options
170
+ export declare interface DeadLetterQueueOptions {
171
+ queueSuffix?: string
172
+ maxRetries?: number
173
+ processFailed?: boolean
174
+ removeFromOriginalQueue?: boolean
175
+ enabled?: boolean
176
+ }
177
+ export type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent'
178
+ export type JobStatus = 'waiting' | 'active' | 'completed' | 'failed' | 'delayed' | 'paused'
179
+ // Priority Queue types
180
+ export type PriorityLevel = number
@@ -0,0 +1,26 @@
1
+ import { RedisClient } from 'bun';
2
+ import type { JobOptions, QueueConfig } from './types';
3
+ /**
4
+ * Gets a Redis client from the config or creates a new one
5
+ */
6
+ export declare function getRedisClient(queueConfig?: QueueConfig): RedisClient;
7
+ /**
8
+ * Generates a unique job ID
9
+ */
10
+ export declare function generateId(): string;
11
+ /**
12
+ * Merges job options with defaults
13
+ */
14
+ export declare function mergeOptions(options?: JobOptions): JobOptions;
15
+ /**
16
+ * Gets key with prefix
17
+ */
18
+ export declare function getKey(key: string, prefix?: string): string;
19
+ /**
20
+ * Parses Redis hash into a job
21
+ */
22
+ export declare function parseJob(hash: Record<string, string>): any;
23
+ /**
24
+ * Wait for the specified number of milliseconds
25
+ */
26
+ export declare function wait(ms: number): Promise<void>;
@@ -0,0 +1,35 @@
1
+ import type { RedisClient } from 'bun';
2
+ export declare interface WorkCoordinatorOptions {
3
+ keyPrefix?: string
4
+ pollInterval?: number
5
+ instanceId?: string
6
+ jobsPerWorker?: number
7
+ maxWorkersPerInstance?: number
8
+ }
9
+ /**
10
+ * Manages work distribution among multiple queue instances
11
+ * to ensure fair sharing of jobs and prevent overloading any one instance
12
+ */
13
+ export declare class WorkCoordinator {
14
+ readonly private redisClient: RedisClient;
15
+ readonly private keyPrefix: string;
16
+ readonly private instanceId: string;
17
+ readonly private pollInterval: number;
18
+ readonly private jobsPerWorker: number;
19
+ readonly private maxWorkersPerInstance: number;
20
+ readonly private logger: any;
21
+ private pollTimer: NodeJS.Timeout | null;
22
+ private workers: number;
23
+ private running: boolean;
24
+ constructor(redisClient: RedisClient, options?: WorkCoordinatorOptions);
25
+ start(): Promise<void>;
26
+ stop(): Promise<void>;
27
+ private registerInstance(): Promise<void>;
28
+ private unregisterInstance(): Promise<void>;
29
+ private startPolling(): void;
30
+ private sendHeartbeat(): Promise<void>;
31
+ private coordinateWork(): Promise<void>;
32
+ private calculateWorkerDistribution(instanceInfo: Record<string, any>, activeInstances: string[], totalWorkers: number, totalMaxWorkers: number): Record<string, number>;
33
+ getWorkerCount(): number;
34
+ getInstanceStatistics(): Promise<Record<string, any>>;
35
+ }
@@ -0,0 +1,19 @@
1
+ import type { Job } from './job';
2
+ import type { Queue } from './queue';
3
+ export declare class Worker<T = any> {
4
+ queue: Queue<T>;
5
+ concurrency: number;
6
+ handler: (job: Job<T>) => Promise<any>;
7
+ processing: Map<string, Promise<any>>;
8
+ running: boolean;
9
+ timer: NodeJS.Timeout | null;
10
+ constructor(queue: Queue<T>, concurrency: number, handler: (job: Job<T>) => Promise<any>);
11
+ start(): void;
12
+ stop(timeout?: any): Promise<void>;
13
+ private processTick(): void;
14
+ private processJobs(): Promise<void>;
15
+ private processJob(jobId: string): void;
16
+ private moveToActive(jobId: string): Promise<void>;
17
+ private moveDelayedJobsToWaiting(): Promise<void>;
18
+ adjustConcurrency(newConcurrency: number): void;
19
+ }
@@ -0,0 +1,6 @@
1
+ export {
2
+ QueueWorker,
3
+ type WorkerEvents,
4
+ type WorkerOptions,
5
+ } from './queue-worker';
6
+ export { WorkerManager } from './worker-manager';
@@ -0,0 +1,62 @@
1
+ import { FailedJobManager } from '../failed';
2
+ import type { QueueManagerConfig } from '../types';
3
+ export declare interface WorkerOptions {
4
+ name?: string
5
+ connection?: string
6
+ queue?: string[]
7
+ delay?: number
8
+ memory?: number
9
+ timeout?: number
10
+ sleep?: number
11
+ maxTries?: number
12
+ force?: boolean
13
+ stopWhenEmpty?: boolean
14
+ maxJobs?: number
15
+ maxTime?: number
16
+ rest?: number
17
+ }
18
+ export declare interface WorkerEvents {
19
+ jobProcessing: (job: QueueJob<any>) => void
20
+ jobProcessed: (job: QueueJob<any>, result: any) => void
21
+ jobFailed: (job: QueueJob<any>, error: Error) => void
22
+ jobRetry: (job: QueueJob<any>) => void
23
+ jobTimeout: (job: QueueJob<any>) => void
24
+ workerStopping: (status: number) => void
25
+ }
26
+ export declare interface WorkerStats {
27
+ jobsProcessed: number
28
+ runtime: number
29
+ isRunning: boolean
30
+ lastRestart: number
31
+ }
32
+ export declare class QueueWorker {
33
+ private logger: any;
34
+ private failedJobManager: FailedJobManager;
35
+ private isRunning: any;
36
+ private shouldStop: any;
37
+ private jobsProcessed: any;
38
+ private startTime: any;
39
+ private lastRestart: any;
40
+ private events: Partial<WorkerEvents>;
41
+ private config: QueueManagerConfig;
42
+ private options?: WorkerOptions;
43
+ constructor(config: QueueManagerConfig, options?: WorkerOptions);
44
+ work(): Promise<void>;
45
+ stop(status?: number, options?: { wait?: boolean }): Promise<void>;
46
+ restart(): Promise<void>;
47
+ private runNextJob(): Promise<void>;
48
+ private getNextJob(queue: any): Promise<QueueJob<any> | null>;
49
+ private processJob(queueJob: QueueJob<any>, queueName: string): Promise<void>;
50
+ private executeJob(queueJob: QueueJob<any>): Promise<any>;
51
+ private executeJobClass(queueJob: QueueJob<any>, jobData: any): Promise<any>;
52
+ private handleJobException(queueJob: QueueJob<any>, error: Error, queueName: string): Promise<void>;
53
+ private retryJob(queueJob: QueueJob<any>, _error: Error): Promise<void>;
54
+ private failJob(queueJob: QueueJob<any>, error: Error, queueName: string): Promise<void>;
55
+ private isJobClass(data: any): boolean;
56
+ private getJobMaxTries(queueJob: QueueJob<any>): number;
57
+ private calculateRetryDelay(queueJob: QueueJob<any>): number;
58
+ private checkLimits(): Promise<void>;
59
+ private sleep(ms: number): Promise<void>;
60
+ on<K extends keyof WorkerEvents>(event: K, callback: WorkerEvents[K]): this;
61
+ getStats(): WorkerStats;
62
+ }
@@ -0,0 +1,22 @@
1
+ import { QueueWorker } from './queue-worker';
2
+ import type { QueueManagerConfig } from '../types';
3
+ import type { WorkerOptions } from './queue-worker';
4
+ export declare class WorkerManager {
5
+ private workers: Map<string, QueueWorker>;
6
+ private logger: any;
7
+ private config: QueueManagerConfig;
8
+ constructor(config: QueueManagerConfig);
9
+ startWorker(name: string, options?: WorkerOptions): Promise<QueueWorker>;
10
+ stopWorker(name: string, options?: { wait?: boolean }): Promise<boolean>;
11
+ restartWorker(name: string): Promise<boolean>;
12
+ stopAllWorkers(options?: { wait?: boolean }): Promise<void>;
13
+ getWorker(name: string): QueueWorker | undefined;
14
+ getWorkerNames(): string[];
15
+ getWorkerStats(): Record<string, any>;
16
+ isWorkerRunning(name: string): boolean;
17
+ getWorkerCount(): number;
18
+ work(options?: WorkerOptions & { name?: string }): Promise<QueueWorker>;
19
+ restart(name?: string): Promise<void>;
20
+ terminate(name?: string, options?: { wait?: boolean }): Promise<void>;
21
+ monitor(intervalMs?: number): NodeJS.Timeout;
22
+ }
package/package.json ADDED
@@ -0,0 +1,75 @@
1
+ {
2
+ "name": "@stacksjs/bun-queue",
3
+ "type": "module",
4
+ "version": "0.0.1",
5
+ "description": "A Redis-backed job queue built for Bun.",
6
+ "author": "Chris Breuer <chris@stacksjs.org>",
7
+ "license": "MIT",
8
+ "homepage": "https://github.com/stacksjs/bun-queue#readme",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/stacksjs/bun-queue.git"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/stacksjs/bun-queue/issues"
15
+ },
16
+ "keywords": [
17
+ "queue",
18
+ "job",
19
+ "redis",
20
+ "worker",
21
+ "task",
22
+ "scheduler",
23
+ "bun",
24
+ "typescript"
25
+ ],
26
+ "exports": {
27
+ ".": {
28
+ "types": "./src/index.ts",
29
+ "import": "./src/index.ts"
30
+ },
31
+ "./*": {
32
+ "import": "./src/*"
33
+ }
34
+ },
35
+ "module": "./src/index.ts",
36
+ "types": "./src/index.ts",
37
+ "files": [
38
+ "README.md",
39
+ "dist"
40
+ ],
41
+ "scripts": {
42
+ "build": "bun --bun build.ts && bun run compile",
43
+ "compile": "bun build ./bin/cli.ts --compile --minify --outfile bin/queue",
44
+ "compile:all": "bun run compile:linux-x64 && bun run compile:linux-arm64 && bun run compile:windows-x64 && bun run compile:darwin-x64 && bun run compile:darwin-arm64",
45
+ "compile:linux-x64": "bun build ./bin/cli.ts --compile --minify --target=bun-linux-x64 --outfile bin/queue-linux-x64",
46
+ "compile:linux-arm64": "bun build ./bin/cli.ts --compile --minify --target=bun-linux-arm64 --outfile bin/queue-linux-arm64",
47
+ "compile:windows-x64": "bun build ./bin/cli.ts --compile --minify --target=bun-windows-x64 --outfile bin/queue-windows-x64.exe",
48
+ "compile:darwin-x64": "bun build ./bin/cli.ts --compile --minify --target=bun-darwin-x64 --outfile bin/queue-darwin-x64",
49
+ "compile:darwin-arm64": "bun build ./bin/cli.ts --compile --minify --target=bun-darwin-arm64 --outfile bin/queue-darwin-arm64",
50
+ "zip": "bun run zip:all",
51
+ "zip:all": "bun run zip:linux-x64 && bun run zip:linux-arm64 && bun run zip:windows-x64 && bun run zip:darwin-x64 && bun run zip:darwin-arm64",
52
+ "zip:linux-x64": "zip -j bin/queue-linux-x64.zip bin/queue-linux-x64",
53
+ "zip:linux-arm64": "zip -j bin/queue-linux-arm64.zip bin/queue-linux-arm64",
54
+ "zip:windows-x64": "zip -j bin/queue-windows-x64.zip bin/queue-windows-x64.exe",
55
+ "zip:darwin-x64": "zip -j bin/queue-darwin-x64.zip bin/queue-darwin-x64",
56
+ "zip:darwin-arm64": "zip -j bin/queue-darwin-arm64.zip bin/queue-darwin-arm64",
57
+ "fresh": "bunx rimraf node_modules/ bun.lock && bun i",
58
+ "prepublishOnly": "bun --bun run build && bun run compile:all && bun run zip",
59
+ "test": "bun test",
60
+ "lint": "bunx --bun eslint .",
61
+ "lint:fix": "bunx --bun eslint . --fix",
62
+ "changelog": "bunx logsmith --verbose",
63
+ "changelog:generate": "bunx logsmith --output CHANGELOG.md",
64
+ "release": "bun --bun run changelog:generate && bunx --bun bumpx prompt --recursive",
65
+ "typecheck": "bun --bun tsc --noEmit",
66
+ "example:basic": "bun examples/basic.ts",
67
+ "example:advanced": "bun examples/advanced.ts",
68
+ "example:advanced-features": "bun examples/advanced-features.ts",
69
+ "example:priority-queue": "bun examples/priority-queue.ts",
70
+ "example:key-rate-limiting": "bun examples/key-rate-limiting.ts",
71
+ "example:distributed-locks": "bun examples/distributed-locks.ts",
72
+ "example:cron-jobs": "bun examples/cron-jobs.ts",
73
+ "example:dead-letter-queue": "bun examples/dead-letter-queue.ts"
74
+ }
75
+ }