@stacksjs/queue 0.70.23 → 0.70.25
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/dist/index.js +30 -4912
- package/dist/src/action.d.ts +46 -0
- package/dist/src/batch.d.ts +115 -0
- package/dist/src/discovery.d.ts +79 -0
- package/dist/src/events.d.ts +138 -0
- package/dist/src/health.d.ts +85 -0
- package/dist/src/index.d.ts +137 -0
- package/dist/src/job-progress.d.ts +53 -0
- package/dist/src/job.d.ts +116 -0
- package/dist/src/notifications.d.ts +70 -0
- package/dist/src/scheduler.d.ts +52 -0
- package/dist/src/testing.d.ts +74 -0
- package/dist/src/worker.d.ts +26 -0
- package/package.json +19 -7
- package/dist/action.d.ts +0 -25
- package/dist/index.d.ts +0 -3
- package/dist/job.d.ts +0 -199
- package/dist/process.d.ts +0 -24
- package/dist/utils.d.ts +0 -4
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { JobOptions } from '@stacksjs/types';
|
|
2
|
+
/*.ts) and dispatch.
|
|
3
|
+
* Inspired by Laravel's dispatchable jobs.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* // app/Jobs/SendWelcomeEmail.ts
|
|
8
|
+
* export default new Job({
|
|
9
|
+
* name: 'SendWelcomeEmail',
|
|
10
|
+
* queue: 'emails',
|
|
11
|
+
* tries: 3,
|
|
12
|
+
* backoff: [10, 30, 60],
|
|
13
|
+
*
|
|
14
|
+
* async handle(payload: { email: string }) {
|
|
15
|
+
* await sendEmail(payload.email)
|
|
16
|
+
* },
|
|
17
|
+
* })
|
|
18
|
+
*
|
|
19
|
+
* // Dispatching:
|
|
20
|
+
* import SendWelcomeEmail from '~/app/Jobs/SendWelcomeEmail'
|
|
21
|
+
*
|
|
22
|
+
* await SendWelcomeEmail.dispatch({ email: 'user@example.com' })
|
|
23
|
+
* await SendWelcomeEmail.dispatchIf(user.isNew, { email: user.email })
|
|
24
|
+
* await SendWelcomeEmail.dispatchAfter(60, { email: user.email })
|
|
25
|
+
* await SendWelcomeEmail.dispatchNow({ email: user.email })
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare class Job {
|
|
29
|
+
name: JobOptions['name'];
|
|
30
|
+
description: JobOptions['description'];
|
|
31
|
+
action?: JobOptions['action'];
|
|
32
|
+
handle?: JobOptions['handle'];
|
|
33
|
+
queue?: string;
|
|
34
|
+
rate: JobOptions['rate'];
|
|
35
|
+
tries: JobOptions['tries'];
|
|
36
|
+
timeout?: number;
|
|
37
|
+
backoff: JobOptions['backoff'];
|
|
38
|
+
backoffConfig: JobOptions['backoffConfig'];
|
|
39
|
+
enabled: JobOptions['enabled'];
|
|
40
|
+
constructor(options: JobOptions & { queue?: string; timeout?: number });
|
|
41
|
+
dispatch(payload?: any): Promise<void>;
|
|
42
|
+
dispatchIf(condition: boolean, payload?: any): Promise<void>;
|
|
43
|
+
dispatchUnless(condition: boolean, payload?: any): Promise<void>;
|
|
44
|
+
dispatchAfter(delaySeconds: number, payload?: any): Promise<void>;
|
|
45
|
+
dispatchNow(payload?: any): Promise<void>;
|
|
46
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import type { Job } from './action';
|
|
2
|
+
export declare function getBatchCallbacks(batchId: string): BatchOptions | undefined;
|
|
3
|
+
/**
|
|
4
|
+
* Record that a job in a batch completed successfully.
|
|
5
|
+
* Called by the worker after a batch job finishes.
|
|
6
|
+
*
|
|
7
|
+
* Uses an atomic decrement on the database so two concurrent workers
|
|
8
|
+
* finishing batch jobs at the same instant don't both read pending=N
|
|
9
|
+
* and both write pending=N-1 — that race used to leave the counter
|
|
10
|
+
* stuck above zero and the batch's `then`/`finally` callbacks never
|
|
11
|
+
* fired. Falls back to read-modify-write (with a debug log) when the
|
|
12
|
+
* driver doesn't expose atomic SQL.
|
|
13
|
+
*/
|
|
14
|
+
export declare function recordBatchJobCompletion(batchId: string): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Record that a job in a batch failed.
|
|
17
|
+
* Called by the worker when a batch job fails its final attempt.
|
|
18
|
+
*/
|
|
19
|
+
export declare function recordBatchJobFailure(batchId: string, jobId: string, error: Error): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Check if a batch has been cancelled (used by worker to skip jobs)
|
|
22
|
+
*/
|
|
23
|
+
export declare function isBatchCancelled(batchId: string): Promise<boolean>;
|
|
24
|
+
/**
|
|
25
|
+
* A pending job within a batch (job + optional payload)
|
|
26
|
+
*/
|
|
27
|
+
export declare interface BatchableJob {
|
|
28
|
+
job: Job
|
|
29
|
+
payload?: any
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Batch record stored in the database
|
|
33
|
+
*/
|
|
34
|
+
export declare interface BatchRecord {
|
|
35
|
+
id: string
|
|
36
|
+
name: string
|
|
37
|
+
total_jobs: number
|
|
38
|
+
pending_jobs: number
|
|
39
|
+
failed_jobs: number
|
|
40
|
+
failed_job_ids: string
|
|
41
|
+
options: string
|
|
42
|
+
cancelled_at: string | null
|
|
43
|
+
created_at: string
|
|
44
|
+
finished_at: string | null
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Batch options for callbacks and behavior
|
|
48
|
+
*/
|
|
49
|
+
export declare interface BatchOptions {
|
|
50
|
+
name?: string
|
|
51
|
+
queue?: string
|
|
52
|
+
allowFailures?: boolean
|
|
53
|
+
thenCallbacks: Array<(batch: PendingBatch | DispatchedBatch) => Promise<void> | void>
|
|
54
|
+
catchCallbacks: Array<(batch: PendingBatch | DispatchedBatch, error: Error) => Promise<void> | void>
|
|
55
|
+
finallyCallbacks: Array<(batch: PendingBatch | DispatchedBatch) => Promise<void> | void>
|
|
56
|
+
progressCallbacks: Array<(batch: PendingBatch | DispatchedBatch) => Promise<void> | void>
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Batch status
|
|
60
|
+
*/
|
|
61
|
+
export type BatchStatus = 'pending' | 'processing' | 'completed' | 'failed' | 'cancelled';
|
|
62
|
+
/**
|
|
63
|
+
* PendingBatch - a batch that has been configured but not yet dispatched
|
|
64
|
+
*/
|
|
65
|
+
export declare class PendingBatch {
|
|
66
|
+
constructor(jobs: Array<Job | BatchableJob>);
|
|
67
|
+
name(name: string): this;
|
|
68
|
+
onQueue(queue: string): this;
|
|
69
|
+
allowFailures(): this;
|
|
70
|
+
then(callback: (batch: PendingBatch | DispatchedBatch) => Promise<void> | void): this;
|
|
71
|
+
catch(callback: (batch: PendingBatch | DispatchedBatch, error: Error) => Promise<void> | void): this;
|
|
72
|
+
finally(callback: (batch: PendingBatch | DispatchedBatch) => Promise<void> | void): this;
|
|
73
|
+
progress(callback: (batch: PendingBatch | DispatchedBatch) => Promise<void> | void): this;
|
|
74
|
+
dispatch(): Promise<DispatchedBatch>;
|
|
75
|
+
getJobs(): BatchableJob[];
|
|
76
|
+
getOptions(): BatchOptions;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* DispatchedBatch - a batch that has been dispatched and can be inspected
|
|
80
|
+
*/
|
|
81
|
+
export declare class DispatchedBatch {
|
|
82
|
+
readonly id: string;
|
|
83
|
+
constructor(id: string);
|
|
84
|
+
fresh(): Promise<BatchRecord | null>;
|
|
85
|
+
getName(): Promise<string>;
|
|
86
|
+
totalJobs(): Promise<number>;
|
|
87
|
+
pendingJobs(): Promise<number>;
|
|
88
|
+
failedJobs(): Promise<number>;
|
|
89
|
+
completedJobs(): Promise<number>;
|
|
90
|
+
progress(): Promise<number>;
|
|
91
|
+
finished(): Promise<boolean>;
|
|
92
|
+
cancelled(): Promise<boolean>;
|
|
93
|
+
hasFailures(): Promise<boolean>;
|
|
94
|
+
failedJobIds(): Promise<string[]>;
|
|
95
|
+
cancel(): Promise<void>;
|
|
96
|
+
add(jobs: Array<Job | BatchableJob>): Promise<void>;
|
|
97
|
+
delete(): Promise<void>;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Create a new pending batch
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```typescript
|
|
104
|
+
* const batch = Batch.create([job1, job2, job3])
|
|
105
|
+
* .name('My Batch')
|
|
106
|
+
* .then(async (_batch) => console.log('Done!'))
|
|
107
|
+
* .dispatch()
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
export declare class Batch {
|
|
111
|
+
static create(jobs: Array<Job | BatchableJob>): PendingBatch;
|
|
112
|
+
static find(id: string): Promise<DispatchedBatch | null>;
|
|
113
|
+
static all(): Promise<DispatchedBatch[]>;
|
|
114
|
+
static prune(olderThanHours?: number): Promise<number>;
|
|
115
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { JobOptions } from '@stacksjs/types';
|
|
2
|
+
/**
|
|
3
|
+
* Discover jobs from the app/Jobs directory
|
|
4
|
+
*/
|
|
5
|
+
export declare function discoverJobs(jobsPath?: string): Promise<DiscoveredJob[]>;
|
|
6
|
+
/**
|
|
7
|
+
* Get a job by name from the registry
|
|
8
|
+
*/
|
|
9
|
+
export declare function getJob(name: string): DiscoveredJob | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* Get all discovered jobs
|
|
12
|
+
*/
|
|
13
|
+
export declare function getAllJobs(): DiscoveredJob[];
|
|
14
|
+
/**
|
|
15
|
+
* Get scheduled jobs
|
|
16
|
+
*/
|
|
17
|
+
export declare function getScheduledJobs(): DiscoveredJob[];
|
|
18
|
+
/**
|
|
19
|
+
* Execute a job by name
|
|
20
|
+
*/
|
|
21
|
+
export declare function executeJob<T = any>(name: string, payload?: any): Promise<T>;
|
|
22
|
+
/**
|
|
23
|
+
* Convert discovered job config to bun-queue JobOptions
|
|
24
|
+
*/
|
|
25
|
+
export declare function toJobOptions(job: DiscoveredJob): JobOptions;
|
|
26
|
+
// Global job registry
|
|
27
|
+
export declare const jobRegistry: JobRegistry;
|
|
28
|
+
/**
|
|
29
|
+
* Discovered job metadata
|
|
30
|
+
*/
|
|
31
|
+
export declare interface DiscoveredJob {
|
|
32
|
+
name: string
|
|
33
|
+
path: string
|
|
34
|
+
config: JobConfig
|
|
35
|
+
type: 'class' | 'function'
|
|
36
|
+
module: any
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Job configuration from discovery
|
|
40
|
+
*/
|
|
41
|
+
export declare interface JobConfig {
|
|
42
|
+
name?: string
|
|
43
|
+
description?: string
|
|
44
|
+
queue?: string
|
|
45
|
+
tries?: number
|
|
46
|
+
backoff?: number | number[]
|
|
47
|
+
rate?: string
|
|
48
|
+
timeout?: number
|
|
49
|
+
withoutOverlapping?: boolean
|
|
50
|
+
retries?: number
|
|
51
|
+
retryAfter?: number[]
|
|
52
|
+
schedule?: string
|
|
53
|
+
backoffConfig?: {
|
|
54
|
+
strategy?: 'fixed' | 'exponential' | 'linear'
|
|
55
|
+
initialDelay?: number
|
|
56
|
+
factor?: number
|
|
57
|
+
maxDelay?: number
|
|
58
|
+
jitter?: {
|
|
59
|
+
enabled?: boolean
|
|
60
|
+
factor?: number
|
|
61
|
+
minDelay?: number
|
|
62
|
+
maxDelay?: number
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Job registry for managing discovered jobs
|
|
68
|
+
*/
|
|
69
|
+
declare class JobRegistry {
|
|
70
|
+
register(job: DiscoveredJob): void;
|
|
71
|
+
get(name: string): DiscoveredJob | undefined;
|
|
72
|
+
all(): DiscoveredJob[];
|
|
73
|
+
byQueue(queue: string): DiscoveredJob[];
|
|
74
|
+
scheduled(): DiscoveredJob[];
|
|
75
|
+
has(name: string): boolean;
|
|
76
|
+
clear(): void;
|
|
77
|
+
setInitialized(value: boolean): void;
|
|
78
|
+
isInitialized(): boolean;
|
|
79
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get the global queue events instance
|
|
3
|
+
*/
|
|
4
|
+
export declare function getQueueEvents(): QueueEvents;
|
|
5
|
+
/**
|
|
6
|
+
* Subscribe to a queue event
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* // Listen for job completions
|
|
11
|
+
* onQueueEvent('job:completed', (payload) => {
|
|
12
|
+
* console.log(`Job ${payload.jobId} completed!`)
|
|
13
|
+
* })
|
|
14
|
+
*
|
|
15
|
+
* // Listen for all events
|
|
16
|
+
* onQueueEvent('*', (event, payload) => {
|
|
17
|
+
* console.log(`Event: ${event}`, payload)
|
|
18
|
+
* })
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare function onQueueEvent(event: QueueEventType | '*', handler: QueueEventHandler | ((_event: QueueEventType, _payload: QueueEventPayload) => void | Promise<void>)): () => void;
|
|
22
|
+
/**
|
|
23
|
+
* Emit a queue event
|
|
24
|
+
*/
|
|
25
|
+
export declare function emitQueueEvent(event: QueueEventType, payload: Omit<QueueEventPayload, 'timestamp'>): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Event-aware job wrapper
|
|
28
|
+
*
|
|
29
|
+
* Wraps a job handler to automatically emit events
|
|
30
|
+
*/
|
|
31
|
+
export declare function withEvents<T extends (...args: any[]) => Promise<any>>(queueName: string, handler: T): T;
|
|
32
|
+
/**
|
|
33
|
+
* Queue event listener decorator
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```typescript
|
|
37
|
+
* class EmailNotifications {
|
|
38
|
+
* @OnQueueEvent('job:completed')
|
|
39
|
+
* async onJobCompleted(payload: QueueEventPayload) {
|
|
40
|
+
* console.log('Job completed:', payload)
|
|
41
|
+
* }
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare function OnQueueEvent(event: QueueEventType): void;
|
|
46
|
+
/**
|
|
47
|
+
* Get or create the global QueueMetrics instance
|
|
48
|
+
*/
|
|
49
|
+
export declare function getGlobalMetrics(): QueueMetrics;
|
|
50
|
+
export declare function getWorkerTracker(): WorkerTracker;
|
|
51
|
+
/**
|
|
52
|
+
* Queue event payload interface
|
|
53
|
+
*/
|
|
54
|
+
export declare interface QueueEventPayload {
|
|
55
|
+
jobId?: string
|
|
56
|
+
queueName?: string
|
|
57
|
+
jobName?: string
|
|
58
|
+
data?: any
|
|
59
|
+
result?: any
|
|
60
|
+
error?: Error
|
|
61
|
+
progress?: number
|
|
62
|
+
timestamp: number
|
|
63
|
+
attemptsMade?: number
|
|
64
|
+
duration?: number
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Worker status tracker
|
|
68
|
+
*
|
|
69
|
+
* Tracks registered workers and their activity for health checks.
|
|
70
|
+
*/
|
|
71
|
+
export declare interface TrackedWorker {
|
|
72
|
+
id: string
|
|
73
|
+
status: 'active' | 'idle' | 'stopped'
|
|
74
|
+
queue: string
|
|
75
|
+
processedCount: number
|
|
76
|
+
failedCount: number
|
|
77
|
+
lastActivityAt: string
|
|
78
|
+
startedAt: string
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Queue event types
|
|
82
|
+
*/
|
|
83
|
+
export type QueueEventType = | 'job:added'
|
|
84
|
+
| 'job:processing'
|
|
85
|
+
| 'job:completed'
|
|
86
|
+
| 'job:failed'
|
|
87
|
+
| 'job:retrying'
|
|
88
|
+
| 'job:stalled'
|
|
89
|
+
| 'job:progress'
|
|
90
|
+
| 'queue:paused'
|
|
91
|
+
| 'queue:resumed'
|
|
92
|
+
| 'queue:error'
|
|
93
|
+
| 'worker:started'
|
|
94
|
+
| 'worker:stopped'
|
|
95
|
+
| 'batch:added'
|
|
96
|
+
| 'batch:completed'
|
|
97
|
+
| 'batch:failed';
|
|
98
|
+
/**
|
|
99
|
+
* Queue event handler type
|
|
100
|
+
*/
|
|
101
|
+
export type QueueEventHandler = (_payload: QueueEventPayload) => void | Promise<void>;
|
|
102
|
+
/**
|
|
103
|
+
* Queue events emitter
|
|
104
|
+
*/
|
|
105
|
+
export declare class QueueEvents {
|
|
106
|
+
on(event: QueueEventType, handler: QueueEventHandler): () => void;
|
|
107
|
+
onAny(handler: (event: QueueEventType, payload: QueueEventPayload) => void | Promise<void>): () => void;
|
|
108
|
+
once(event: QueueEventType, handler: QueueEventHandler): () => void;
|
|
109
|
+
emit(event: QueueEventType, payload: Omit<QueueEventPayload, 'timestamp'>): Promise<void>;
|
|
110
|
+
off(event: QueueEventType): void;
|
|
111
|
+
removeAllListeners(): void;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Queue metrics based on events
|
|
115
|
+
*/
|
|
116
|
+
export declare class QueueMetrics {
|
|
117
|
+
constructor();
|
|
118
|
+
getThroughputPerMinute(): number;
|
|
119
|
+
getAverageProcessingTime(): number;
|
|
120
|
+
getMetrics(): {
|
|
121
|
+
counts: { added: number; completed: number; failed: number; processing: number }
|
|
122
|
+
averageDuration: number
|
|
123
|
+
recentErrors: Array<{ error: Error; timestamp: number }>
|
|
124
|
+
throughputPerMinute: number
|
|
125
|
+
};
|
|
126
|
+
reset(): void;
|
|
127
|
+
stop(): void;
|
|
128
|
+
}
|
|
129
|
+
declare class WorkerTracker {
|
|
130
|
+
register(id: string, queue: string): void;
|
|
131
|
+
markActive(id: string): void;
|
|
132
|
+
markIdle(id: string): void;
|
|
133
|
+
recordCompletion(id: string): void;
|
|
134
|
+
recordFailure(id: string): void;
|
|
135
|
+
unregister(id: string): void;
|
|
136
|
+
getAll(): TrackedWorker[];
|
|
137
|
+
clear(): void;
|
|
138
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Perform queue health check
|
|
3
|
+
*/
|
|
4
|
+
export declare function checkQueueHealth(config?: HealthCheckConfig): Promise<QueueHealthResult>;
|
|
5
|
+
/**
|
|
6
|
+
* Create a health check HTTP handler
|
|
7
|
+
*/
|
|
8
|
+
export declare function createHealthCheckHandler(config?: HealthCheckConfig): (req: Request) => Promise<Response>;
|
|
9
|
+
/**
|
|
10
|
+
* Quick health check - returns just the status
|
|
11
|
+
*/
|
|
12
|
+
export declare function isQueueHealthy(config?: HealthCheckConfig): Promise<boolean>;
|
|
13
|
+
/**
|
|
14
|
+
* Queue health check result
|
|
15
|
+
*/
|
|
16
|
+
export declare interface QueueHealthResult {
|
|
17
|
+
status: HealthStatus
|
|
18
|
+
timestamp: string
|
|
19
|
+
queues: QueueStatus[]
|
|
20
|
+
workers: WorkerStatus[]
|
|
21
|
+
metrics: QueueMetrics
|
|
22
|
+
alerts: HealthAlert[]
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Individual queue status
|
|
26
|
+
*/
|
|
27
|
+
export declare interface QueueStatus {
|
|
28
|
+
name: string
|
|
29
|
+
status: HealthStatus
|
|
30
|
+
pending: number
|
|
31
|
+
processing: number
|
|
32
|
+
delayed: number
|
|
33
|
+
failed: number
|
|
34
|
+
oldestJobAge?: number
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Worker status
|
|
38
|
+
*/
|
|
39
|
+
export declare interface WorkerStatus {
|
|
40
|
+
id: string
|
|
41
|
+
status: 'active' | 'idle' | 'stopped'
|
|
42
|
+
queue: string
|
|
43
|
+
processedCount: number
|
|
44
|
+
failedCount: number
|
|
45
|
+
lastActivityAt?: string
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Queue metrics summary
|
|
49
|
+
*/
|
|
50
|
+
export declare interface QueueMetrics {
|
|
51
|
+
totalPending: number
|
|
52
|
+
totalProcessing: number
|
|
53
|
+
totalDelayed: number
|
|
54
|
+
totalFailed: number
|
|
55
|
+
throughputPerMinute: number
|
|
56
|
+
averageProcessingTime: number
|
|
57
|
+
errorRate: number
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Health alert
|
|
61
|
+
*/
|
|
62
|
+
export declare interface HealthAlert {
|
|
63
|
+
level: 'warning' | 'critical'
|
|
64
|
+
message: string
|
|
65
|
+
queue?: string
|
|
66
|
+
timestamp: string
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Health check configuration
|
|
70
|
+
*/
|
|
71
|
+
export declare interface HealthCheckConfig {
|
|
72
|
+
maxPendingWarning?: number
|
|
73
|
+
maxPendingCritical?: number
|
|
74
|
+
maxFailedWarning?: number
|
|
75
|
+
maxFailedCritical?: number
|
|
76
|
+
maxJobAgeWarning?: number
|
|
77
|
+
maxJobAgeCritical?: number
|
|
78
|
+
maxErrorRateWarning?: number
|
|
79
|
+
maxErrorRateCritical?: number
|
|
80
|
+
queues?: string[]
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Health status
|
|
84
|
+
*/
|
|
85
|
+
export type HealthStatus = 'healthy' | 'degraded' | 'unhealthy';
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
// =============================================================================
|
|
2
|
+
// Redis queue driver
|
|
3
|
+
// =============================================================================
|
|
4
|
+
// Redis driver is lazily loaded to avoid requiring bun-queue when not using Redis.
|
|
5
|
+
// Use: const { RedisQueue } = await import('@stacksjs/queue/drivers/redis')
|
|
6
|
+
// Or access via the queue manager which dynamically imports the driver.
|
|
7
|
+
export declare function getRedisQueue(): Promise<void>;
|
|
8
|
+
/**
|
|
9
|
+
* @stacksjs/queue
|
|
10
|
+
*
|
|
11
|
+
* A thin wrapper around bun-queue that integrates with Stacks conventions.
|
|
12
|
+
* Core Stacks queue exports are always available. For advanced bun-queue
|
|
13
|
+
* features (Queue, Worker, dispatch, etc.), import from '@stacksjs/queue/bun-queue'.
|
|
14
|
+
*/
|
|
15
|
+
// =============================================================================
|
|
16
|
+
// Stacks Job class for file-based jobs (app/Jobs/*.ts)
|
|
17
|
+
// =============================================================================
|
|
18
|
+
export { Job } from './action';
|
|
19
|
+
// =============================================================================
|
|
20
|
+
// Stacks job helper for dispatching file-based jobs
|
|
21
|
+
// =============================================================================
|
|
22
|
+
export { Jobs, job, jobBatch, runJob } from './job';
|
|
23
|
+
// =============================================================================
|
|
24
|
+
// Per-job progress + cancellation (cache-backed; safe across processes)
|
|
25
|
+
// =============================================================================
|
|
26
|
+
export { setJobProgress, getJobProgress, cancelJob, isJobCancelled, clearJobState } from './job-progress';
|
|
27
|
+
// =============================================================================
|
|
28
|
+
// Job discovery (for app/Jobs directory)
|
|
29
|
+
// =============================================================================
|
|
30
|
+
export {
|
|
31
|
+
discoverJobs,
|
|
32
|
+
executeJob,
|
|
33
|
+
getAllJobs,
|
|
34
|
+
getJob,
|
|
35
|
+
getScheduledJobs,
|
|
36
|
+
jobRegistry,
|
|
37
|
+
toJobOptions,
|
|
38
|
+
type DiscoveredJob,
|
|
39
|
+
type JobConfig,
|
|
40
|
+
} from './discovery';
|
|
41
|
+
// =============================================================================
|
|
42
|
+
// Stacks scheduler (integrates with job discovery)
|
|
43
|
+
// =============================================================================
|
|
44
|
+
export {
|
|
45
|
+
getRegisteredJobs,
|
|
46
|
+
getSchedulerStatus,
|
|
47
|
+
isSchedulerRunning,
|
|
48
|
+
startScheduler,
|
|
49
|
+
stopScheduler,
|
|
50
|
+
triggerJob,
|
|
51
|
+
} from './scheduler';
|
|
52
|
+
// =============================================================================
|
|
53
|
+
// Stacks queue events (integrates with Stacks logging)
|
|
54
|
+
// =============================================================================
|
|
55
|
+
export {
|
|
56
|
+
emitQueueEvent,
|
|
57
|
+
getGlobalMetrics,
|
|
58
|
+
getQueueEvents,
|
|
59
|
+
getWorkerTracker,
|
|
60
|
+
onQueueEvent,
|
|
61
|
+
OnQueueEvent,
|
|
62
|
+
QueueEvents,
|
|
63
|
+
QueueMetrics,
|
|
64
|
+
withEvents,
|
|
65
|
+
type QueueEventHandler,
|
|
66
|
+
type QueueEventPayload,
|
|
67
|
+
type QueueEventType,
|
|
68
|
+
type TrackedWorker,
|
|
69
|
+
} from './events';
|
|
70
|
+
// =============================================================================
|
|
71
|
+
// Health checks
|
|
72
|
+
// =============================================================================
|
|
73
|
+
export {
|
|
74
|
+
checkQueueHealth,
|
|
75
|
+
createHealthCheckHandler,
|
|
76
|
+
isQueueHealthy,
|
|
77
|
+
type HealthAlert,
|
|
78
|
+
type HealthCheckConfig,
|
|
79
|
+
type HealthStatus,
|
|
80
|
+
type QueueHealthResult,
|
|
81
|
+
type QueueMetrics as HealthQueueMetrics,
|
|
82
|
+
type QueueStatus,
|
|
83
|
+
type WorkerStatus,
|
|
84
|
+
} from './health';
|
|
85
|
+
// =============================================================================
|
|
86
|
+
// Failed job notifications
|
|
87
|
+
// =============================================================================
|
|
88
|
+
export {
|
|
89
|
+
configureFailedJobNotifications,
|
|
90
|
+
FailedJobNotifier,
|
|
91
|
+
getFailedJobNotifier,
|
|
92
|
+
notifyJobFailed,
|
|
93
|
+
type FailedJobInfo,
|
|
94
|
+
type FailedJobNotificationConfig,
|
|
95
|
+
type NotificationChannel,
|
|
96
|
+
} from './notifications';
|
|
97
|
+
// =============================================================================
|
|
98
|
+
// Testing utilities
|
|
99
|
+
// =============================================================================
|
|
100
|
+
export {
|
|
101
|
+
createQueueTester,
|
|
102
|
+
expectJobToFail,
|
|
103
|
+
fake,
|
|
104
|
+
getFakeQueue,
|
|
105
|
+
isFaked,
|
|
106
|
+
QueueTester,
|
|
107
|
+
restore,
|
|
108
|
+
runJob as runTestJob,
|
|
109
|
+
type DispatchedJob,
|
|
110
|
+
} from './testing';
|
|
111
|
+
// =============================================================================
|
|
112
|
+
// Job batches
|
|
113
|
+
// =============================================================================
|
|
114
|
+
export {
|
|
115
|
+
Batch,
|
|
116
|
+
DispatchedBatch,
|
|
117
|
+
PendingBatch,
|
|
118
|
+
getBatchCallbacks,
|
|
119
|
+
isBatchCancelled,
|
|
120
|
+
recordBatchJobCompletion,
|
|
121
|
+
recordBatchJobFailure,
|
|
122
|
+
type BatchableJob,
|
|
123
|
+
type BatchOptions,
|
|
124
|
+
type BatchRecord,
|
|
125
|
+
type BatchStatus,
|
|
126
|
+
} from './batch';
|
|
127
|
+
// =============================================================================
|
|
128
|
+
// Worker functions (for queue:work command)
|
|
129
|
+
// =============================================================================
|
|
130
|
+
export {
|
|
131
|
+
executeFailedJobs,
|
|
132
|
+
getActiveJobCount,
|
|
133
|
+
isWorkerRunning,
|
|
134
|
+
retryFailedJob,
|
|
135
|
+
startProcessor,
|
|
136
|
+
stopProcessor,
|
|
137
|
+
} from './worker';
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Update the progress of the running job. Workers call this from
|
|
3
|
+
* inside their handler; the UI polls `getJobProgress(id)` to render
|
|
4
|
+
* a progress bar.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* await job.progress(0.5, 'Halfway there')
|
|
9
|
+
* // … later
|
|
10
|
+
* await job.progress(1.0, 'Done')
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export declare function setJobProgress(jobId: string, percent: number, message?: string): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Read the current progress of a job, or `null` if no progress has
|
|
16
|
+
* been recorded yet (job hasn't started, or the entry expired).
|
|
17
|
+
*/
|
|
18
|
+
export declare function getJobProgress(jobId: string): Promise<JobProgress | null>;
|
|
19
|
+
/**
|
|
20
|
+
* Mark a job as cancelled. The next time the worker calls
|
|
21
|
+
* `isJobCancelled(id)` it will see the flag and can stop cleanly. The
|
|
22
|
+
* worker is responsible for checking — the framework can't preempt a
|
|
23
|
+
* running handler safely.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* // From an admin endpoint:
|
|
28
|
+
* await cancelJob(req.params.id)
|
|
29
|
+
*
|
|
30
|
+
* // Inside the worker:
|
|
31
|
+
* if (await isJobCancelled(job.id)) return
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare function cancelJob(jobId: string): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Check whether the named job has been cancelled. Workers should call
|
|
37
|
+
* this between unit-of-work iterations so cancellations are honored
|
|
38
|
+
* promptly without preempting in-flight work.
|
|
39
|
+
*/
|
|
40
|
+
export declare function isJobCancelled(jobId: string): Promise<boolean>;
|
|
41
|
+
/**
|
|
42
|
+
* Clear progress + cancellation state for a finished job. Workers
|
|
43
|
+
* should call this on completion (success or failure) so admin UIs
|
|
44
|
+
* showing "in-flight jobs" don't keep finished entries forever.
|
|
45
|
+
*
|
|
46
|
+
* No-op if no entries exist for the id — safe to call always.
|
|
47
|
+
*/
|
|
48
|
+
export declare function clearJobState(jobId: string): Promise<void>;
|
|
49
|
+
declare interface JobProgress {
|
|
50
|
+
percent: number
|
|
51
|
+
message?: string
|
|
52
|
+
updatedAt: number
|
|
53
|
+
}
|