@engjts/nexus 0.1.8 → 0.1.9

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 (205) hide show
  1. package/package.json +1 -1
  2. package/BENCHMARK_REPORT.md +0 -343
  3. package/documentation/01-getting-started.md +0 -240
  4. package/documentation/02-context.md +0 -335
  5. package/documentation/03-routing.md +0 -397
  6. package/documentation/04-middleware.md +0 -483
  7. package/documentation/05-validation.md +0 -514
  8. package/documentation/06-error-handling.md +0 -465
  9. package/documentation/07-performance.md +0 -364
  10. package/documentation/08-adapters.md +0 -470
  11. package/documentation/09-api-reference.md +0 -548
  12. package/documentation/10-examples.md +0 -582
  13. package/documentation/11-deployment.md +0 -477
  14. package/documentation/12-sentry.md +0 -620
  15. package/documentation/13-sentry-data-storage.md +0 -996
  16. package/documentation/14-sentry-data-reference.md +0 -457
  17. package/documentation/15-sentry-summary.md +0 -409
  18. package/documentation/16-alerts-system.md +0 -745
  19. package/documentation/17-alert-adapters.md +0 -696
  20. package/documentation/18-alerts-implementation-summary.md +0 -385
  21. package/documentation/19-class-based-routing.md +0 -840
  22. package/documentation/20-websocket-realtime.md +0 -813
  23. package/documentation/21-cache-system.md +0 -510
  24. package/documentation/22-job-queue.md +0 -772
  25. package/documentation/23-sentry-plugin.md +0 -551
  26. package/documentation/24-testing-utilities.md +0 -1287
  27. package/documentation/25-api-versioning.md +0 -533
  28. package/documentation/26-context-store.md +0 -607
  29. package/documentation/27-dependency-injection.md +0 -329
  30. package/documentation/28-lifecycle-hooks.md +0 -521
  31. package/documentation/29-package-structure.md +0 -196
  32. package/documentation/30-plugin-system.md +0 -414
  33. package/documentation/31-jwt-authentication.md +0 -597
  34. package/documentation/32-cli.md +0 -268
  35. package/documentation/ALERTS-COMPLETE-SUMMARY.md +0 -429
  36. package/documentation/ALERTS-INDEX.md +0 -330
  37. package/documentation/ALERTS-QUICK-REFERENCE.md +0 -286
  38. package/documentation/README.md +0 -178
  39. package/documentation/index.html +0 -34
  40. package/modern_framework_paper.md +0 -1870
  41. package/public/css/style.css +0 -87
  42. package/public/index.html +0 -34
  43. package/public/js/app.js +0 -27
  44. package/src/advanced/cache/InMemoryCacheStore.ts +0 -68
  45. package/src/advanced/cache/MultiTierCache.ts +0 -194
  46. package/src/advanced/cache/RedisCacheStore.ts +0 -341
  47. package/src/advanced/cache/index.ts +0 -5
  48. package/src/advanced/cache/types.ts +0 -40
  49. package/src/advanced/graphql/SimpleDataLoader.ts +0 -42
  50. package/src/advanced/graphql/index.ts +0 -22
  51. package/src/advanced/graphql/server.ts +0 -252
  52. package/src/advanced/graphql/types.ts +0 -42
  53. package/src/advanced/jobs/InMemoryQueueStore.ts +0 -68
  54. package/src/advanced/jobs/JobQueue.ts +0 -556
  55. package/src/advanced/jobs/RedisQueueStore.ts +0 -367
  56. package/src/advanced/jobs/index.ts +0 -5
  57. package/src/advanced/jobs/types.ts +0 -70
  58. package/src/advanced/observability/APMManager.ts +0 -163
  59. package/src/advanced/observability/AlertManager.ts +0 -109
  60. package/src/advanced/observability/MetricRegistry.ts +0 -151
  61. package/src/advanced/observability/ObservabilityCenter.ts +0 -304
  62. package/src/advanced/observability/StructuredLogger.ts +0 -154
  63. package/src/advanced/observability/TracingManager.ts +0 -117
  64. package/src/advanced/observability/adapters.ts +0 -304
  65. package/src/advanced/observability/createObservabilityMiddleware.ts +0 -63
  66. package/src/advanced/observability/index.ts +0 -11
  67. package/src/advanced/observability/types.ts +0 -174
  68. package/src/advanced/playground/extractPathParams.ts +0 -6
  69. package/src/advanced/playground/generateFieldExample.ts +0 -31
  70. package/src/advanced/playground/generatePlaygroundHTML.ts +0 -1956
  71. package/src/advanced/playground/generateSummary.ts +0 -19
  72. package/src/advanced/playground/getTagFromPath.ts +0 -9
  73. package/src/advanced/playground/index.ts +0 -8
  74. package/src/advanced/playground/playground.ts +0 -250
  75. package/src/advanced/playground/types.ts +0 -49
  76. package/src/advanced/playground/zodToExample.ts +0 -16
  77. package/src/advanced/playground/zodToParams.ts +0 -15
  78. package/src/advanced/postman/buildAuth.ts +0 -31
  79. package/src/advanced/postman/buildBody.ts +0 -15
  80. package/src/advanced/postman/buildQueryParams.ts +0 -27
  81. package/src/advanced/postman/buildRequestItem.ts +0 -36
  82. package/src/advanced/postman/buildResponses.ts +0 -11
  83. package/src/advanced/postman/buildUrl.ts +0 -33
  84. package/src/advanced/postman/capitalize.ts +0 -4
  85. package/src/advanced/postman/generateCollection.ts +0 -59
  86. package/src/advanced/postman/generateEnvironment.ts +0 -34
  87. package/src/advanced/postman/generateExampleFromZod.ts +0 -21
  88. package/src/advanced/postman/generateFieldExample.ts +0 -45
  89. package/src/advanced/postman/generateName.ts +0 -20
  90. package/src/advanced/postman/generateUUID.ts +0 -11
  91. package/src/advanced/postman/getTagFromPath.ts +0 -10
  92. package/src/advanced/postman/index.ts +0 -28
  93. package/src/advanced/postman/postman.ts +0 -156
  94. package/src/advanced/postman/slugify.ts +0 -7
  95. package/src/advanced/postman/types.ts +0 -140
  96. package/src/advanced/realtime/index.ts +0 -18
  97. package/src/advanced/realtime/websocket.ts +0 -231
  98. package/src/advanced/sentry/index.ts +0 -1236
  99. package/src/advanced/sentry/types.ts +0 -355
  100. package/src/advanced/static/generateDirectoryListing.ts +0 -47
  101. package/src/advanced/static/generateETag.ts +0 -7
  102. package/src/advanced/static/getMimeType.ts +0 -9
  103. package/src/advanced/static/index.ts +0 -32
  104. package/src/advanced/static/isSafePath.ts +0 -13
  105. package/src/advanced/static/publicDir.ts +0 -21
  106. package/src/advanced/static/serveStatic.ts +0 -225
  107. package/src/advanced/static/spa.ts +0 -24
  108. package/src/advanced/static/types.ts +0 -159
  109. package/src/advanced/swagger/SwaggerGenerator.ts +0 -66
  110. package/src/advanced/swagger/buildOperation.ts +0 -61
  111. package/src/advanced/swagger/buildParameters.ts +0 -61
  112. package/src/advanced/swagger/buildRequestBody.ts +0 -21
  113. package/src/advanced/swagger/buildResponses.ts +0 -54
  114. package/src/advanced/swagger/capitalize.ts +0 -5
  115. package/src/advanced/swagger/convertPath.ts +0 -9
  116. package/src/advanced/swagger/createSwagger.ts +0 -12
  117. package/src/advanced/swagger/generateOperationId.ts +0 -21
  118. package/src/advanced/swagger/generateSpec.ts +0 -105
  119. package/src/advanced/swagger/generateSummary.ts +0 -24
  120. package/src/advanced/swagger/generateSwaggerUI.ts +0 -70
  121. package/src/advanced/swagger/generateThemeCss.ts +0 -53
  122. package/src/advanced/swagger/index.ts +0 -25
  123. package/src/advanced/swagger/swagger.ts +0 -237
  124. package/src/advanced/swagger/types.ts +0 -206
  125. package/src/advanced/swagger/zodFieldToOpenAPI.ts +0 -94
  126. package/src/advanced/swagger/zodSchemaToOpenAPI.ts +0 -50
  127. package/src/advanced/swagger/zodToOpenAPI.ts +0 -22
  128. package/src/advanced/testing/factory.ts +0 -509
  129. package/src/advanced/testing/harness.ts +0 -612
  130. package/src/advanced/testing/index.ts +0 -430
  131. package/src/advanced/testing/load-test.ts +0 -618
  132. package/src/advanced/testing/mock-server.ts +0 -498
  133. package/src/advanced/testing/mock.ts +0 -670
  134. package/src/cli/bin.ts +0 -9
  135. package/src/cli/cli.ts +0 -158
  136. package/src/cli/commands/add.ts +0 -178
  137. package/src/cli/commands/build.ts +0 -73
  138. package/src/cli/commands/create.ts +0 -166
  139. package/src/cli/commands/dev.ts +0 -85
  140. package/src/cli/commands/generate.ts +0 -99
  141. package/src/cli/commands/help.ts +0 -95
  142. package/src/cli/commands/init.ts +0 -91
  143. package/src/cli/commands/version.ts +0 -38
  144. package/src/cli/index.ts +0 -6
  145. package/src/cli/templates/generators.ts +0 -359
  146. package/src/cli/templates/index.ts +0 -680
  147. package/src/cli/utils/exec.ts +0 -52
  148. package/src/cli/utils/file-system.ts +0 -78
  149. package/src/cli/utils/logger.ts +0 -111
  150. package/src/core/adapter.ts +0 -88
  151. package/src/core/application.ts +0 -1453
  152. package/src/core/context-pool.ts +0 -79
  153. package/src/core/context.ts +0 -856
  154. package/src/core/index.ts +0 -94
  155. package/src/core/middleware.ts +0 -272
  156. package/src/core/performance/buffer-pool.ts +0 -108
  157. package/src/core/performance/middleware-optimizer.ts +0 -162
  158. package/src/core/plugin/PluginManager.ts +0 -435
  159. package/src/core/plugin/builder.ts +0 -358
  160. package/src/core/plugin/index.ts +0 -50
  161. package/src/core/plugin/types.ts +0 -214
  162. package/src/core/router/file-router.ts +0 -623
  163. package/src/core/router/index.ts +0 -260
  164. package/src/core/router/radix-tree.ts +0 -242
  165. package/src/core/serializer.ts +0 -397
  166. package/src/core/store/index.ts +0 -30
  167. package/src/core/store/registry.ts +0 -178
  168. package/src/core/store/request-store.ts +0 -240
  169. package/src/core/store/types.ts +0 -233
  170. package/src/core/types.ts +0 -616
  171. package/src/database/adapter.ts +0 -35
  172. package/src/database/adapters/index.ts +0 -1
  173. package/src/database/adapters/mysql.ts +0 -669
  174. package/src/database/database.ts +0 -70
  175. package/src/database/dialect.ts +0 -388
  176. package/src/database/index.ts +0 -12
  177. package/src/database/migrations.ts +0 -86
  178. package/src/database/optimizer.ts +0 -125
  179. package/src/database/query-builder.ts +0 -404
  180. package/src/database/realtime.ts +0 -53
  181. package/src/database/schema.ts +0 -71
  182. package/src/database/transactions.ts +0 -56
  183. package/src/database/types.ts +0 -87
  184. package/src/deployment/cluster.ts +0 -471
  185. package/src/deployment/config.ts +0 -454
  186. package/src/deployment/docker.ts +0 -599
  187. package/src/deployment/graceful-shutdown.ts +0 -373
  188. package/src/deployment/index.ts +0 -56
  189. package/src/index.ts +0 -281
  190. package/src/security/adapter.ts +0 -318
  191. package/src/security/auth/JWTPlugin.ts +0 -234
  192. package/src/security/auth/JWTProvider.ts +0 -316
  193. package/src/security/auth/adapter.ts +0 -12
  194. package/src/security/auth/jwt.ts +0 -234
  195. package/src/security/auth/middleware.ts +0 -188
  196. package/src/security/csrf.ts +0 -220
  197. package/src/security/headers.ts +0 -108
  198. package/src/security/index.ts +0 -60
  199. package/src/security/rate-limit/adapter.ts +0 -7
  200. package/src/security/rate-limit/memory.ts +0 -108
  201. package/src/security/rate-limit/middleware.ts +0 -181
  202. package/src/security/sanitization.ts +0 -75
  203. package/src/security/types.ts +0 -240
  204. package/src/security/utils.ts +0 -52
  205. package/tsconfig.json +0 -39
@@ -1,772 +0,0 @@
1
- # Job Queue System
2
-
3
- Background job processing dengan support untuk retry, concurrency control, rate limiting, dan callbacks.
4
-
5
- ## Table of Contents
6
-
7
- 1. [Introduction](#introduction)
8
- 2. [Core Concepts](#core-concepts)
9
- 3. [Basic Usage](#basic-usage)
10
- 4. [Configuration](#configuration)
11
- 5. [Job Handlers](#job-handlers)
12
- 6. [Job States](#job-states)
13
- 7. [Callbacks & Hooks](#callbacks--hooks)
14
- 8. [Advanced Features](#advanced-features)
15
- 9. [Event Listeners](#event-listeners)
16
- 10. [Best Practices](#best-practices)
17
- 11. [Examples](#examples)
18
-
19
- ## Introduction
20
-
21
- Job Queue adalah sistem untuk menjalankan tugas-tugas berat/panjang di background tanpa memblokir request HTTP. Cocok untuk:
22
-
23
- - **Email sending** - Kirim email asynchronous
24
- - **File processing** - Upload, convert, compress files
25
- - **API calls** - Fetch data dari external API dengan retry
26
- - **Data import** - Import data dalam batch
27
- - **Notifications** - Send push notifications, SMS, dsb
28
- - **Scheduled tasks** - Jalankan task di waktu tertentu
29
-
30
- ## Core Concepts
31
-
32
- ### Job
33
-
34
- Unit kerja yang akan diproses oleh queue. Setiap job memiliki:
35
-
36
- ```typescript
37
- interface Job<Data = any, Result = any> {
38
- id: string; // Unique job ID
39
- name: string; // Job type/name
40
- data: Data; // Job payload
41
- result?: Result; // Job result (after completion)
42
- error?: { message: string }; // Error info (if failed)
43
- state: JobState; // Current state
44
- attemptsMade: number; // Retry count
45
- maxAttempts: number; // Max retry attempts
46
- priority: number; // Higher = process first
47
- createdAt: number; // Creation timestamp
48
- runAt: number; // When to run (for delayed jobs)
49
- updatedAt: number; // Last update timestamp
50
- metadata?: Record<string, any>; // Custom metadata
51
- }
52
- ```
53
-
54
- ### JobQueue
55
-
56
- Container untuk job dan handler processing logic.
57
-
58
- ```typescript
59
- const queue = new JobQueue('email', {
60
- concurrency: 5, // Max 5 jobs running simultaneously
61
- retry: { ... }, // Retry configuration
62
- limiter: { ... }, // Rate limiting
63
- hooks: { ... } // Callback hooks
64
- });
65
- ```
66
-
67
- ### Job States
68
-
69
- ```
70
- waiting → active → completed
71
-
72
- failed/delayed → active → completed
73
- ```
74
-
75
- - **waiting**: Job siap dijalankan
76
- - **delayed**: Job dijadwalkan untuk nanti
77
- - **active**: Job sedang diproses
78
- - **completed**: Job berhasil
79
- - **failed**: Job gagal permanent
80
- - **paused**: Queue dalam mode pause
81
-
82
- ## Basic Usage
83
-
84
- ### 1. Create Queue
85
-
86
- ```typescript
87
- import { JobQueue } from './src/advanced/jobs/queue';
88
-
89
- const emailQueue = new JobQueue('email', {
90
- concurrency: 2
91
- });
92
- ```
93
-
94
- ### 2. Register Job Handler
95
-
96
- ```typescript
97
- emailQueue.process('send-email', async (job) => {
98
- const { email, subject, message } = job.data;
99
-
100
- // Do work here
101
- const result = await sendEmail(email, subject, message);
102
-
103
- // Return result
104
- return result;
105
- });
106
- ```
107
-
108
- ### 3. Add Job to Queue
109
-
110
- ```typescript
111
- const job = await emailQueue.add('send-email', {
112
- email: 'user@example.com',
113
- subject: 'Welcome!',
114
- message: 'Thanks for signing up'
115
- });
116
-
117
- console.log(job.id); // jobId untuk tracking
118
- ```
119
-
120
- ### 4. Listen to Events
121
-
122
- ```typescript
123
- emailQueue.on('completed', (job, result) => {
124
- console.log('Email sent:', result);
125
- });
126
-
127
- emailQueue.on('failed', (job, error) => {
128
- console.log('Email failed:', error.message);
129
- });
130
- ```
131
-
132
- ## Configuration
133
-
134
- ### QueueOptions
135
-
136
- ```typescript
137
- interface QueueOptions<Data = any> {
138
- concurrency?: number; // Default: 5
139
- retry?: RetryOptions; // Retry config
140
- limiter?: RateLimitOptions; // Rate limit config
141
- hooks?: QueueHooks<Data>; // Callback hooks
142
- store?: QueueStore<Data>; // Custom storage
143
- }
144
- ```
145
-
146
- ### Retry Configuration
147
-
148
- ```typescript
149
- const queue = new JobQueue('tasks', {
150
- retry: {
151
- attempts: 3, // Retry 3 times max
152
- backoff: 'exponential', // 'fixed' or 'exponential'
153
- delay: 1000, // Initial delay: 1 second
154
- maxDelay: 60000 // Max delay: 1 minute
155
- }
156
- });
157
- ```
158
-
159
- **Exponential backoff example:**
160
- - Attempt 1 fails → wait 1s
161
- - Attempt 2 fails → wait 2s
162
- - Attempt 3 fails → wait 4s
163
- - Attempt 4 = FAIL PERMANENT
164
-
165
- ### Rate Limiting
166
-
167
- ```typescript
168
- const queue = new JobQueue('api-calls', {
169
- concurrency: 10, // 10 concurrent jobs
170
- limiter: {
171
- max: 5, // But max 5 jobs
172
- duration: 60000 // Per minute (60 seconds)
173
- }
174
- });
175
-
176
- // Result: 5 jobs per minute, even with 10 concurrency
177
- ```
178
-
179
- ### Custom Storage
180
-
181
- Default menggunakan in-memory storage. Bisa custom:
182
-
183
- ```typescript
184
- class PostgresQueueStore implements QueueStore {
185
- async enqueue(job: Job) { ... }
186
- async dequeue(): Promise<Job | undefined> { ... }
187
- async update(job: Job) { ... }
188
- async get(id: string) { ... }
189
- async list(state?: JobState) { ... }
190
- async stats() { ... }
191
- }
192
-
193
- const queue = new JobQueue('email', {
194
- store: new PostgresQueueStore()
195
- });
196
- ```
197
-
198
- ## Job Handlers
199
-
200
- ### Simple Handler
201
-
202
- ```typescript
203
- queue.process('simple-job', async (job) => {
204
- console.log('Processing:', job.data);
205
- return { success: true };
206
- });
207
- ```
208
-
209
- ### Handler dengan Error Handling
210
-
211
- ```typescript
212
- queue.process('risky-job', async (job) => {
213
- try {
214
- const result = await riskyOperation(job.data);
215
- return result;
216
- } catch (error) {
217
- throw new Error(`Failed: ${error.message}`);
218
- }
219
- });
220
- ```
221
-
222
- ### Handler dengan Async Operations
223
-
224
- ```typescript
225
- queue.process('db-import', async (job) => {
226
- const records = job.data.records;
227
-
228
- // Batch insert
229
- const inserted = await db.users.insert(records);
230
-
231
- // Return count
232
- return { inserted: inserted.length };
233
- });
234
- ```
235
-
236
- ### Handler Accessing Job Meta
237
-
238
- ```typescript
239
- queue.process('task', async (job) => {
240
- console.log('Job ID:', job.id);
241
- console.log('Attempt:', job.attemptsMade);
242
- console.log('Max retries:', job.maxAttempts);
243
- console.log('Priority:', job.priority);
244
- console.log('Metadata:', job.metadata);
245
-
246
- return { done: true };
247
- });
248
- ```
249
-
250
- ## Job States
251
-
252
- ### State Transitions
253
-
254
- ```
255
- 1. Add job → waiting state
256
- 2. Dequeue & start → active state
257
- 3. Complete → completed state
258
- OR fail → delayed state (if retry available) or failed state
259
- ```
260
-
261
- ### Check Job State
262
-
263
- ```typescript
264
- const job = await queue.add('task', data);
265
- console.log(job.state); // 'waiting'
266
-
267
- // Later...
268
- const currentJob = await queue.store.get(job.id);
269
- console.log(currentJob.state); // 'completed', 'failed', etc
270
- ```
271
-
272
- ## Callbacks & Hooks
273
-
274
- ### Three Types of Callbacks
275
-
276
- ```typescript
277
- const queue = new JobQueue('email', {
278
- hooks: {
279
- onComplete: async (job, result) => {
280
- // Called when job succeeds
281
- },
282
- onFailed: async (job, error) => {
283
- // Called when job fails permanently
284
- },
285
- onRetry: async (job, attempt, delay) => {
286
- // Called before each retry
287
- }
288
- }
289
- });
290
- ```
291
-
292
- ### Example: Email Callbacks
293
-
294
- ```typescript
295
- const queue = new JobQueue('email', {
296
- hooks: {
297
- onComplete: async (job, result) => {
298
- // Update database: email_logs.status = 'sent'
299
- await db.emailLogs.update(
300
- { jobId: job.id },
301
- { status: 'sent', result }
302
- );
303
-
304
- // Send webhook
305
- await webhook.post('/events/email-sent', {
306
- email: job.data.email,
307
- timestamp: new Date()
308
- });
309
- },
310
-
311
- onFailed: async (job, error) => {
312
- // Update database: email_logs.status = 'failed'
313
- await db.emailLogs.update(
314
- { jobId: job.id },
315
- {
316
- status: 'failed',
317
- error: error.message,
318
- failedAt: new Date()
319
- }
320
- );
321
-
322
- // Alert admin
323
- await slack.notify({
324
- channel: '#alerts',
325
- text: `Email delivery failed: ${job.data.email}`
326
- });
327
- },
328
-
329
- onRetry: async (job, attempt, delay) => {
330
- // Log retry attempt
331
- await db.jobRetries.insert({
332
- jobId: job.id,
333
- attempt,
334
- nextRetryIn: delay
335
- });
336
- }
337
- }
338
- });
339
- ```
340
-
341
- ## Advanced Features
342
-
343
- ### 1. Priority Jobs
344
-
345
- Higher priority jobs execute first:
346
-
347
- ```typescript
348
- // Low priority
349
- await queue.add('email', data, { priority: 0 });
350
-
351
- // Medium priority
352
- await queue.add('email', data, { priority: 5 });
353
-
354
- // High priority (execute first)
355
- await queue.add('email', data, { priority: 10 });
356
- ```
357
-
358
- ### 2. Delayed Jobs
359
-
360
- Schedule job untuk nanti:
361
-
362
- ```typescript
363
- // Run 5 minutes from now
364
- await queue.add('reminder', data, {
365
- delay: 5 * 60 * 1000
366
- });
367
-
368
- // Run 1 hour from now
369
- await queue.add('report', data, {
370
- delay: 60 * 60 * 1000
371
- });
372
- ```
373
-
374
- ### 3. Bulk Add
375
-
376
- Add multiple jobs at once:
377
-
378
- ```typescript
379
- const jobs = [
380
- { name: 'send-email', data: { email: 'user1@ex.com' } },
381
- { name: 'send-email', data: { email: 'user2@ex.com' } },
382
- { name: 'send-email', data: { email: 'user3@ex.com' } }
383
- ];
384
-
385
- await queue.addBulk(jobs);
386
- ```
387
-
388
- ### 4. Manual Retry
389
-
390
- Retry failed job manually:
391
-
392
- ```typescript
393
- try {
394
- await queue.retry(jobId);
395
- } catch (error) {
396
- console.log('Job not found');
397
- }
398
- ```
399
-
400
- ### 5. Pause & Resume
401
-
402
- Control queue processing:
403
-
404
- ```typescript
405
- queue.pause(); // Stop processing new jobs
406
- queue.resume(); // Resume processing
407
- ```
408
-
409
- ### 6. Queue Statistics
410
-
411
- ```typescript
412
- const stats = await queue.stats();
413
-
414
- console.log(stats);
415
- // {
416
- // waiting: 5,
417
- // active: 2,
418
- // completed: 100,
419
- // failed: 3,
420
- // delayed: 10
421
- // }
422
- ```
423
-
424
- ## Event Listeners
425
-
426
- Queue extends EventEmitter, emit 5 events:
427
-
428
- ```typescript
429
- // Job added to queue
430
- queue.on('added', (job) => {
431
- console.log('Job added:', job.id);
432
- });
433
-
434
- // Job started processing
435
- queue.on('active', (job) => {
436
- console.log('Job processing:', job.id);
437
- });
438
-
439
- // Job completed successfully
440
- queue.on('completed', (job, result) => {
441
- console.log('Job done:', result);
442
- });
443
-
444
- // Job failed
445
- queue.on('failed', (job, error) => {
446
- console.log('Job error:', error.message);
447
- });
448
-
449
- // Job about to retry
450
- queue.on('retrying', (job, attempt, delay) => {
451
- console.log(`Retry ${attempt} in ${delay}ms`);
452
- });
453
-
454
- // Queue paused
455
- queue.on('paused', () => {
456
- console.log('Queue paused');
457
- });
458
-
459
- // Queue resumed
460
- queue.on('resumed', () => {
461
- console.log('Queue resumed');
462
- });
463
- ```
464
-
465
- ## Best Practices
466
-
467
- ### 1. Use Meaningful Job Names
468
-
469
- ```typescript
470
- // Good
471
- queue.process('send-welcome-email', handler);
472
- queue.process('import-users-csv', handler);
473
- queue.process('generate-report', handler);
474
-
475
- // Avoid
476
- queue.process('job1', handler);
477
- queue.process('task', handler);
478
- ```
479
-
480
- ### 2. Include Metadata for Tracking
481
-
482
- ```typescript
483
- await queue.add('email', emailData, {
484
- metadata: {
485
- userId: user.id,
486
- campaignId: campaign.id,
487
- source: 'signup-flow'
488
- }
489
- });
490
-
491
- // Later in handler
492
- queue.process('email', async (job) => {
493
- console.log('From campaign:', job.metadata?.campaignId);
494
- });
495
- ```
496
-
497
- ### 3. Set Appropriate Concurrency
498
-
499
- ```typescript
500
- // Email: 2-5 concurrent (don't overwhelm SMTP)
501
- new JobQueue('email', { concurrency: 3 });
502
-
503
- // API calls: 10-20 concurrent
504
- new JobQueue('api', { concurrency: 15 });
505
-
506
- // Database: 5-10 concurrent (DB connection limits)
507
- new JobQueue('db', { concurrency: 8 });
508
-
509
- // CPU intensive: 1-2 concurrent
510
- new JobQueue('cpu-heavy', { concurrency: 1 });
511
- ```
512
-
513
- ### 4. Use Rate Limiting for External APIs
514
-
515
- ```typescript
516
- new JobQueue('external-api', {
517
- concurrency: 20,
518
- limiter: {
519
- max: 100, // 100 requests
520
- duration: 60000 // per minute (API rate limit)
521
- }
522
- });
523
- ```
524
-
525
- ### 5. Implement Proper Error Handling
526
-
527
- ```typescript
528
- queue.process('api-call', async (job) => {
529
- const maxRetries = 3;
530
-
531
- try {
532
- // Your operation
533
- const result = await fetchFromAPI(job.data.url);
534
- return result;
535
- } catch (error) {
536
- // Log detailed error
537
- console.error({
538
- jobId: job.id,
539
- attempt: job.attemptsMade,
540
- maxAttempts: job.maxAttempts,
541
- error: error.message,
542
- stack: error.stack
543
- });
544
-
545
- throw error; // Let queue handle retry
546
- }
547
- });
548
- ```
549
-
550
- ### 6. Use Callbacks for Side Effects
551
-
552
- ```typescript
553
- const queue = new JobQueue('notifications', {
554
- hooks: {
555
- onComplete: async (job, result) => {
556
- // Update database
557
- await db.notifications.update(job.id, {
558
- status: 'sent',
559
- sentAt: new Date(),
560
- result
561
- });
562
- },
563
- onFailed: async (job, error) => {
564
- // Store failure reason
565
- await db.notifications.update(job.id, {
566
- status: 'failed',
567
- error: error.message,
568
- failedAt: new Date()
569
- });
570
-
571
- // Send alert
572
- await alertService.notify({
573
- type: 'notification-failed',
574
- jobId: job.id,
575
- error: error.message
576
- });
577
- }
578
- }
579
- });
580
- ```
581
-
582
- ### 7. Validate Job Data
583
-
584
- ```typescript
585
- import { z } from 'zod';
586
-
587
- const emailSchema = z.object({
588
- email: z.string().email(),
589
- subject: z.string().min(5),
590
- message: z.string().min(10)
591
- });
592
-
593
- queue.process('send-email', async (job) => {
594
- // Validate before processing
595
- const validated = emailSchema.parse(job.data);
596
-
597
- return await sendEmail(validated);
598
- });
599
- ```
600
-
601
- ## Examples
602
-
603
- ### Example 1: Email Queue with Callbacks
604
-
605
- ```typescript
606
- import { JobQueue } from './src/advanced/jobs/queue';
607
-
608
- const emailQueue = new JobQueue('email', {
609
- concurrency: 3,
610
- retry: {
611
- attempts: 3,
612
- backoff: 'exponential',
613
- delay: 1000
614
- },
615
- hooks: {
616
- onComplete: async (job, result) => {
617
- await db.emails.updateStatus(job.id, 'sent');
618
- await analytics.track('email_sent', {
619
- email: job.data.email
620
- });
621
- },
622
- onFailed: async (job, error) => {
623
- await db.emails.updateStatus(job.id, 'failed');
624
- await alertService.notify({
625
- message: `Email failed: ${job.data.email}`,
626
- error: error.message
627
- });
628
- }
629
- }
630
- });
631
-
632
- emailQueue.process('send-email', async (job) => {
633
- const { email, subject, message } = job.data;
634
- await mailService.send(email, subject, message);
635
- return { sent: true };
636
- });
637
-
638
- // Usage in endpoint
639
- app.post('/api/send-email', async (ctx) => {
640
- const job = await emailQueue.add('send-email', {
641
- email: ctx.body.email,
642
- subject: ctx.body.subject,
643
- message: ctx.body.message
644
- });
645
-
646
- return { jobId: job.id };
647
- });
648
- ```
649
-
650
- ### Example 2: File Processing Queue
651
-
652
- ```typescript
653
- const fileQueue = new JobQueue('files', {
654
- concurrency: 2,
655
- limiter: {
656
- max: 10,
657
- duration: 60000
658
- }
659
- });
660
-
661
- fileQueue.process('process-upload', async (job) => {
662
- const { fileId, fileName } = job.data;
663
-
664
- // Download file
665
- const file = await storage.download(fileId);
666
-
667
- // Process
668
- const processed = await imageService.optimize(file);
669
-
670
- // Upload result
671
- const resultId = await storage.upload(processed);
672
-
673
- return { resultId, fileName };
674
- });
675
-
676
- // Add to queue from endpoint
677
- app.post('/api/upload', async (ctx) => {
678
- const file = ctx.files.file;
679
- const fileId = await storage.save(file);
680
-
681
- const job = await fileQueue.add('process-upload', {
682
- fileId,
683
- fileName: file.name
684
- });
685
-
686
- return {
687
- fileId,
688
- jobId: job.id,
689
- status: 'processing'
690
- };
691
- });
692
- ```
693
-
694
- ### Example 3: Scheduled Tasks
695
-
696
- ```typescript
697
- const schedulerQueue = new JobQueue('scheduler', {
698
- concurrency: 5
699
- });
700
-
701
- schedulerQueue.process('send-daily-report', async (job) => {
702
- const { userId } = job.data;
703
- const report = await generateReport(userId);
704
- await emailService.send(userId, 'Daily Report', report);
705
- return { sent: true };
706
- });
707
-
708
- // Schedule every day at 8 AM
709
- setInterval(async () => {
710
- const now = new Date();
711
- if (now.getHours() === 8 && now.getMinutes() === 0) {
712
- const users = await db.users.findAll();
713
- await schedulerQueue.addBulk(
714
- users.map(u => ({
715
- name: 'send-daily-report',
716
- data: { userId: u.id }
717
- }))
718
- );
719
- }
720
- }, 60000); // Check every minute
721
- ```
722
-
723
- ### Example 4: Data Import
724
-
725
- ```typescript
726
- const importQueue = new JobQueue('import', {
727
- concurrency: 1,
728
- retry: { attempts: 2 }
729
- });
730
-
731
- importQueue.process('import-csv', async (job) => {
732
- const { fileId, userId } = job.data;
733
-
734
- // Read CSV
735
- const file = await storage.read(fileId);
736
- const records = await parseCSV(file);
737
-
738
- // Validate
739
- const validated = records.map(r => validateRecord(r));
740
-
741
- // Insert
742
- const inserted = await db.users.insertMany(validated);
743
-
744
- // Notify user
745
- await emailService.send(userId, 'Import Complete',
746
- `Successfully imported ${inserted.length} records`
747
- );
748
-
749
- return { imported: inserted.length };
750
- });
751
-
752
- importQueue.on('failed', async (job, error) => {
753
- const { userId } = job.data;
754
- await emailService.send(userId, 'Import Failed',
755
- `Error: ${error.message}`
756
- );
757
- });
758
- ```
759
-
760
- ---
761
-
762
- ## Summary
763
-
764
- Job Queue cocok untuk:
765
- - ✅ Long-running operations (jangan block HTTP response)
766
- - ✅ Retry logic dengan exponential backoff
767
- - ✅ Rate limiting & concurrency control
768
- - ✅ Callback hooks untuk success/failure
769
- - ✅ Priority & delayed job scheduling
770
- - ✅ Bulk operations
771
-
772
- Use dengan bijak untuk improve application reliability & user experience!