@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,37 @@
1
+ import type { JobMiddleware } from '../job-base';
2
+ // Job middleware factory
3
+ export declare const Middleware: {
4
+ rateLimited: (key: string, maxAttempts: number, decaySeconds?: number) => any;
5
+ withoutOverlapping: (key?: string, releaseAfterSeconds?: number, expireAfterSeconds?: number) => any;
6
+ skipIfBatchCancelled: () => any;
7
+ throttlesExceptions: (maxAttempts?: number, decaySeconds?: number, by?: (job: Job) => string) => any
8
+ };
9
+ export declare class RateLimited implements JobMiddleware {
10
+ private key: string;
11
+ private maxAttempts: number;
12
+ private decaySeconds?: number;
13
+ constructor(key: string, maxAttempts: number, decaySeconds?: number);
14
+ handle(job: Job, next: () => Promise<void>): Promise<void>;
15
+ static by(key: string, maxAttempts: number, decaySeconds?: number): RateLimited;
16
+ }
17
+ export declare class WithoutOverlapping implements JobMiddleware {
18
+ private key?: string;
19
+ private releaseAfterSeconds?: number;
20
+ private expireAfterSeconds?: number;
21
+ constructor(key?: string, releaseAfterSeconds?: number, expireAfterSeconds?: number);
22
+ handle(job: Job, next: () => Promise<void>): Promise<void>;
23
+ static by(key: string): WithoutOverlapping;
24
+ releaseAfter(seconds: number): this;
25
+ expireAfter(seconds: number): this;
26
+ }
27
+ export declare class SkipIfBatchCancelled implements JobMiddleware {
28
+ handle(job: Job, next: () => Promise<void>): Promise<void>;
29
+ }
30
+ export declare class ThrottlesExceptions implements JobMiddleware {
31
+ private maxAttempts?: number;
32
+ private decaySeconds?: number;
33
+ private by?: (job: Job) => string;
34
+ constructor(maxAttempts?: number, decaySeconds?: number, by?: (job: Job) => string);
35
+ handle(job: Job, next: () => Promise<void>): Promise<void>;
36
+ static by(callback: (job: Job) => string, maxAttempts?: number, decaySeconds?: number): ThrottlesExceptions;
37
+ }
@@ -0,0 +1,39 @@
1
+ import type { RedisClient } from 'bun';
2
+ export declare interface LeaderElectionOptions {
3
+ keyPrefix?: string
4
+ heartbeatInterval?: number
5
+ leaderTimeout?: number
6
+ onBecomeLeader?: () => void
7
+ onLeadershipLost?: () => void
8
+ onLeaderChanged?: (leaderId: string) => void
9
+ instanceId?: string
10
+ }
11
+ /**
12
+ * Implements leader election for distributed queue instances
13
+ * using Redis for coordination
14
+ */
15
+ export declare class LeaderElection {
16
+ readonly private redisClient: RedisClient;
17
+ readonly private keyPrefix: string;
18
+ readonly private instanceId: string;
19
+ readonly private logger: any;
20
+ readonly private heartbeatInterval: number;
21
+ readonly private leaderTimeout: number;
22
+ readonly private options: LeaderElectionOptions;
23
+ private heartbeatTimer: NodeJS.Timeout | null;
24
+ private watchdogTimer: NodeJS.Timeout | null;
25
+ private isLeader: any;
26
+ private currentLeaderId: string | null;
27
+ constructor(redisClient: RedisClient, options?: LeaderElectionOptions);
28
+ start(): Promise<void>;
29
+ stop(): Promise<void>;
30
+ isCurrentLeader(): boolean;
31
+ getCurrentLeader(): Promise<string | null>;
32
+ private electLeader(): Promise<void>;
33
+ private becomeLeader(): void;
34
+ private startHeartbeat(): void;
35
+ private startWatchdog(): void;
36
+ private checkLeadership(): Promise<void>;
37
+ private loseLeadership(): void;
38
+ private stepDown(): Promise<void>;
39
+ }
@@ -0,0 +1,14 @@
1
+ import type { LogLevel } from './types';
2
+ export declare function createLogger(queueName?: string): Logger;
3
+ export declare const logger: Logger;
4
+ declare class Logger {
5
+ private level: LogLevel;
6
+ private queueName?: string;
7
+ constructor(queueName?: string);
8
+ setLevel(level: LogLevel): void;
9
+ private formatMessage(message: string): string;
10
+ debug(message: string, args: any[]): void;
11
+ info(message: string, args: any[]): void;
12
+ warn(message: string, args: any[]): void;
13
+ error(message: string, args: any[]): void;
14
+ }
@@ -0,0 +1,22 @@
1
+ import type { Queue } from './queue';
2
+ export declare interface QueueMetrics {
3
+ completed: number[]
4
+ failed: number[]
5
+ delayed: number[]
6
+ active: number[]
7
+ waiting: number[]
8
+ added: number
9
+ processedRate: number
10
+ }
11
+ export declare class Metrics {
12
+ private queue: Queue;
13
+ private collectInterval: number;
14
+ private intervalId: number | null;
15
+ private metrics: QueueMetrics;
16
+ constructor(queue: Queue);
17
+ private startCollecting(): void;
18
+ stop(): void;
19
+ private collectMetrics(): Promise<void>;
20
+ trackJobAdded(): void;
21
+ getMetrics(): Promise<QueueMetrics>;
22
+ }
@@ -0,0 +1,61 @@
1
+ import type { JobContract, JobMiddleware } from './job-base';
2
+ export declare const middleware: {
3
+ rateLimit: (maxAttempts: number, decayMinutes?: number, prefix?: string) => any;
4
+ unique: (ttl?: number) => any;
5
+ throttle: (allows: number, every: number, prefix?: string) => any;
6
+ withoutOverlapping: (ttl?: number, releaseAfter?: number) => any;
7
+ skipIf: (condition: () => boolean | Promise<boolean>) => any;
8
+ onFailure: (callback: (error: Error, job: JobContract) => Promise<void> | void) => any
9
+ };
10
+ export declare interface MiddlewareStack {
11
+ through: (middleware: JobMiddleware[]) => Promise<void>
12
+ then: (destination: () => Promise<void>) => Promise<void>
13
+ }
14
+ export declare class JobMiddlewareStack implements MiddlewareStack {
15
+ private job: JobContract;
16
+ private middlewares: JobMiddleware[];
17
+ private index: any;
18
+ constructor(job: JobContract, middlewares: JobMiddleware[]);
19
+ through(middleware: JobMiddleware[]): Promise<void>;
20
+ then(destination: () => Promise<void>): Promise<void>;
21
+ private executeMiddleware(destination: () => Promise<void>): Promise<void>;
22
+ }
23
+ export declare class RateLimitMiddleware implements JobMiddleware {
24
+ private maxAttempts: number;
25
+ private decayMinutes: number;
26
+ private prefix: string;
27
+ constructor(maxAttempts: number, decayMinutes?: number, prefix?: any);
28
+ handle(job: JobContract, next: () => Promise<void>): Promise<void>;
29
+ private getRateLimitKey(job: JobContract): string;
30
+ }
31
+ export declare class UniqueJobMiddleware implements JobMiddleware {
32
+ private ttl: number;
33
+ constructor(ttl?: number);
34
+ handle(job: JobContract, next: () => Promise<void>): Promise<void>;
35
+ private getUniqueKey(job: JobContract, uniqueId: string): string;
36
+ }
37
+ export declare class ThrottleMiddleware implements JobMiddleware {
38
+ private allows: number;
39
+ private every: number;
40
+ private prefix: string;
41
+ constructor(allows: number, every: number, prefix?: any);
42
+ handle(job: JobContract, next: () => Promise<void>): Promise<void>;
43
+ private getThrottleKey(job: JobContract): string;
44
+ }
45
+ export declare class WithoutOverlappingMiddleware implements JobMiddleware {
46
+ private ttl: number;
47
+ private releaseAfter: number;
48
+ constructor(ttl?: number, releaseAfter?: number);
49
+ handle(job: JobContract, next: () => Promise<void>): Promise<void>;
50
+ private getOverlapKey(job: JobContract): string;
51
+ }
52
+ export declare class SkipIfMiddleware implements JobMiddleware {
53
+ private condition: () => boolean | Promise<boolean>;
54
+ constructor(condition: () => boolean | Promise<boolean>);
55
+ handle(_job: JobContract, next: () => Promise<void>): Promise<void>;
56
+ }
57
+ export declare class FailureMiddleware implements JobMiddleware {
58
+ private callback: (error: Error, job: JobContract) => Promise<void> | void;
59
+ constructor(callback: (error: Error, job: JobContract) => Promise<void> | void);
60
+ handle(job: JobContract, next: () => Promise<void>): Promise<void>;
61
+ }
@@ -0,0 +1,23 @@
1
+ import type { RedisClient } from 'bun';
2
+ import type { Observable, ObservableOptions } from './types';
3
+ import type { Queue } from './queue';
4
+ export declare class QueueObservable {
5
+ readonly private redisClient: RedisClient;
6
+ readonly private queues: Map<string, Queue<any>>;
7
+ readonly private observables: Map<string, Observable>;
8
+ readonly private timers: Map<string, NodeJS.Timeout>;
9
+ readonly private prefix: string;
10
+ readonly private logger: any;
11
+ constructor(prefix: string, redisClient: RedisClient);
12
+ createObservable(queues: Queue<any>[], options?: ObservableOptions): Promise<Observable>;
13
+ startObservable(observableId: string): Promise<void>;
14
+ stopObservable(observableId: string): Promise<void>;
15
+ removeObservable(observableId: string): Promise<void>;
16
+ getAllObservables(): Promise<Observable[]>;
17
+ getObservable(observableId: string): Promise<Observable | null>;
18
+ private startMonitoring(observableId: string): void;
19
+ getObservableStats(observableId: string): Promise<Record<string, any> | null>;
20
+ closeAll(): Promise<void>;
21
+ private getObservableKey(observableId: string): string;
22
+ private getObservableStatsKey(observableId: string): string;
23
+ }
@@ -0,0 +1,40 @@
1
+ import type { RedisClient } from 'bun';
2
+ import { Job } from './job';
3
+ import { Queue } from './queue';
4
+ import type { JobEvents } from './events';
5
+ import type { JobOptions, JobStatus, PriorityLevel, PriorityQueueOptions, QueueConfig } from './types';
6
+ /**
7
+ * PriorityQueue implements a queue with priority support
8
+ * It maintains separate priority queues and processes higher priority jobs first
9
+ */
10
+ export declare class PriorityQueue<T = any> {
11
+ name: string;
12
+ prefix: string;
13
+ redisClient: RedisClient;
14
+ keyPrefix: string;
15
+ events: JobEvents;
16
+ readonly private baseQueue: Queue<T>;
17
+ readonly private priorityLevels: number;
18
+ readonly private defaultPriorityLevel: number;
19
+ readonly private dynamicReordering: boolean;
20
+ readonly private reorderInterval: number;
21
+ private reorderTimer: NodeJS.Timeout | null;
22
+ readonly private logger: any;
23
+ private jobMoverTimer: NodeJS.Timeout | null;
24
+ constructor(name: string, priorityOptions?: PriorityQueueOptions, queueOptions?: QueueConfig);
25
+ add(data: T, options?: JobOptions): Promise<Job<T>>;
26
+ process(concurrency: number, handler: (job: Job<T>) => Promise<any>): void;
27
+ close(): Promise<void>;
28
+ getJob(jobId: string): Promise<Job<T> | null>;
29
+ removeJob(jobId: string): Promise<void>;
30
+ getJobs(status: JobStatus, start?: any, end?: any): Promise<Job<T>[]>;
31
+ getJobCounts(): Promise<Record<JobStatus, number>>;
32
+ empty(): Promise<void>;
33
+ private moveJobsToWaiting(): Promise<void>;
34
+ private startJobMover(): void;
35
+ private reorderJobs(): Promise<void>;
36
+ private startDynamicReordering(): void;
37
+ getKey(name: string): string;
38
+ getJobKey(jobId: string): string;
39
+ private getPriorityKey(priority: PriorityLevel): string;
40
+ }
@@ -0,0 +1,24 @@
1
+ import { config } from './config';
2
+ import type { QueueConnectionConfig, QueueManagerConfig } from './types';
3
+ export declare function getQueueManager(config?: Partial<QueueManagerConfig>): QueueManager;
4
+ export declare function setQueueManager(manager: QueueManager): void;
5
+ export declare function closeQueueManager(): Promise<void>;
6
+ export declare interface QueueConnection {
7
+ name: string
8
+ config: QueueConnectionConfig
9
+ queues: Map<string, QueueInstance<any>>
10
+ queue: <T = any>(name?: string) => QueueInstance<T>
11
+ }
12
+ export declare class QueueManager {
13
+ private connections: Map<string, QueueConnection>;
14
+ private config: QueueManagerConfig;
15
+ constructor(managerConfig?: Partial<QueueManagerConfig>);
16
+ connection(name?: string): QueueConnection;
17
+ queue<T = any>(name?: string): QueueInstance<T>;
18
+ closeAll(): Promise<void>;
19
+ getConnections(): string[];
20
+ addConnection(name: string, config: QueueConnectionConfig): void;
21
+ removeConnection(name: string): void;
22
+ setDefaultConnection(name: string): void;
23
+ getDefaultConnection(): string;
24
+ }
@@ -0,0 +1,114 @@
1
+ import type { RedisClient } from 'bun';
2
+ import { CleanupService } from './cleanup';
3
+ import { createLogger } from './logger';
4
+ import { CronScheduler } from './cron-scheduler';
5
+ import { DeadLetterQueue } from './dead-letter-queue';
6
+ import { DistributedLock } from './distributed-lock';
7
+ import { Job } from './job';
8
+ import { JobEvents } from './events';
9
+ import { LeaderElection } from './leader-election';
10
+ import { Metrics } from './metrics';
11
+ import { RateLimiter } from './rate-limiter';
12
+ import { StalledJobChecker } from './stalled-checker';
13
+ import { WorkCoordinator } from './work-coordinator';
14
+ import { Worker } from './worker';
15
+ import type { CronJobOptions } from './cron-scheduler';
16
+ import type { DeadLetterQueueOptions, JobOptions, JobStatus, QueueConfig, QueueConnectionConfig } from './types';
17
+ import type { JobContract } from './job-base';
18
+ import type { JobProcessor } from './job-processor';
19
+ export declare class Queue<T = any> {
20
+ name: string;
21
+ prefix: string;
22
+ redisClient: RedisClient;
23
+ keyPrefix: string;
24
+ events: JobEvents;
25
+ private worker: Worker<T> | null;
26
+ private metrics: Metrics | null;
27
+ private cleanupService: CleanupService | null;
28
+ private stalledChecker: StalledJobChecker | null;
29
+ readonly protected logger: ReturnType<typeof createLogger>;
30
+ private limiter: RateLimiter | null;
31
+ private defaultJobOptions: JobOptions | undefined;
32
+ private lock: DistributedLock | null;
33
+ private cronScheduler: CronScheduler | null;
34
+ private deadLetterQueue: DeadLetterQueue<T> | null;
35
+ private defaultDeadLetterOptions: DeadLetterQueueOptions | undefined;
36
+ private leaderElection: LeaderElection | null;
37
+ private workCoordinator: WorkCoordinator | null;
38
+ private instanceId: string;
39
+ private horizontalScalingEnabled: boolean;
40
+ private jobProcessor: JobProcessor;
41
+ constructor(name: string, options?: QueueConnectionConfig);
42
+ private initializeHorizontalScaling(options: QueueConfig): void;
43
+ private handleBecomeLeader(): void;
44
+ private handleLeadershipLost(): void;
45
+ private handleLeaderChanged(leaderId: string): void;
46
+ private init(): Promise<void>;
47
+ add(data: T, options?: JobOptions): Promise<Job<T>>;
48
+ process(concurrency: number, handler: (job: Job<T>) => Promise<any>): void;
49
+ private startHorizontalScaling(concurrency: number, handler: (job: Job<T>) => Promise<any>): Promise<void>;
50
+ private startWorker(concurrency: number, handler: (job: Job<T>) => Promise<any>): void;
51
+ private _horizontalScalingInterval: NodeJS.Timeout | null;
52
+ close(): Promise<void>;
53
+ getInstanceId(): string;
54
+ getClusterInfo(): Promise<Record<string, any> | null>;
55
+ isLeader(): boolean;
56
+ getLeaderId(): Promise<string | null>;
57
+ getJob(jobId: string): Promise<Job<T> | null>;
58
+ pause(): Promise<void>;
59
+ resume(): Promise<void>;
60
+ removeJob(jobId: string): Promise<void>;
61
+ getMetrics(): Promise<any>;
62
+ getJobs(status: JobStatus, start?: any, end?: any): Promise<Job<T>[]>;
63
+ getJobCounts(): Promise<Record<JobStatus, number>>;
64
+ empty(): Promise<void>;
65
+ ping(): Promise<boolean>;
66
+ getKey(name: string): string;
67
+ getJobKey(jobId: string): string;
68
+ isRateLimited(key?: string, data?: T): Promise<{ limited: boolean, resetIn: number }>;
69
+ processJobWithLock(jobId: string, handler: (job: Job<T>) => Promise<any>): Promise<any>;
70
+ getLock(): DistributedLock | null;
71
+ scheduleCron(options: CronJobOptions): Promise<string>;
72
+ unscheduleCron(jobId: string): Promise<boolean>;
73
+ getDeadLetterQueue(): DeadLetterQueue<T>;
74
+ getDefaultDeadLetterOptions(): DeadLetterQueueOptions | undefined;
75
+ moveToDeadLetter(jobId: string, reason: string): Promise<boolean>;
76
+ getDeadLetterJobs(start?: any, end?: any): Promise<Job<T>[]>;
77
+ republishDeadLetterJob(jobId: string, options?: { resetRetries?: boolean }): Promise<Job<T> | null>;
78
+ removeDeadLetterJob(jobId: string): Promise<boolean>;
79
+ clearDeadLetterQueue(): Promise<void>;
80
+ bulkRemove(jobIds: string[]): Promise<number>;
81
+ bulkPause(jobIds: string[]): Promise<number>;
82
+ bulkResume(jobIds: string[]): Promise<number>;
83
+ dispatchJob(job: JobContract, args: any[]): Promise<Job<any>>;
84
+ processJobs(concurrency?: number): void;
85
+ addJobBatch(jobs: JobContract[], batchOptions?: {
86
+ batchId?: string
87
+ allowFailures?: boolean
88
+ }): Promise<Job<any>[]>;
89
+ retryJob(jobId: string, newArgs?: any[]): Promise<Job<any> | null>;
90
+ getFailedJobClasses(): Promise<Array<{
91
+ job: Job<any>
92
+ jobClass: string
93
+ error: string
94
+ failedAt: number
95
+ }>>;
96
+ getJobClassStats(): Promise<{
97
+ byClass: Record<string, {
98
+ total: number
99
+ completed: number
100
+ failed: number
101
+ pending: number
102
+ }>
103
+ overall: {
104
+ total: number
105
+ completed: number
106
+ failed: number
107
+ pending: number
108
+ }
109
+ }>;
110
+ private isJobClass(data: any): boolean;
111
+ clearJobClasses(): Promise<void>;
112
+ pauseJobClasses(): Promise<void>;
113
+ resumeJobClasses(): Promise<void>;
114
+ }
@@ -0,0 +1,13 @@
1
+ import type { Queue } from './queue';
2
+ export declare interface RateLimitResult {
3
+ limited: boolean
4
+ remaining: number
5
+ resetIn: number
6
+ }
7
+ export declare class RateLimiter {
8
+ queue: Queue;
9
+ options: RateLimiterOptions;
10
+ constructor(queue: Queue, options: RateLimiterOptions);
11
+ check(data?: any): Promise<RateLimitResult>;
12
+ checkByKey(key: string): Promise<RateLimitResult>;
13
+ }