@igniter-js/jobs 0.1.0 → 0.1.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.
- package/AGENTS.md +115 -541
- package/CHANGELOG.md +5 -0
- package/README.md +118 -356
- package/dist/adapter-PiDCQWQd.d.mts +529 -0
- package/dist/adapter-PiDCQWQd.d.ts +529 -0
- package/dist/adapters/bullmq.adapter.d.mts +55 -110
- package/dist/adapters/bullmq.adapter.d.ts +55 -110
- package/dist/adapters/bullmq.adapter.js +431 -529
- package/dist/adapters/bullmq.adapter.js.map +1 -1
- package/dist/adapters/bullmq.adapter.mjs +431 -529
- package/dist/adapters/bullmq.adapter.mjs.map +1 -1
- package/dist/adapters/index.d.mts +3 -3
- package/dist/adapters/index.d.ts +3 -3
- package/dist/adapters/index.js +889 -960
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/index.mjs +888 -959
- package/dist/adapters/index.mjs.map +1 -1
- package/dist/adapters/memory.adapter.d.mts +52 -98
- package/dist/adapters/memory.adapter.d.ts +52 -98
- package/dist/adapters/memory.adapter.js +471 -473
- package/dist/adapters/memory.adapter.js.map +1 -1
- package/dist/adapters/memory.adapter.mjs +471 -473
- package/dist/adapters/memory.adapter.mjs.map +1 -1
- package/dist/index.d.mts +485 -958
- package/dist/index.d.ts +485 -958
- package/dist/index.js +2053 -917
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2051 -917
- package/dist/index.mjs.map +1 -1
- package/package.json +34 -16
- package/dist/adapter-CcQCatSa.d.mts +0 -1411
- package/dist/adapter-CcQCatSa.d.ts +0 -1411
package/AGENTS.md
CHANGED
|
@@ -1,557 +1,131 @@
|
|
|
1
|
-
# @igniter-js/jobs
|
|
1
|
+
# AGENTS.md - @igniter-js/jobs
|
|
2
2
|
|
|
3
|
-
> **Last Updated:** 2025-
|
|
4
|
-
> **Version:** 0.1
|
|
3
|
+
> **Last Updated:** 2025-12-15
|
|
4
|
+
> **Version:** 0.0.1 (bootstrap)
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
This file is the operations manual for AI agents maintaining `@igniter-js/jobs`. Follow these instructions before changing any code.
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
## 1. Purpose
|
|
9
9
|
|
|
10
|
-
`@igniter-js/jobs`
|
|
10
|
+
`@igniter-js/jobs` delivers a fluent builder API for background jobs, workers, and queue management. It mirrors the DX of `@igniter-js/store` and `@igniter-js/telemetry`, wraps adapter implementations (BullMQ first, memory for tests), and exposes typed events, scopes, and management APIs.
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
| Concept | Description |
|
|
15
|
-
|---------|-------------|
|
|
16
|
-
| **Queue** | Named container for jobs (e.g., `email`, `notifications`) |
|
|
17
|
-
| **Job** | Unit of work with typed payload and handler |
|
|
18
|
-
| **Cron Job** | Scheduled job with pattern or interval |
|
|
19
|
-
| **Worker** | Process that executes jobs from queues |
|
|
20
|
-
| **Scope** | Multi-tenant context (e.g., organization, workspace) |
|
|
21
|
-
| **Actor** | Entity that triggered the job (e.g., user, system) |
|
|
22
|
-
| **Adapter** | Implementation for queue backend (BullMQ, Memory) |
|
|
23
|
-
|
|
24
|
-
### Package Exports
|
|
25
|
-
|
|
26
|
-
```typescript
|
|
27
|
-
// Main entry point
|
|
28
|
-
import { IgniterJobs, IgniterQueue, IgniterJobsError } from '@igniter-js/jobs'
|
|
29
|
-
|
|
30
|
-
// Adapters
|
|
31
|
-
import { BullMQAdapter, MemoryAdapter } from '@igniter-js/jobs/adapters'
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
---
|
|
35
|
-
|
|
36
|
-
## 2. Architecture
|
|
37
|
-
|
|
38
|
-
### File Structure
|
|
12
|
+
## 2. Directory Map
|
|
39
13
|
|
|
40
14
|
```
|
|
41
15
|
packages/jobs/
|
|
42
16
|
├── src/
|
|
43
|
-
│ ├──
|
|
44
|
-
│ ├──
|
|
45
|
-
│
|
|
46
|
-
│
|
|
47
|
-
│
|
|
48
|
-
│
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
│ │ ├── config.ts # Builder state types
|
|
52
|
-
│ │ └── worker.ts # Worker types
|
|
53
|
-
│ ├── errors/
|
|
54
|
-
│ │ ├── index.ts # Error exports
|
|
55
|
-
│ │ └── igniter-jobs.error.ts # Error class and codes
|
|
56
|
-
│ ├── builders/
|
|
57
|
-
│ │ ├── index.ts # Builder exports
|
|
58
|
-
│ │ ├── igniter-queue.builder.ts # Queue builder
|
|
59
|
-
│ │ ├── igniter-jobs.builder.ts # Jobs builder
|
|
60
|
-
│ │ └── igniter-worker.builder.ts # Worker builder
|
|
61
|
-
│ ├── core/
|
|
62
|
-
│ │ ├── index.ts # Core exports
|
|
63
|
-
│ │ └── igniter-jobs.ts # Runtime class
|
|
64
|
-
│ └── adapters/
|
|
65
|
-
│ ├── index.ts # Adapter exports
|
|
66
|
-
│ ├── bullmq.adapter.ts # BullMQ implementation
|
|
67
|
-
│ └── memory.adapter.ts # Memory implementation
|
|
68
|
-
├── tests/
|
|
69
|
-
│ ├── igniter-queue.builder.test.ts
|
|
70
|
-
│ ├── igniter-jobs.builder.test.ts
|
|
71
|
-
│ ├── igniter-jobs.runtime.test.ts
|
|
72
|
-
│ └── memory.adapter.test.ts
|
|
73
|
-
├── package.json
|
|
74
|
-
├── tsconfig.json
|
|
75
|
-
├── tsup.config.ts
|
|
76
|
-
├── vitest.config.ts
|
|
77
|
-
├── README.md
|
|
78
|
-
└── AGENTS.md # This file
|
|
79
|
-
```
|
|
17
|
+
│ ├── adapters/ # Adapter implementations + barrel
|
|
18
|
+
│ ├── builders/ # Fluent builders (jobs, queue, worker)
|
|
19
|
+
│ ├── core/ # Runtime classes & proxies
|
|
20
|
+
│ ├── errors/ # IgniterJobsError hierarchy
|
|
21
|
+
│ ├── types/ # Public type surface (adapter/config/events/queue/worker)
|
|
22
|
+
│ └── utils/ # Static utility classes (id/prefix helpers)
|
|
23
|
+
├── AGENTS.md
|
|
24
|
+
# AGENTS.md - @igniter-js/jobs
|
|
80
25
|
|
|
81
|
-
|
|
26
|
+
> **Last Updated:** 2025-12-16
|
|
27
|
+
> **Version:** 0.0.1 (bootstrap)
|
|
82
28
|
|
|
83
|
-
|
|
84
|
-
1. IgniterQueue.create('name')
|
|
85
|
-
└─► addJob() / addCron()
|
|
86
|
-
└─► build() → IgniterQueueBuiltConfig
|
|
87
|
-
|
|
88
|
-
2. IgniterJobs.create()
|
|
89
|
-
└─► withAdapter()
|
|
90
|
-
└─► addQueue()
|
|
91
|
-
└─► addScope() / addActor()
|
|
92
|
-
└─► withDefaults()
|
|
93
|
-
└─► build() → IgniterJobsRuntime (with Proxy)
|
|
29
|
+
Operations manual for AI agents maintaining `@igniter-js/jobs`. Read this before changing code.
|
|
94
30
|
|
|
95
|
-
|
|
96
|
-
└─► Proxy intercepts access
|
|
97
|
-
└─► Returns typed dispatch function
|
|
98
|
-
```
|
|
31
|
+
## 1. Mission & Scope
|
|
99
32
|
|
|
100
|
-
|
|
33
|
+
`@igniter-js/jobs` provides a fluent, type-safe API for defining queues, jobs, workers, and scheduling. It mirrors `@igniter-js/store` and `@igniter-js/telemetry` patterns, wraps adapters (BullMQ primary, memory for tests), and emits typed telemetry for observability. Scope includes: builders, runtime, adapters, telemetry glue, and docs/tests for everything public.
|
|
101
34
|
|
|
102
|
-
|
|
35
|
+
## 2. Directory Map & Responsibilities
|
|
103
36
|
|
|
104
|
-
```typescript
|
|
105
|
-
// How it works internally:
|
|
106
|
-
jobs.email.sendWelcome.dispatch(data)
|
|
107
|
-
│ │ │
|
|
108
|
-
│ │ └── Job proxy with dispatch/schedule methods
|
|
109
|
-
│ └── Queue proxy returning job proxies
|
|
110
|
-
└── Root proxy returning queue proxies
|
|
111
37
|
```
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
**
|
|
145
|
-
- `
|
|
146
|
-
-
|
|
147
|
-
- `
|
|
148
|
-
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
-
|
|
153
|
-
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
**
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
- `
|
|
163
|
-
- `
|
|
164
|
-
- `
|
|
165
|
-
- `
|
|
166
|
-
- `
|
|
167
|
-
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
**
|
|
178
|
-
-
|
|
179
|
-
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
// Dispatch Options
|
|
208
|
-
interface DispatchOptions {
|
|
209
|
-
delay?: number
|
|
210
|
-
priority?: number
|
|
211
|
-
attempts?: number
|
|
212
|
-
backoff?: IgniterJobBackoff
|
|
213
|
-
jobId?: string
|
|
214
|
-
scope?: { type: string; id: string }
|
|
215
|
-
actor?: { type: string; id: string }
|
|
216
|
-
}
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
### Type Inference Chain
|
|
220
|
-
|
|
221
|
-
```typescript
|
|
222
|
-
// 1. Define schema
|
|
223
|
-
const schema = z.object({ email: z.string() })
|
|
224
|
-
// Type: z.ZodObject<{ email: z.ZodString }>
|
|
225
|
-
|
|
226
|
-
// 2. Schema infers handler data type
|
|
227
|
-
handler: async ({ data }) => { ... }
|
|
228
|
-
// data type: { email: string }
|
|
229
|
-
|
|
230
|
-
// 3. Queue builder accumulates job types
|
|
231
|
-
.addJob('sendWelcome', { schema, handler })
|
|
232
|
-
// Jobs type: { sendWelcome: { data: { email: string } } }
|
|
233
|
-
|
|
234
|
-
// 4. Runtime proxy provides typed dispatch
|
|
235
|
-
jobs.email.sendWelcome.dispatch({ email: 'x' })
|
|
236
|
-
// Argument type: { email: string }
|
|
237
|
-
```
|
|
238
|
-
|
|
239
|
-
---
|
|
240
|
-
|
|
241
|
-
## 5. Error Handling
|
|
242
|
-
|
|
243
|
-
### Error Codes
|
|
244
|
-
|
|
245
|
-
**Configuration Errors:**
|
|
246
|
-
- `JOBS_MISSING_ADAPTER` - No adapter provided
|
|
247
|
-
- `JOBS_INVALID_QUEUE_NAME` - Invalid queue name
|
|
248
|
-
- `JOBS_INVALID_JOB_NAME` - Invalid job name
|
|
249
|
-
- `JOBS_DUPLICATE_QUEUE` - Queue already registered
|
|
250
|
-
- `JOBS_DUPLICATE_JOB` - Job already registered
|
|
251
|
-
|
|
252
|
-
**Queue Errors:**
|
|
253
|
-
- `JOBS_QUEUE_NOT_FOUND` - Queue doesn't exist
|
|
254
|
-
- `JOBS_QUEUE_PAUSED` - Queue is paused
|
|
255
|
-
- `JOBS_QUEUE_FAILED_TO_PAUSE` - Pause operation failed
|
|
256
|
-
|
|
257
|
-
**Job Errors:**
|
|
258
|
-
- `JOBS_JOB_NOT_FOUND` - Job doesn't exist
|
|
259
|
-
- `JOBS_JOB_VALIDATION_FAILED` - Payload validation failed
|
|
260
|
-
- `JOBS_JOB_HANDLER_FAILED` - Handler threw error
|
|
261
|
-
- `JOBS_JOB_TIMEOUT` - Job exceeded timeout
|
|
262
|
-
|
|
263
|
-
**Dispatch Errors:**
|
|
264
|
-
- `JOBS_DISPATCH_FAILED` - Dispatch operation failed
|
|
265
|
-
- `JOBS_SCHEDULE_FAILED` - Schedule operation failed
|
|
266
|
-
- `JOBS_INVALID_DISPATCH_PAYLOAD` - Invalid payload
|
|
267
|
-
|
|
268
|
-
### Error Class
|
|
269
|
-
|
|
270
|
-
```typescript
|
|
271
|
-
throw new IgniterJobsError({
|
|
272
|
-
code: 'JOBS_JOB_NOT_FOUND',
|
|
273
|
-
message: `Job "${jobId}" not found in queue "${queue}"`,
|
|
274
|
-
statusCode: 404,
|
|
275
|
-
details: { jobId, queue },
|
|
276
|
-
})
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
---
|
|
280
|
-
|
|
281
|
-
## 6. Development Guidelines
|
|
282
|
-
|
|
283
|
-
### Adding New Features
|
|
284
|
-
|
|
285
|
-
1. **Add Types First**
|
|
286
|
-
- Define in appropriate `src/types/*.ts` file
|
|
287
|
-
- Export from `src/types/index.ts`
|
|
288
|
-
- Export from `src/index.ts` if public
|
|
289
|
-
|
|
290
|
-
2. **Update Builders**
|
|
291
|
-
- Add method to builder class
|
|
292
|
-
- Update state type if needed
|
|
293
|
-
- Maintain fluent return type
|
|
294
|
-
|
|
295
|
-
3. **Update Runtime**
|
|
296
|
-
- Implement in `src/core/igniter-jobs.ts`
|
|
297
|
-
- Add proxy handling if needed
|
|
298
|
-
|
|
299
|
-
4. **Update Adapter Interface**
|
|
300
|
-
- Add method to `IgniterJobsAdapter`
|
|
301
|
-
- Implement in BullMQ adapter
|
|
302
|
-
- Implement in Memory adapter
|
|
303
|
-
|
|
304
|
-
5. **Add Tests**
|
|
305
|
-
- Unit test for builder method
|
|
306
|
-
- Integration test for runtime
|
|
307
|
-
- Adapter test for implementation
|
|
308
|
-
|
|
309
|
-
### Testing Strategy
|
|
310
|
-
|
|
311
|
-
```bash
|
|
312
|
-
# Run all tests
|
|
313
|
-
npm test
|
|
314
|
-
|
|
315
|
-
# Watch mode
|
|
316
|
-
npm run test:watch
|
|
317
|
-
|
|
318
|
-
# Coverage
|
|
319
|
-
npm run test:coverage
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
**Test Files:**
|
|
323
|
-
- `tests/igniter-queue.builder.test.ts` - Queue builder
|
|
324
|
-
- `tests/igniter-jobs.builder.test.ts` - Jobs builder
|
|
325
|
-
- `tests/igniter-jobs.runtime.test.ts` - Integration
|
|
326
|
-
- `tests/memory.adapter.test.ts` - Memory adapter
|
|
327
|
-
|
|
328
|
-
### Code Style
|
|
329
|
-
|
|
330
|
-
- Use JSDoc for all public APIs
|
|
331
|
-
- Follow existing patterns exactly
|
|
332
|
-
- No `any` types in public API
|
|
333
|
-
- Export types explicitly
|
|
334
|
-
- Use `readonly` where appropriate
|
|
335
|
-
|
|
336
|
-
---
|
|
337
|
-
|
|
338
|
-
## 7. Adapter Implementation Guide
|
|
339
|
-
|
|
340
|
-
### Required Methods
|
|
341
|
-
|
|
342
|
-
When implementing a new adapter, implement ALL methods from `IgniterJobsAdapter`:
|
|
343
|
-
|
|
344
|
-
```typescript
|
|
345
|
-
interface IgniterJobsAdapter {
|
|
346
|
-
// Connection
|
|
347
|
-
readonly client: unknown
|
|
348
|
-
|
|
349
|
-
// Job Operations
|
|
350
|
-
dispatch(params: AdapterDispatchParams): Promise<string>
|
|
351
|
-
schedule(params: AdapterScheduleParams): Promise<string>
|
|
352
|
-
getJob(queue: string, jobId: string): Promise<IgniterJobInfo | null>
|
|
353
|
-
getJobState(queue: string, jobId: string): Promise<IgniterJobStatus | null>
|
|
354
|
-
getJobProgress(queue: string, jobId: string): Promise<number>
|
|
355
|
-
getJobLogs(queue: string, jobId: string): Promise<IgniterJobLog[]>
|
|
356
|
-
retryJob(queue: string, jobId: string): Promise<void>
|
|
357
|
-
removeJob(queue: string, jobId: string): Promise<void>
|
|
358
|
-
promoteJob(queue: string, jobId: string): Promise<void>
|
|
359
|
-
moveJob(queue: string, jobId: string, state: string, reason?: string): Promise<void>
|
|
360
|
-
retryJobs(queue: string, jobIds: string[]): Promise<void>
|
|
361
|
-
removeJobs(queue: string, jobIds: string[]): Promise<void>
|
|
362
|
-
|
|
363
|
-
// Queue Operations
|
|
364
|
-
getQueue(queue: string): Promise<IgniterQueueInfo>
|
|
365
|
-
pauseQueue(queue: string): Promise<void>
|
|
366
|
-
resumeQueue(queue: string): Promise<void>
|
|
367
|
-
drainQueue(queue: string): Promise<number>
|
|
368
|
-
cleanQueue(queue: string, options: IgniterQueueCleanOptions): Promise<number>
|
|
369
|
-
obliterateQueue(queue: string, options?: { force?: boolean }): Promise<void>
|
|
370
|
-
retryAllFailed(queue: string): Promise<number>
|
|
371
|
-
getJobCounts(queue: string): Promise<IgniterJobCounts>
|
|
372
|
-
listJobs(queue: string, options?: {...}): Promise<IgniterJobSearchResult[]>
|
|
373
|
-
pauseJobType(queue: string, jobName: string): Promise<void>
|
|
374
|
-
resumeJobType(queue: string, jobName: string): Promise<void>
|
|
375
|
-
|
|
376
|
-
// Events
|
|
377
|
-
subscribe(pattern: string, handler: IgniterJobEventHandler): Promise<IgniterJobUnsubscribeFn>
|
|
378
|
-
|
|
379
|
-
// Workers
|
|
380
|
-
createWorker(config: AdapterWorkerConfig, handler: AdapterJobHandler): Promise<AdapterWorkerHandle>
|
|
381
|
-
|
|
382
|
-
// Search
|
|
383
|
-
searchJobs(filter: {...}): Promise<IgniterJobSearchResult[]>
|
|
384
|
-
searchQueues(filter: {...}): Promise<IgniterQueueInfo[]>
|
|
385
|
-
|
|
386
|
-
// Lifecycle
|
|
387
|
-
shutdown(): Promise<void>
|
|
388
|
-
}
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
---
|
|
392
|
-
|
|
393
|
-
## 8. Common Patterns
|
|
394
|
-
|
|
395
|
-
### Multi-tenant Job Dispatch
|
|
396
|
-
|
|
397
|
-
```typescript
|
|
398
|
-
const jobs = IgniterJobs.create()
|
|
399
|
-
.withAdapter(adapter)
|
|
400
|
-
.addQueue(emailQueue)
|
|
401
|
-
.addScope('organization', {
|
|
402
|
-
resolver: (id) => db.org.findUnique({ where: { id } }),
|
|
403
|
-
})
|
|
404
|
-
.addActor('user', {
|
|
405
|
-
resolver: (id) => db.user.findUnique({ where: { id } }),
|
|
406
|
-
})
|
|
407
|
-
.build()
|
|
408
|
-
|
|
409
|
-
// Dispatch with scope/actor
|
|
410
|
-
await jobs.email.sendWelcome.dispatch(
|
|
411
|
-
{ email: 'test@example.com' },
|
|
412
|
-
{
|
|
413
|
-
scope: { type: 'organization', id: 'org-123' },
|
|
414
|
-
actor: { type: 'user', id: 'user-456' },
|
|
415
|
-
}
|
|
416
|
-
)
|
|
417
|
-
```
|
|
418
|
-
|
|
419
|
-
### Job With Progress Updates
|
|
420
|
-
|
|
421
|
-
```typescript
|
|
422
|
-
const queue = IgniterQueue.create('exports')
|
|
423
|
-
.addJob('generateReport', {
|
|
424
|
-
schema: z.object({ reportId: z.string() }),
|
|
425
|
-
handler: async ({ data, updateProgress, log }) => {
|
|
426
|
-
await updateProgress(10)
|
|
427
|
-
await log('info', 'Starting report generation')
|
|
428
|
-
|
|
429
|
-
// ... process
|
|
430
|
-
|
|
431
|
-
await updateProgress(50)
|
|
432
|
-
await log('info', 'Halfway done')
|
|
433
|
-
|
|
434
|
-
// ... finish
|
|
435
|
-
|
|
436
|
-
await updateProgress(100)
|
|
437
|
-
return { success: true }
|
|
438
|
-
},
|
|
439
|
-
})
|
|
440
|
-
.build()
|
|
441
|
-
```
|
|
442
|
-
|
|
443
|
-
### Scheduled Jobs
|
|
444
|
-
|
|
445
|
-
```typescript
|
|
446
|
-
// Schedule at specific time
|
|
447
|
-
await jobs.email.sendWelcome.schedule({
|
|
448
|
-
data: { email: 'test@example.com' },
|
|
449
|
-
at: new Date('2025-12-25T00:00:00Z'),
|
|
450
|
-
})
|
|
451
|
-
|
|
452
|
-
// Schedule with delay
|
|
453
|
-
await jobs.email.sendWelcome.schedule({
|
|
454
|
-
data: { email: 'test@example.com' },
|
|
455
|
-
delay: 60000, // 1 minute
|
|
456
|
-
})
|
|
457
|
-
```
|
|
458
|
-
|
|
459
|
-
### Worker with Rate Limiting
|
|
460
|
-
|
|
461
|
-
```typescript
|
|
462
|
-
const worker = await jobs.worker
|
|
463
|
-
.forQueues(['email'])
|
|
464
|
-
.withConcurrency(10)
|
|
465
|
-
.withLimiter({
|
|
466
|
-
max: 100, // max jobs
|
|
467
|
-
duration: 60000, // per minute
|
|
468
|
-
})
|
|
469
|
-
.withLockDuration(30000)
|
|
470
|
-
.onIdle(() => console.log('No jobs to process'))
|
|
471
|
-
.start()
|
|
472
|
-
```
|
|
473
|
-
|
|
474
|
-
---
|
|
475
|
-
|
|
476
|
-
## 9. Version History
|
|
477
|
-
|
|
478
|
-
### 0.1.0 (Initial Release)
|
|
479
|
-
|
|
480
|
-
- ✅ IgniterQueue builder with addJob/addCron
|
|
481
|
-
- ✅ IgniterJobs builder with full configuration
|
|
482
|
-
- ✅ IgniterWorker builder with fluent API
|
|
483
|
-
- ✅ Proxy-based runtime for type-safe access
|
|
484
|
-
- ✅ BullMQ adapter with full feature support
|
|
485
|
-
- ✅ Memory adapter for testing
|
|
486
|
-
- ✅ Scope and actor support
|
|
487
|
-
- ✅ Event subscription system
|
|
488
|
-
- ✅ Job and queue search
|
|
489
|
-
- ✅ Error codes and classes
|
|
490
|
-
|
|
491
|
-
---
|
|
492
|
-
|
|
493
|
-
## 10. Troubleshooting
|
|
494
|
-
|
|
495
|
-
### Common Issues
|
|
496
|
-
|
|
497
|
-
**"JOBS_MISSING_ADAPTER"**
|
|
498
|
-
- Ensure `withAdapter()` is called before `build()`
|
|
499
|
-
- Check adapter is properly instantiated
|
|
500
|
-
|
|
501
|
-
**"JOBS_QUEUE_NOT_FOUND"**
|
|
502
|
-
- Queue must be registered with `addQueue()`
|
|
503
|
-
- Check queue name spelling
|
|
504
|
-
|
|
505
|
-
**"JOBS_JOB_VALIDATION_FAILED"**
|
|
506
|
-
- Payload doesn't match Zod schema
|
|
507
|
-
- Check `details.issues` for validation errors
|
|
508
|
-
|
|
509
|
-
**TypeScript errors on dispatch**
|
|
510
|
-
- Ensure queue is added before build
|
|
511
|
-
- Check job name exists in queue
|
|
512
|
-
- Verify payload matches schema
|
|
513
|
-
|
|
514
|
-
### Debug Tips
|
|
515
|
-
|
|
516
|
-
```typescript
|
|
517
|
-
// Enable BullMQ debug logging
|
|
518
|
-
process.env.DEBUG = 'bullmq:*'
|
|
519
|
-
|
|
520
|
-
// Check job state
|
|
521
|
-
const state = await jobs.job.state('queue', 'job-id')
|
|
522
|
-
console.log('Job state:', state)
|
|
523
|
-
|
|
524
|
-
// Get job logs
|
|
525
|
-
const logs = await jobs.job.logs('queue', 'job-id')
|
|
526
|
-
console.log('Job logs:', logs)
|
|
527
|
-
|
|
528
|
-
// Subscribe to all events
|
|
529
|
-
await jobs.subscribe('*', (event) => {
|
|
530
|
-
console.log('Event:', event.type, event.data)
|
|
531
|
-
})
|
|
532
|
-
```
|
|
533
|
-
|
|
534
|
-
---
|
|
535
|
-
|
|
536
|
-
## 11. Dependencies
|
|
537
|
-
|
|
538
|
-
### Peer Dependencies
|
|
539
|
-
|
|
540
|
-
| Package | Version | Purpose |
|
|
541
|
-
|---------|---------|---------|
|
|
542
|
-
| `bullmq` | `^5.0.0` | Job queue implementation |
|
|
543
|
-
| `ioredis` | `^5.0.0` | Redis client |
|
|
544
|
-
| `zod` | `^3.0.0` | Schema validation |
|
|
545
|
-
| `@igniter-js/telemetry` | `^0.1.0` | Optional tracing |
|
|
546
|
-
|
|
547
|
-
### Dev Dependencies
|
|
548
|
-
|
|
549
|
-
| Package | Version | Purpose |
|
|
550
|
-
|---------|---------|---------|
|
|
551
|
-
| `typescript` | `^5.0.0` | TypeScript compiler |
|
|
552
|
-
| `vitest` | `^1.0.0` | Testing framework |
|
|
553
|
-
| `tsup` | `^8.0.0` | Build tool |
|
|
554
|
-
|
|
555
|
-
---
|
|
556
|
-
|
|
557
|
-
**Remember:** Always follow existing patterns. When in doubt, check how similar features are implemented in `@igniter-js/store` or `@igniter-js/core`.
|
|
38
|
+
packages/jobs/
|
|
39
|
+
├── src/
|
|
40
|
+
│ ├── adapters/ # Adapter impls + barrel (bullmq, memory); capability parity with @igniter-js/adapter-bullmq
|
|
41
|
+
│ ├── builders/ # Fluent builders: queue, worker, job, cron definitions
|
|
42
|
+
│ ├── core/ # Runtime classes (queue runtime, worker runtime, proxies)
|
|
43
|
+
│ ├── errors/ # IgniterJobsError hierarchy
|
|
44
|
+
│ ├── telemetry/ # Event descriptors + emit helpers (if present)
|
|
45
|
+
│ ├── types/ # Public surface (config, adapter contracts, events, queue/worker types)
|
|
46
|
+
│ └── utils/ # Static helpers (ids, prefixes, validation)
|
|
47
|
+
├── AGENTS.md # You are here
|
|
48
|
+
├── CHANGELOG.md # Release notes
|
|
49
|
+
├── README.md # User-facing docs
|
|
50
|
+
├── package.json # Package metadata
|
|
51
|
+
├── tsconfig.json # TS build config
|
|
52
|
+
├── tsup.config.ts # Build outputs
|
|
53
|
+
└── vitest.config.ts # Test config
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 3. Architecture Overview
|
|
57
|
+
|
|
58
|
+
- **Builders (immutable):** `.create()` → chain setters → `.build()`. Must copy state, never mutate in-place. Maintain type accumulation for scopes/options like `@igniter-js/store`.
|
|
59
|
+
- **Runtime flow (happy path):**
|
|
60
|
+
1) User defines queue/worker via builders.
|
|
61
|
+
2) Adapter (BullMQ) wires queues/workers; memory adapter is for tests.
|
|
62
|
+
3) Job enqueue → adapter schedules → worker consumes → lifecycle events emit (internal + telemetry).
|
|
63
|
+
4) Errors bubble as `IgniterJobsError` with codes; runtime logs/telemetry should not crash workers.
|
|
64
|
+
- **Telemetry:** Optional peer; events emitted via lightweight helper (fire-and-forget). Event names `igniter.jobs.<group>.<event>`; attributes prefixed with `ctx.`. No actors; single scope (e.g., queue/workspace) only.
|
|
65
|
+
- **Scheduling:** `queue.addCron()` produces repeatable jobs; advanced scheduling metadata (skip weekends/business hours) attaches via `metadata.advancedScheduling`. BullMQ repeat options must be preserved.
|
|
66
|
+
|
|
67
|
+
## 4. Design Rules (must-keep)
|
|
68
|
+
|
|
69
|
+
- **Prefixing:** Public classes/types start with `IgniterJobs` (singular `IgniterJob` when appropriate). Utils are static classes.
|
|
70
|
+
- **Type Safety:** No implicit `any` on public API. Use `Prettify` helpers for flattened types. Align with `packages/core/src/types/jobs.interface.ts` and keep parity.
|
|
71
|
+
- **Adapters:** `IgniterJobsAdapter` defines capabilities. BullMQ adapter must keep: rate limiting, scheduling (cron/repeat), retries/backoff, job metadata, progress, bulk ops, management APIs (pause/resume/drain/clean/obliterate), hooks/callbacks. Memory adapter is test-only.
|
|
72
|
+
- **Docs:** TSDoc (English) with examples/edge cases for every exported symbol. Keep README + AGENTS + CHANGELOG in sync with behavior.
|
|
73
|
+
- **Utils:** Keep shared helpers in `src/utils`; add tests. Prefer pure functions or static classes.
|
|
74
|
+
- **Telemetry:** Optional dependency; interface lives in types to avoid hard dependency. Telemetry errors must never fail job execution.
|
|
75
|
+
|
|
76
|
+
## 5. Component Map (what to touch)
|
|
77
|
+
|
|
78
|
+
- **src/builders/**: Queue builder, worker builder, job definition builder. Ensure immutability and type accumulation. Provide `.withTelemetry()`, `.withAdapter()`, and scheduling helpers.
|
|
79
|
+
- **src/core/**: Runtime wrappers that orchestrate builders + adapters. Handles lifecycle hooks, logging/telemetry, error translation.
|
|
80
|
+
- **src/adapters/**: Adapter implementations + barrel. BullMQ mirrors `@igniter-js/adapter-bullmq`; memory adapter minimal but API-compatible for tests.
|
|
81
|
+
- **src/errors/**: `IgniterJobsError` codes. Add new codes here first; keep messages actionable.
|
|
82
|
+
- **src/telemetry/**: Event descriptors + emit helpers. Keep names stable and attributes prefixed `ctx.`.
|
|
83
|
+
- **src/types/**: Single source of truth for public API (config, events, adapters, queue/worker types). Update before implementation.
|
|
84
|
+
- **src/utils/**: ID generation, prefix handling, validation, backoff helpers. Pure and tested.
|
|
85
|
+
|
|
86
|
+
## 6. Telemetry Events (contract)
|
|
87
|
+
|
|
88
|
+
- **Namespace:** `igniter.jobs`.
|
|
89
|
+
- **Job events:** `enqueued`, `scheduled`, `started`, `completed`, `failed`, `progress`, `retrying`.
|
|
90
|
+
- **Worker events:** `started`, `stopped`, `idle`, `paused`, `resumed`.
|
|
91
|
+
- **Queue events:** `paused`, `resumed`, `drained`, `cleaned`, `obliterated`.
|
|
92
|
+
- **Attributes:** always include `ctx.job.id`, `ctx.job.queue`, plus duration/progress where applicable. Add `ctx.worker.id` for worker lifecycle.
|
|
93
|
+
- **Behavior:** Emission is best-effort; never throw. Keep helper tolerant (swallow telemetry errors, log if logger available).
|
|
94
|
+
|
|
95
|
+
## 7. Testing Strategy
|
|
96
|
+
|
|
97
|
+
- `npm test --filter @igniter-js/jobs`
|
|
98
|
+
- `bun test` (if bun is configured in scripts)
|
|
99
|
+
- `npx tsc --noEmit` for types
|
|
100
|
+
|
|
101
|
+
## 8. Build & Tooling
|
|
102
|
+
|
|
103
|
+
- **Build:** `bun run build` or `npm run build --filter @igniter-js/jobs` (tsup). Outputs ESM + CJS with dts.
|
|
104
|
+
- **Config:** `tsconfig.json` extends shared base; `tsup.config.ts` declares multiple entries if needed; keep barrels aligned.
|
|
105
|
+
- **External deps:** BullMQ/Redis via adapter; avoid pulling heavy deps into core runtime. Telemetry is optional peer.
|
|
106
|
+
|
|
107
|
+
## 9. Workflow Checklist (per change)
|
|
108
|
+
|
|
109
|
+
1. Read this AGENTS + `README.md` + relevant code before editing.
|
|
110
|
+
2. Update types (public surface) first; then implementation; then tests.
|
|
111
|
+
3. Preserve BullMQ feature parity; log any intentional deltas in CHANGELOG.
|
|
112
|
+
4. Keep telemetry names/attributes stable; update descriptors + tests if changed.
|
|
113
|
+
5. Add/adjust TSDoc for every exported symbol and public function.
|
|
114
|
+
6. Run tests and typecheck (`npm test --filter @igniter-js/jobs`, `npx tsc --noEmit`).
|
|
115
|
+
7. Update README + AGENTS + CHANGELOG when behavior or API changes.
|
|
116
|
+
|
|
117
|
+
## 10. Troubleshooting Notes
|
|
118
|
+
|
|
119
|
+
- **Telemetry failures:** Should be swallowed; if tests fail, ensure helper mocks errors without throwing.
|
|
120
|
+
- **Cron/repeat drift:** Verify repeat options passed untouched to BullMQ; advanced scheduling metadata must survive serialization.
|
|
121
|
+
- **Type regressions:** Compare against `packages/core/src/types/jobs.interface.ts`. No `any` leakage in public exports.
|
|
122
|
+
- **Adapter parity gaps:** Cross-check with `packages/adapter-bullmq/src/bullmq.adapter.ts` for missing capabilities.
|
|
123
|
+
- **Flaky integration tests:** Prefer Redis-mock/stub; isolate time-based tests with fake timers.
|
|
124
|
+
|
|
125
|
+
## 11. References
|
|
126
|
+
|
|
127
|
+
- `packages/core/src/types/jobs.interface.ts` — canonical job interfaces.
|
|
128
|
+
- `packages/adapter-bullmq/src/bullmq.adapter.ts` — legacy feature set to mirror.
|
|
129
|
+
- `packages/store`, `packages/telemetry` — builder/test patterns and redaction/sampling ideas.
|
|
130
|
+
|
|
131
|
+
Stay consistent, type-safe, and keep docs/tests in lockstep with the code.
|