Skip to content

Commit 592f4b9

Browse files
committed
docs: add JSDoc documentation to public APIs
1 parent df0688c commit 592f4b9

File tree

8 files changed

+833
-7
lines changed

8 files changed

+833
-7
lines changed

src/contracts/adapter.ts

Lines changed: 94 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,64 @@
11
import type { JobData } from '../types/main.js'
22

3+
/**
4+
* A job that has been acquired by a worker for processing.
5+
* Extends JobData with the timestamp when the job was acquired.
6+
*/
37
export interface AcquiredJob extends JobData {
8+
/** Timestamp (in ms) when the job was acquired by the worker */
49
acquiredAt: number
510
}
611

12+
/**
13+
* Adapter interface for queue storage backends.
14+
*
15+
* Implementations handle job persistence, atomic operations, and
16+
* concurrency control. Built-in adapters: Redis, Knex (PostgreSQL/SQLite).
17+
*
18+
* @example
19+
* ```typescript
20+
* import { redis } from '@boringnode/queue'
21+
*
22+
* const config = {
23+
* default: 'redis',
24+
* adapters: {
25+
* redis: redis({ host: 'localhost', port: 6379 })
26+
* }
27+
* }
28+
* ```
29+
*/
730
export interface Adapter {
831
/**
932
* Set the worker ID for this adapter instance.
1033
* Required before calling pop methods when consuming jobs.
34+
*
35+
* @param workerId - Unique identifier for the worker
1136
*/
1237
setWorkerId(workerId: string): void
1338

1439
/**
1540
* Pop the next available job from the default queue.
16-
* The driver handles locking internally.
41+
* Atomically moves the job from pending to active state.
42+
*
43+
* @returns The acquired job, or null if queue is empty
1744
*/
1845
pop(): Promise<AcquiredJob | null>
1946

2047
/**
2148
* Pop the next available job from a specific queue.
22-
* The driver handles locking internally.
49+
* Atomically moves the job from pending to active state.
50+
*
51+
* @param queue - The queue name to pop from
52+
* @returns The acquired job, or null if queue is empty
2353
*/
2454
popFrom(queue: string): Promise<AcquiredJob | null>
2555

2656
/**
2757
* Recover stalled jobs that have been active for too long.
28-
* Jobs that exceed maxStalledCount will be failed permanently.
58+
* A stalled job is one where the worker stopped responding (e.g., crash).
59+
*
60+
* Jobs within maxStalledCount are moved back to pending.
61+
* Jobs exceeding maxStalledCount are failed permanently.
2962
*
3063
* @param queue - The queue to check for stalled jobs
3164
* @param stalledThreshold - Duration in ms after which a job is considered stalled
@@ -39,26 +72,81 @@ export interface Adapter {
3972
): Promise<number>
4073

4174
/**
42-
* Mark a job as completed and remove it from active set.
75+
* Mark a job as completed and remove it from the queue.
76+
*
77+
* @param jobId - The job ID to complete
78+
* @param queue - The queue the job belongs to
4379
*/
4480
completeJob(jobId: string, queue: string): Promise<void>
4581

4682
/**
47-
* Mark a job as failed permanently.
83+
* Mark a job as failed permanently and remove it from the queue.
84+
*
85+
* @param jobId - The job ID to fail
86+
* @param queue - The queue the job belongs to
87+
* @param error - Optional error that caused the failure
4888
*/
4989
failJob(jobId: string, queue: string, error?: Error): Promise<void>
5090

5191
/**
52-
* Retry a job - move back to pending queue with incremented attempts.
92+
* Retry a job by moving it back to pending with incremented attempts.
93+
*
94+
* @param jobId - The job ID to retry
95+
* @param queue - The queue the job belongs to
96+
* @param retryAt - Optional future date to delay the retry
5397
*/
5498
retryJob(jobId: string, queue: string, retryAt?: Date): Promise<void>
5599

100+
/**
101+
* Push a job to the default queue for immediate processing.
102+
*
103+
* @param jobData - The job data to push
104+
*/
56105
push(jobData: JobData): Promise<void>
106+
107+
/**
108+
* Push a job to a specific queue for immediate processing.
109+
*
110+
* @param queue - The queue name to push to
111+
* @param jobData - The job data to push
112+
*/
57113
pushOn(queue: string, jobData: JobData): Promise<void>
114+
115+
/**
116+
* Push a job to the default queue with a delay.
117+
*
118+
* @param jobData - The job data to push
119+
* @param delay - Delay in milliseconds before the job becomes available
120+
*/
58121
pushLater(jobData: JobData, delay: number): Promise<void>
122+
123+
/**
124+
* Push a job to a specific queue with a delay.
125+
*
126+
* @param queue - The queue name to push to
127+
* @param jobData - The job data to push
128+
* @param delay - Delay in milliseconds before the job becomes available
129+
*/
59130
pushLaterOn(queue: string, jobData: JobData, delay: number): Promise<void>
60131

132+
/**
133+
* Get the number of pending jobs in the default queue.
134+
*
135+
* @returns The number of pending jobs
136+
*/
61137
size(): Promise<number>
138+
139+
/**
140+
* Get the number of pending jobs in a specific queue.
141+
*
142+
* @param queue - The queue name to check
143+
* @returns The number of pending jobs
144+
*/
62145
sizeOf(queue: string): Promise<number>
146+
147+
/**
148+
* Clean up resources (close connections, etc.).
149+
* Called when the worker stops or the adapter is no longer needed.
150+
*/
63151
destroy(): Promise<void>
64152
}

src/job.ts

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,83 @@
11
import { JobDispatcher } from './job_dispatcher.js'
22
import type { JobOptions } from './types/main.js'
33

4+
/**
5+
* Abstract base class for all queue jobs.
6+
*
7+
* Extend this class to create your own jobs. Each job must implement
8+
* the `execute()` method which contains the job's business logic.
9+
*
10+
* @typeParam Payload - The type of data this job receives
11+
*
12+
* @example
13+
* ```typescript
14+
* import { Job } from '@boringnode/queue'
15+
*
16+
* interface SendEmailPayload {
17+
* to: string
18+
* subject: string
19+
* body: string
20+
* }
21+
*
22+
* export default class SendEmailJob extends Job<SendEmailPayload> {
23+
* static options = {
24+
* queue: 'emails',
25+
* maxRetries: 3,
26+
* }
27+
*
28+
* async execute() {
29+
* await sendEmail(this.payload.to, this.payload.subject, this.payload.body)
30+
* }
31+
*
32+
* async failed(error: Error) {
33+
* console.error(`Failed to send email to ${this.payload.to}:`, error)
34+
* }
35+
* }
36+
* ```
37+
*/
438
export abstract class Job<Payload = any> {
539
readonly #payload: Payload
640

41+
/** Static options for this job class (queue, retries, timeout, etc.) */
742
static options: JobOptions = {}
843

44+
/** The payload data passed to this job instance */
945
get payload(): Payload {
1046
return this.#payload
1147
}
1248

49+
/**
50+
* Create a new job instance.
51+
*
52+
* @param payload - The data to be processed by this job
53+
*/
1354
constructor(payload: Payload) {
1455
this.#payload = payload
1556
}
1657

58+
/**
59+
* Dispatch this job to the queue.
60+
*
61+
* Returns a JobDispatcher for fluent configuration before dispatching.
62+
* The job is not actually dispatched until `.run()` is called or the
63+
* dispatcher is awaited.
64+
*
65+
* @param payload - The data to pass to the job
66+
* @returns A JobDispatcher for fluent configuration
67+
*
68+
* @example
69+
* ```typescript
70+
* // Simple dispatch
71+
* await SendEmailJob.dispatch({ to: 'user@example.com', subject: 'Hello' })
72+
*
73+
* // With options
74+
* await SendEmailJob.dispatch({ to: 'user@example.com' })
75+
* .toQueue('high-priority')
76+
* .priority(1)
77+
* .in('5m')
78+
* .run()
79+
* ```
80+
*/
1781
static dispatch<T extends Job>(
1882
this: new (payload: any) => T,
1983
payload: T extends Job<infer P> ? P : never
@@ -38,7 +102,45 @@ export abstract class Job<Payload = any> {
38102
return dispatcher
39103
}
40104

105+
/**
106+
* Execute the job's business logic.
107+
*
108+
* This method is called by the worker when processing the job.
109+
* Implement your job's logic here.
110+
*
111+
* @param signal - Optional AbortSignal for timeout handling.
112+
* Check `signal.aborted` for long-running operations.
113+
* @throws Any error thrown will trigger retry logic (if configured)
114+
*
115+
* @example
116+
* ```typescript
117+
* async execute(signal?: AbortSignal) {
118+
* for (const item of this.payload.items) {
119+
* if (signal?.aborted) {
120+
* throw new Error('Job timed out')
121+
* }
122+
* await processItem(item)
123+
* }
124+
* }
125+
* ```
126+
*/
41127
abstract execute(signal?: AbortSignal): Promise<void>
42128

129+
/**
130+
* Called when the job has permanently failed (after all retries exhausted).
131+
*
132+
* Use this hook for cleanup, logging, or notifications.
133+
* This is optional - implement only if you need failure handling.
134+
*
135+
* @param error - The error that caused the final failure
136+
*
137+
* @example
138+
* ```typescript
139+
* async failed(error: Error) {
140+
* await notifyAdmin(`Job failed: ${error.message}`)
141+
* await cleanup(this.payload)
142+
* }
143+
* ```
144+
*/
43145
failed?(error: Error): Promise<void>
44146
}

0 commit comments

Comments
 (0)