Skip to content

Commit ef3e218

Browse files
committed
refactor!: replace static jobName with options.name
1 parent e1bc7b5 commit ef3e218

File tree

10 files changed

+64
-48
lines changed

10 files changed

+64
-48
lines changed

README.md

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,13 @@ Create a job by extending the `Job` class:
3939

4040
```typescript
4141
import { Job } from '@boringnode/queue'
42-
import type { JobContext, JobOptions } from '@boringnode/queue/types'
42+
import type { JobOptions } from '@boringnode/queue/types'
4343

4444
interface SendEmailPayload {
4545
to: string
4646
}
4747

4848
export default class SendEmailJob extends Job<SendEmailPayload> {
49-
static readonly jobName = 'SendEmailJob'
50-
5149
static options: JobOptions = {
5250
queue: 'email',
5351
}
@@ -58,6 +56,10 @@ export default class SendEmailJob extends Job<SendEmailPayload> {
5856
}
5957
```
6058

59+
> **Note**: The job name defaults to the class name (`SendEmailJob`). You can override it with `name: 'CustomName'` in options if needed.
60+
>
61+
> **Warning**: If you minify your code in production, class names may be mangled. In that case, always specify `name` explicitly in your job options.
62+
6163
### 2. Configure the Queue Manager
6264

6365
```typescript
@@ -250,8 +252,6 @@ Jobs with lower priority numbers are processed first:
250252

251253
```typescript
252254
export default class UrgentJob extends Job<Payload> {
253-
static readonly jobName = 'UrgentJob'
254-
255255
static options: JobOptions = {
256256
priority: 1, // Processed before default priority (5)
257257
}
@@ -270,8 +270,6 @@ Configure automatic retries with backoff strategies:
270270
import { exponentialBackoff, linearBackoff, fixedBackoff } from '@boringnode/queue'
271271

272272
export default class ReliableJob extends Job<Payload> {
273-
static readonly jobName = 'ReliableJob'
274-
275273
static options: JobOptions = {
276274
maxRetries: 5,
277275
retry: {
@@ -303,8 +301,6 @@ Set a maximum execution time for jobs:
303301

304302
```typescript
305303
export default class LimitedJob extends Job<Payload> {
306-
static readonly jobName = 'LimitedJob'
307-
308304
static options: JobOptions = {
309305
timeout: '30s', // Maximum execution time
310306
failOnTimeout: false, // Retry on timeout (default)
@@ -332,8 +328,6 @@ Jobs have access to an abort signal via `this.signal` to handle timeouts gracefu
332328

333329
```typescript
334330
export default class LongRunningJob extends Job<Payload> {
335-
static readonly jobName = 'LongRunningJob'
336-
337331
static options: JobOptions = {
338332
timeout: '30s',
339333
}
@@ -418,8 +412,6 @@ interface SendEmailPayload {
418412
}
419413

420414
export default class SendEmailJob extends Job<SendEmailPayload> {
421-
static readonly jobName = 'SendEmailJob'
422-
423415
constructor(
424416
private mailer: MailerService, // Injected by IoC container
425417
private logger: Logger // Injected by IoC container
@@ -540,10 +532,11 @@ const config = {
540532
Jobs must:
541533

542534
- Extend the `Job` class
543-
- Have a static `jobName` property
544535
- Implement the `execute` method
545536
- Be exported as default
546537

538+
The job name is automatically derived from the class name, or can be explicitly set via `static options = { name: 'CustomName' }`.
539+
547540
## Logging
548541

549542
You can pass a logger to the queue manager for debugging or monitoring. The logger must be compatible with the [pino](https://github.com/pinojs/pino) interface.

examples/jobs/metrics_job.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ interface MetricsJobPayload {
1717
* ```
1818
*/
1919
export default class MetricsJob extends Job<MetricsJobPayload> {
20-
static readonly jobName = 'MetricsJob'
21-
2220
static options: JobOptions = {
2321
queue: 'metrics',
2422
}

examples/jobs/send_email_job.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ interface SendEmailPayload {
66
}
77

88
export default class SendEmailJob extends Job<SendEmailPayload> {
9-
static readonly jobName = 'SendEmailJob'
10-
119
static options: JobOptions = {
1210
queue: 'email',
1311
}

examples/jobs/sync_job.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ interface SyncJobPayload {
77
}
88

99
export default class SyncJob extends Job<SyncJobPayload> {
10-
static readonly jobName = 'SyncJob'
11-
1210
static options: JobOptions = {
1311
adapter: 'sync',
1412
}

src/job.ts

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -173,21 +173,21 @@ export abstract class Job<Payload = any> {
173173
this: new (...args: any[]) => T,
174174
payload: T extends Job<infer P> ? P : never
175175
): JobDispatcher<T extends Job<infer P> ? P : never> {
176-
const dispatcher = new JobDispatcher<T extends Job<infer P> ? P : never>(
177-
(this as any).jobName,
178-
payload
179-
)
176+
const options = (this as any).options || {}
177+
const jobName = options.name || this.name
180178

181-
if ((this as any).options.queue) {
182-
dispatcher.toQueue((this as any).options.queue)
179+
const dispatcher = new JobDispatcher<T extends Job<infer P> ? P : never>(jobName, payload)
180+
181+
if (options.queue) {
182+
dispatcher.toQueue(options.queue)
183183
}
184184

185-
if ((this as any).options.adapter) {
186-
dispatcher.with((this as any).options.adapter)
185+
if (options.adapter) {
186+
dispatcher.with(options.adapter)
187187
}
188188

189-
if ((this as any).options.priority !== undefined) {
190-
dispatcher.priority((this as any).options.priority)
189+
if (options.priority !== undefined) {
190+
dispatcher.priority(options.priority)
191191
}
192192

193193
return dispatcher
@@ -222,7 +222,10 @@ export abstract class Job<Payload = any> {
222222
this: new (...args: any[]) => T,
223223
payload: T extends Job<infer P> ? P : never
224224
): ScheduleBuilder {
225-
return new ScheduleBuilder((this as any).jobName, payload)
225+
const options = (this as any).options || {}
226+
const jobName = options.name || this.name
227+
228+
return new ScheduleBuilder(jobName, payload)
226229
}
227230

228231
/**

src/locator.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,9 @@ class LocatorSingleton {
8080
const module = await import(`file://${absolutePath}`)
8181
const JobClass = module.default as JobClass
8282

83-
if (JobClass && typeof JobClass === 'function' && JobClass.name) {
84-
this.register(JobClass.name, JobClass)
83+
if (JobClass && typeof JobClass === 'function') {
84+
const jobName = JobClass.options?.name || JobClass.name
85+
this.register(jobName, JobClass)
8586
registered++
8687
}
8788
} catch (error) {

src/types/main.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ export interface JobData {
8888
* ```typescript
8989
* class SendEmailJob extends Job<EmailPayload> {
9090
* static options: JobOptions = {
91+
* name: 'SendEmailJob',
9192
* queue: 'emails',
9293
* maxRetries: 3,
9394
* timeout: '30s',
@@ -96,6 +97,15 @@ export interface JobData {
9697
* ```
9798
*/
9899
export interface JobOptions {
100+
/**
101+
* Unique name for this job class.
102+
*
103+
* Used to identify the job when dispatching and processing.
104+
*
105+
* @default constructor.name
106+
*/
107+
name?: string
108+
99109
/**
100110
* Queue name for this job.
101111
*

tests/_utils/register_worker_concurrency_suite.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ export function registerWorkerConcurrencyTestSuite(options: WorkerConcurrencyTes
2121
const jobExecutions: Map<string, number> = new Map()
2222

2323
class TrackingJob extends Job<{ jobId: string }> {
24-
static jobName = 'TrackingJob'
25-
2624
async execute() {
2725
const count = jobExecutions.get(this.payload.jobId) || 0
2826
jobExecutions.set(this.payload.jobId, count + 1)
@@ -31,7 +29,7 @@ export function registerWorkerConcurrencyTestSuite(options: WorkerConcurrencyTes
3129
}
3230

3331
const adapter = await options.createAdapter()
34-
Locator.register('TrackingJob', TrackingJob)
32+
Locator.register(TrackingJob.name, TrackingJob)
3533

3634
cleanup(() => Locator.clear())
3735

@@ -78,8 +76,6 @@ export function registerWorkerConcurrencyTestSuite(options: WorkerConcurrencyTes
7876
const jobExecutions: Map<string, number> = new Map()
7977

8078
class TrackingJob extends Job<{ jobId: string }> {
81-
static jobName = 'TrackingJob'
82-
8379
async execute() {
8480
const count = jobExecutions.get(this.payload.jobId) || 0
8581
jobExecutions.set(this.payload.jobId, count + 1)
@@ -88,7 +84,7 @@ export function registerWorkerConcurrencyTestSuite(options: WorkerConcurrencyTes
8884
}
8985

9086
const adapter = await options.createAdapter()
91-
Locator.register('TrackingJob', TrackingJob)
87+
Locator.register(TrackingJob.name, TrackingJob)
9288

9389
cleanup(() => Locator.clear())
9490

@@ -137,8 +133,6 @@ export function registerWorkerConcurrencyTestSuite(options: WorkerConcurrencyTes
137133
const executionOrder: string[] = []
138134

139135
class TrackingJob extends Job<{ jobId: string }> {
140-
static jobName = 'TrackingJob'
141-
142136
async execute() {
143137
executionOrder.push(this.payload.jobId)
144138
const count = jobExecutions.get(this.payload.jobId) || 0
@@ -149,7 +143,7 @@ export function registerWorkerConcurrencyTestSuite(options: WorkerConcurrencyTes
149143
}
150144

151145
const adapter = await options.createAdapter()
152-
Locator.register('TrackingJob', TrackingJob)
146+
Locator.register(TrackingJob.name, TrackingJob)
153147

154148
cleanup(() => Locator.clear())
155149

tests/locator.spec.ts

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ import * as errors from '../src/exceptions.js'
55
import SendEmailJob from '../examples/jobs/send_email_job.js'
66

77
class TestJob extends Job<{ message: string }> {
8-
static jobName = 'TestJob'
9-
108
execute(): Promise<void> {
119
return Promise.resolve()
1210
}
@@ -17,8 +15,6 @@ class TestJob extends Job<{ message: string }> {
1715
}
1816

1917
class AnotherTestJob extends Job<{ value: number }> {
20-
static jobName = 'AnotherTestJob'
21-
2218
execute(): Promise<void> {
2319
return Promise.resolve()
2420
}
@@ -28,6 +24,16 @@ class AnotherTestJob extends Job<{ value: number }> {
2824
}
2925
}
3026

27+
class JobWithCustomName extends Job<{ data: string }> {
28+
static options = {
29+
name: 'CustomNamedJob',
30+
}
31+
32+
execute(): Promise<void> {
33+
return Promise.resolve()
34+
}
35+
}
36+
3137
test.group('Locator', (group) => {
3238
group.each.setup(() => {
3339
Locator.clear()
@@ -97,4 +103,20 @@ test.group('Locator', (group) => {
97103
assert.equal(error.message, 'Requested job "NonExistentJob" is not registered')
98104
}
99105
})
106+
107+
test('should use constructor.name as default job name when registering from glob', async ({
108+
assert,
109+
}) => {
110+
await Locator.registerFromGlob(['./examples/jobs/*.ts'])
111+
112+
// SendEmailJob has no options.name, so it should use the class name
113+
assert.equal(Locator.get('SendEmailJob'), SendEmailJob)
114+
})
115+
116+
test('should use options.name when provided', async ({ assert }) => {
117+
Locator.register(JobWithCustomName.options.name!, JobWithCustomName)
118+
119+
assert.equal(Locator.get('CustomNamedJob'), JobWithCustomName)
120+
assert.isUndefined(Locator.get('JobWithCustomName'))
121+
})
100122
})

tests/schedule.spec.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -386,15 +386,14 @@ test.group('Schedule', (group) => {
386386

387387
test.group('Job.schedule()', (group) => {
388388
class TestScheduleJob extends Job<{ value: string }> {
389-
static readonly jobName = 'TestScheduleJob'
390389
async execute() {}
391390
}
392391

393392
group.each.setup(async () => {
394393
const sharedAdapter = memory()()
395394

396395
// Register the job
397-
Locator.register('TestScheduleJob', TestScheduleJob)
396+
Locator.register(TestScheduleJob.name, TestScheduleJob)
398397

399398
await QueueManager.init({
400399
default: 'memory',

0 commit comments

Comments
 (0)