@engjts/nexus 0.1.8 → 0.1.10

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 (221) hide show
  1. package/dist/advanced/playground/playground.js.map +1 -1
  2. package/dist/advanced/static/generateDirectoryListing.d.ts +1 -1
  3. package/dist/advanced/static/generateDirectoryListing.d.ts.map +1 -1
  4. package/dist/advanced/static/generateDirectoryListing.js +12 -6
  5. package/dist/advanced/static/generateDirectoryListing.js.map +1 -1
  6. package/dist/advanced/static/index.d.ts +2 -0
  7. package/dist/advanced/static/index.d.ts.map +1 -1
  8. package/dist/advanced/static/index.js +4 -1
  9. package/dist/advanced/static/index.js.map +1 -1
  10. package/dist/advanced/static/serveStatic.d.ts.map +1 -1
  11. package/dist/advanced/static/serveStatic.js +7 -1
  12. package/dist/advanced/static/serveStatic.js.map +1 -1
  13. package/dist/index.d.ts +1 -1
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +3 -1
  16. package/dist/index.js.map +1 -1
  17. package/package.json +1 -1
  18. package/BENCHMARK_REPORT.md +0 -343
  19. package/documentation/01-getting-started.md +0 -240
  20. package/documentation/02-context.md +0 -335
  21. package/documentation/03-routing.md +0 -397
  22. package/documentation/04-middleware.md +0 -483
  23. package/documentation/05-validation.md +0 -514
  24. package/documentation/06-error-handling.md +0 -465
  25. package/documentation/07-performance.md +0 -364
  26. package/documentation/08-adapters.md +0 -470
  27. package/documentation/09-api-reference.md +0 -548
  28. package/documentation/10-examples.md +0 -582
  29. package/documentation/11-deployment.md +0 -477
  30. package/documentation/12-sentry.md +0 -620
  31. package/documentation/13-sentry-data-storage.md +0 -996
  32. package/documentation/14-sentry-data-reference.md +0 -457
  33. package/documentation/15-sentry-summary.md +0 -409
  34. package/documentation/16-alerts-system.md +0 -745
  35. package/documentation/17-alert-adapters.md +0 -696
  36. package/documentation/18-alerts-implementation-summary.md +0 -385
  37. package/documentation/19-class-based-routing.md +0 -840
  38. package/documentation/20-websocket-realtime.md +0 -813
  39. package/documentation/21-cache-system.md +0 -510
  40. package/documentation/22-job-queue.md +0 -772
  41. package/documentation/23-sentry-plugin.md +0 -551
  42. package/documentation/24-testing-utilities.md +0 -1287
  43. package/documentation/25-api-versioning.md +0 -533
  44. package/documentation/26-context-store.md +0 -607
  45. package/documentation/27-dependency-injection.md +0 -329
  46. package/documentation/28-lifecycle-hooks.md +0 -521
  47. package/documentation/29-package-structure.md +0 -196
  48. package/documentation/30-plugin-system.md +0 -414
  49. package/documentation/31-jwt-authentication.md +0 -597
  50. package/documentation/32-cli.md +0 -268
  51. package/documentation/ALERTS-COMPLETE-SUMMARY.md +0 -429
  52. package/documentation/ALERTS-INDEX.md +0 -330
  53. package/documentation/ALERTS-QUICK-REFERENCE.md +0 -286
  54. package/documentation/README.md +0 -178
  55. package/documentation/index.html +0 -34
  56. package/modern_framework_paper.md +0 -1870
  57. package/public/css/style.css +0 -87
  58. package/public/index.html +0 -34
  59. package/public/js/app.js +0 -27
  60. package/src/advanced/cache/InMemoryCacheStore.ts +0 -68
  61. package/src/advanced/cache/MultiTierCache.ts +0 -194
  62. package/src/advanced/cache/RedisCacheStore.ts +0 -341
  63. package/src/advanced/cache/index.ts +0 -5
  64. package/src/advanced/cache/types.ts +0 -40
  65. package/src/advanced/graphql/SimpleDataLoader.ts +0 -42
  66. package/src/advanced/graphql/index.ts +0 -22
  67. package/src/advanced/graphql/server.ts +0 -252
  68. package/src/advanced/graphql/types.ts +0 -42
  69. package/src/advanced/jobs/InMemoryQueueStore.ts +0 -68
  70. package/src/advanced/jobs/JobQueue.ts +0 -556
  71. package/src/advanced/jobs/RedisQueueStore.ts +0 -367
  72. package/src/advanced/jobs/index.ts +0 -5
  73. package/src/advanced/jobs/types.ts +0 -70
  74. package/src/advanced/observability/APMManager.ts +0 -163
  75. package/src/advanced/observability/AlertManager.ts +0 -109
  76. package/src/advanced/observability/MetricRegistry.ts +0 -151
  77. package/src/advanced/observability/ObservabilityCenter.ts +0 -304
  78. package/src/advanced/observability/StructuredLogger.ts +0 -154
  79. package/src/advanced/observability/TracingManager.ts +0 -117
  80. package/src/advanced/observability/adapters.ts +0 -304
  81. package/src/advanced/observability/createObservabilityMiddleware.ts +0 -63
  82. package/src/advanced/observability/index.ts +0 -11
  83. package/src/advanced/observability/types.ts +0 -174
  84. package/src/advanced/playground/extractPathParams.ts +0 -6
  85. package/src/advanced/playground/generateFieldExample.ts +0 -31
  86. package/src/advanced/playground/generatePlaygroundHTML.ts +0 -1956
  87. package/src/advanced/playground/generateSummary.ts +0 -19
  88. package/src/advanced/playground/getTagFromPath.ts +0 -9
  89. package/src/advanced/playground/index.ts +0 -8
  90. package/src/advanced/playground/playground.ts +0 -250
  91. package/src/advanced/playground/types.ts +0 -49
  92. package/src/advanced/playground/zodToExample.ts +0 -16
  93. package/src/advanced/playground/zodToParams.ts +0 -15
  94. package/src/advanced/postman/buildAuth.ts +0 -31
  95. package/src/advanced/postman/buildBody.ts +0 -15
  96. package/src/advanced/postman/buildQueryParams.ts +0 -27
  97. package/src/advanced/postman/buildRequestItem.ts +0 -36
  98. package/src/advanced/postman/buildResponses.ts +0 -11
  99. package/src/advanced/postman/buildUrl.ts +0 -33
  100. package/src/advanced/postman/capitalize.ts +0 -4
  101. package/src/advanced/postman/generateCollection.ts +0 -59
  102. package/src/advanced/postman/generateEnvironment.ts +0 -34
  103. package/src/advanced/postman/generateExampleFromZod.ts +0 -21
  104. package/src/advanced/postman/generateFieldExample.ts +0 -45
  105. package/src/advanced/postman/generateName.ts +0 -20
  106. package/src/advanced/postman/generateUUID.ts +0 -11
  107. package/src/advanced/postman/getTagFromPath.ts +0 -10
  108. package/src/advanced/postman/index.ts +0 -28
  109. package/src/advanced/postman/postman.ts +0 -156
  110. package/src/advanced/postman/slugify.ts +0 -7
  111. package/src/advanced/postman/types.ts +0 -140
  112. package/src/advanced/realtime/index.ts +0 -18
  113. package/src/advanced/realtime/websocket.ts +0 -231
  114. package/src/advanced/sentry/index.ts +0 -1236
  115. package/src/advanced/sentry/types.ts +0 -355
  116. package/src/advanced/static/generateDirectoryListing.ts +0 -47
  117. package/src/advanced/static/generateETag.ts +0 -7
  118. package/src/advanced/static/getMimeType.ts +0 -9
  119. package/src/advanced/static/index.ts +0 -32
  120. package/src/advanced/static/isSafePath.ts +0 -13
  121. package/src/advanced/static/publicDir.ts +0 -21
  122. package/src/advanced/static/serveStatic.ts +0 -225
  123. package/src/advanced/static/spa.ts +0 -24
  124. package/src/advanced/static/types.ts +0 -159
  125. package/src/advanced/swagger/SwaggerGenerator.ts +0 -66
  126. package/src/advanced/swagger/buildOperation.ts +0 -61
  127. package/src/advanced/swagger/buildParameters.ts +0 -61
  128. package/src/advanced/swagger/buildRequestBody.ts +0 -21
  129. package/src/advanced/swagger/buildResponses.ts +0 -54
  130. package/src/advanced/swagger/capitalize.ts +0 -5
  131. package/src/advanced/swagger/convertPath.ts +0 -9
  132. package/src/advanced/swagger/createSwagger.ts +0 -12
  133. package/src/advanced/swagger/generateOperationId.ts +0 -21
  134. package/src/advanced/swagger/generateSpec.ts +0 -105
  135. package/src/advanced/swagger/generateSummary.ts +0 -24
  136. package/src/advanced/swagger/generateSwaggerUI.ts +0 -70
  137. package/src/advanced/swagger/generateThemeCss.ts +0 -53
  138. package/src/advanced/swagger/index.ts +0 -25
  139. package/src/advanced/swagger/swagger.ts +0 -237
  140. package/src/advanced/swagger/types.ts +0 -206
  141. package/src/advanced/swagger/zodFieldToOpenAPI.ts +0 -94
  142. package/src/advanced/swagger/zodSchemaToOpenAPI.ts +0 -50
  143. package/src/advanced/swagger/zodToOpenAPI.ts +0 -22
  144. package/src/advanced/testing/factory.ts +0 -509
  145. package/src/advanced/testing/harness.ts +0 -612
  146. package/src/advanced/testing/index.ts +0 -430
  147. package/src/advanced/testing/load-test.ts +0 -618
  148. package/src/advanced/testing/mock-server.ts +0 -498
  149. package/src/advanced/testing/mock.ts +0 -670
  150. package/src/cli/bin.ts +0 -9
  151. package/src/cli/cli.ts +0 -158
  152. package/src/cli/commands/add.ts +0 -178
  153. package/src/cli/commands/build.ts +0 -73
  154. package/src/cli/commands/create.ts +0 -166
  155. package/src/cli/commands/dev.ts +0 -85
  156. package/src/cli/commands/generate.ts +0 -99
  157. package/src/cli/commands/help.ts +0 -95
  158. package/src/cli/commands/init.ts +0 -91
  159. package/src/cli/commands/version.ts +0 -38
  160. package/src/cli/index.ts +0 -6
  161. package/src/cli/templates/generators.ts +0 -359
  162. package/src/cli/templates/index.ts +0 -680
  163. package/src/cli/utils/exec.ts +0 -52
  164. package/src/cli/utils/file-system.ts +0 -78
  165. package/src/cli/utils/logger.ts +0 -111
  166. package/src/core/adapter.ts +0 -88
  167. package/src/core/application.ts +0 -1453
  168. package/src/core/context-pool.ts +0 -79
  169. package/src/core/context.ts +0 -856
  170. package/src/core/index.ts +0 -94
  171. package/src/core/middleware.ts +0 -272
  172. package/src/core/performance/buffer-pool.ts +0 -108
  173. package/src/core/performance/middleware-optimizer.ts +0 -162
  174. package/src/core/plugin/PluginManager.ts +0 -435
  175. package/src/core/plugin/builder.ts +0 -358
  176. package/src/core/plugin/index.ts +0 -50
  177. package/src/core/plugin/types.ts +0 -214
  178. package/src/core/router/file-router.ts +0 -623
  179. package/src/core/router/index.ts +0 -260
  180. package/src/core/router/radix-tree.ts +0 -242
  181. package/src/core/serializer.ts +0 -397
  182. package/src/core/store/index.ts +0 -30
  183. package/src/core/store/registry.ts +0 -178
  184. package/src/core/store/request-store.ts +0 -240
  185. package/src/core/store/types.ts +0 -233
  186. package/src/core/types.ts +0 -616
  187. package/src/database/adapter.ts +0 -35
  188. package/src/database/adapters/index.ts +0 -1
  189. package/src/database/adapters/mysql.ts +0 -669
  190. package/src/database/database.ts +0 -70
  191. package/src/database/dialect.ts +0 -388
  192. package/src/database/index.ts +0 -12
  193. package/src/database/migrations.ts +0 -86
  194. package/src/database/optimizer.ts +0 -125
  195. package/src/database/query-builder.ts +0 -404
  196. package/src/database/realtime.ts +0 -53
  197. package/src/database/schema.ts +0 -71
  198. package/src/database/transactions.ts +0 -56
  199. package/src/database/types.ts +0 -87
  200. package/src/deployment/cluster.ts +0 -471
  201. package/src/deployment/config.ts +0 -454
  202. package/src/deployment/docker.ts +0 -599
  203. package/src/deployment/graceful-shutdown.ts +0 -373
  204. package/src/deployment/index.ts +0 -56
  205. package/src/index.ts +0 -281
  206. package/src/security/adapter.ts +0 -318
  207. package/src/security/auth/JWTPlugin.ts +0 -234
  208. package/src/security/auth/JWTProvider.ts +0 -316
  209. package/src/security/auth/adapter.ts +0 -12
  210. package/src/security/auth/jwt.ts +0 -234
  211. package/src/security/auth/middleware.ts +0 -188
  212. package/src/security/csrf.ts +0 -220
  213. package/src/security/headers.ts +0 -108
  214. package/src/security/index.ts +0 -60
  215. package/src/security/rate-limit/adapter.ts +0 -7
  216. package/src/security/rate-limit/memory.ts +0 -108
  217. package/src/security/rate-limit/middleware.ts +0 -181
  218. package/src/security/sanitization.ts +0 -75
  219. package/src/security/types.ts +0 -240
  220. package/src/security/utils.ts +0 -52
  221. 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!