queen-mq 0.2.22 → 0.3.0
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/README.md +162 -136
- package/client-js/benchmark/consumer.js +1 -1
- package/client-js/client/client.js +24 -3
- package/client-js/client-v2/LOGGING.md +240 -0
- package/client-js/client-v2/Queen.js +389 -0
- package/client-js/client-v2/README.md +1883 -0
- package/client-js/client-v2/buffer/BufferManager.js +215 -0
- package/client-js/client-v2/buffer/MessageBuffer.js +132 -0
- package/client-js/client-v2/builders/QueueBuilder.js +724 -0
- package/client-js/client-v2/builders/TransactionBuilder.js +110 -0
- package/client-js/client-v2/consumer/ConsumerManager.js +390 -0
- package/client-js/client-v2/http/HttpClient.js +215 -0
- package/client-js/client-v2/http/LoadBalancer.js +50 -0
- package/client-js/client-v2/index.js +7 -0
- package/client-js/client-v2/utils/defaults.js +54 -0
- package/client-js/client-v2/utils/logger.js +54 -0
- package/client-js/client-v2/utils/validation.js +31 -0
- package/client-js/test-v2/AI_TEST_SUMMARY.md +226 -0
- package/client-js/test-v2/GETTING_STARTED.md +154 -0
- package/client-js/test-v2/ai_buffering.js +194 -0
- package/client-js/test-v2/ai_error_handling.js +223 -0
- package/client-js/test-v2/ai_lease_renewal.js +206 -0
- package/client-js/test-v2/ai_mixed_scenarios.js +278 -0
- package/client-js/test-v2/ai_priority.js +169 -0
- package/client-js/test-v2/ai_resources.js +217 -0
- package/client-js/test-v2/ai_ttl_retention.js +170 -0
- package/client-js/test-v2/complete.js +59 -0
- package/client-js/test-v2/consume.js +655 -0
- package/client-js/test-v2/dlq.js +82 -0
- package/client-js/test-v2/load.js +177 -0
- package/client-js/test-v2/pop.js +114 -0
- package/client-js/test-v2/push.js +333 -0
- package/client-js/test-v2/queue.js +39 -0
- package/client-js/test-v2/run.js +187 -0
- package/client-js/test-v2/subscription.js +354 -0
- package/client-js/test-v2/transaction.js +443 -0
- package/package.json +1 -1
|
@@ -0,0 +1,655 @@
|
|
|
1
|
+
export async function testConsumer(client) {
|
|
2
|
+
const queue = await client.queue('test-queue-v2-consume').create()
|
|
3
|
+
if (!queue.configured) {
|
|
4
|
+
return { success: false, message: 'Queue not created' }
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
await client
|
|
8
|
+
.queue('test-queue-v2-consume')
|
|
9
|
+
.push([{ data: { message: 'Hello, world!' } }])
|
|
10
|
+
|
|
11
|
+
let msgToReturn = null
|
|
12
|
+
|
|
13
|
+
await client
|
|
14
|
+
.queue('test-queue-v2-consume')
|
|
15
|
+
.batch(1)
|
|
16
|
+
.limit(1)
|
|
17
|
+
.each()
|
|
18
|
+
.consume(async msg => {
|
|
19
|
+
msgToReturn = msg
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
return { success: msgToReturn !== null, message: 'Consumer test completed successfully' }
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function testConsumerTrace(client) {
|
|
26
|
+
const queue = await client.queue('test-queue-v2-consume-trace').create()
|
|
27
|
+
if (!queue.configured) {
|
|
28
|
+
return { success: false, message: 'Queue not created' }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
await client
|
|
32
|
+
.queue('test-queue-v2-consume-trace')
|
|
33
|
+
.push([{ data: { message: 'Hello, world!' } }])
|
|
34
|
+
|
|
35
|
+
let msgToReturn = null
|
|
36
|
+
|
|
37
|
+
await client
|
|
38
|
+
.queue('test-queue-v2-consume-trace')
|
|
39
|
+
.batch(1)
|
|
40
|
+
.limit(1)
|
|
41
|
+
.each()
|
|
42
|
+
.consume(async msg => {
|
|
43
|
+
msgToReturn = msg
|
|
44
|
+
await msg.trace({
|
|
45
|
+
traceName: ['test-trace', 'test-trace-2'],
|
|
46
|
+
eventType: 'info',
|
|
47
|
+
data: { message: 'Hello, world!' }
|
|
48
|
+
})
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
return { success: msgToReturn !== null, message: 'Consumer test completed successfully' }
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export async function testConsumerNamespace(client) {
|
|
55
|
+
const queue = await client.queue('test-queue-v2-namespace')
|
|
56
|
+
.namespace('test-namespace')
|
|
57
|
+
.create()
|
|
58
|
+
if (!queue.configured) {
|
|
59
|
+
return { success: false, message: 'Queue not created' }
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
await client
|
|
63
|
+
.queue('test-queue-v2-namespace')
|
|
64
|
+
.push([{ data: { message: 'Hello, world!' } }])
|
|
65
|
+
|
|
66
|
+
let msgToReturn = null
|
|
67
|
+
|
|
68
|
+
await client
|
|
69
|
+
.queue()
|
|
70
|
+
.namespace('test-namespace')
|
|
71
|
+
.batch(1)
|
|
72
|
+
.limit(1)
|
|
73
|
+
.each()
|
|
74
|
+
.consume(async msg => {
|
|
75
|
+
msgToReturn = msg
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
return { success: msgToReturn !== null, message: 'Consumer test completed successfully' }
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export async function testConsumerTask(client) {
|
|
82
|
+
const queue = await client.queue('test-queue-v2-task')
|
|
83
|
+
.task('test-task')
|
|
84
|
+
.create()
|
|
85
|
+
if (!queue.configured) {
|
|
86
|
+
return { success: false, message: 'Queue not created' }
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
await client
|
|
90
|
+
.queue('test-queue-v2-task')
|
|
91
|
+
.push([{ data: { message: 'Hello, world!' } }])
|
|
92
|
+
|
|
93
|
+
let msgToReturn = null
|
|
94
|
+
|
|
95
|
+
await client
|
|
96
|
+
.queue()
|
|
97
|
+
.task('test-task')
|
|
98
|
+
.batch(1)
|
|
99
|
+
.limit(1)
|
|
100
|
+
.each()
|
|
101
|
+
.consume(async msg => {
|
|
102
|
+
msgToReturn = msg
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
return { success: msgToReturn !== null, message: 'Consumer test completed successfully' }
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export async function testConsumerWithPartition(client) {
|
|
109
|
+
const queue = await client.queue('test-queue-v2-consume-with-partition').create()
|
|
110
|
+
if (!queue.configured) {
|
|
111
|
+
return { success: false, message: 'Queue not created' }
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
for (let i = 0; i < 100; i++) {
|
|
115
|
+
await client
|
|
116
|
+
.queue('test-queue-v2-consume-with-partition')
|
|
117
|
+
.buffer({ messageCount: 100, timeMillis: 1000 })
|
|
118
|
+
.partition('test-partition-01')
|
|
119
|
+
.push([{ data: { message: 'Hello, world!' } }])
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
for (let i = 0; i < 100; i++) {
|
|
123
|
+
await client
|
|
124
|
+
.queue('test-queue-v2-consume-with-partition')
|
|
125
|
+
.buffer({ messageCount: 100, timeMillis: 1000 })
|
|
126
|
+
.partition('test-partition-02')
|
|
127
|
+
.push([{ data: { message: 'Hello, world!' } }])
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
let msgToReturn1 = null
|
|
131
|
+
let msgToReturn2 = null
|
|
132
|
+
await client
|
|
133
|
+
.queue('test-queue-v2-consume-with-partition')
|
|
134
|
+
.partition('test-partition-01')
|
|
135
|
+
.batch(100)
|
|
136
|
+
.limit(1)
|
|
137
|
+
.consume(async msgs => {
|
|
138
|
+
msgToReturn1 = msgs.length
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
await client
|
|
142
|
+
.queue('test-queue-v2-consume-with-partition')
|
|
143
|
+
.partition('test-partition-02')
|
|
144
|
+
.batch(100)
|
|
145
|
+
.limit(1)
|
|
146
|
+
.consume(async msgs => {
|
|
147
|
+
msgToReturn2 = msgs.length
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
return { success: msgToReturn1 == 100 && msgToReturn2 == 100, message: 'Consumer test completed successfully' }
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
export async function testConsumerBatchConsume(client) {
|
|
155
|
+
const queue = await client.queue('test-queue-v2-consume-batch').create()
|
|
156
|
+
if (!queue.configured) {
|
|
157
|
+
return { success: false, message: 'Queue not created' }
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
await client
|
|
161
|
+
.queue('test-queue-v2-consume-batch')
|
|
162
|
+
.push([
|
|
163
|
+
{ data: { message: 'Hello, world!' } },
|
|
164
|
+
{ data: { message: 'Hello, world 2!' } },
|
|
165
|
+
{ data: { message: 'Hello, world 3!' } }
|
|
166
|
+
])
|
|
167
|
+
|
|
168
|
+
let msgLength = 0
|
|
169
|
+
|
|
170
|
+
await client
|
|
171
|
+
.queue('test-queue-v2-consume-batch')
|
|
172
|
+
.batch(10)
|
|
173
|
+
.wait(false)
|
|
174
|
+
.limit(1)
|
|
175
|
+
.consume(async msgs => {
|
|
176
|
+
msgLength = msgs.length
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
return { success: msgLength === 3, message: 'Consumer test completed successfully' }
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export async function testConsumerOrdering(client) {
|
|
183
|
+
const queue = await client.queue('test-queue-v2-consume-batch').create()
|
|
184
|
+
if (!queue.configured) {
|
|
185
|
+
return { success: false, message: 'Queue not created' }
|
|
186
|
+
}
|
|
187
|
+
let messagesToPush = 100
|
|
188
|
+
|
|
189
|
+
for (let i = 0; i < messagesToPush; i++) {
|
|
190
|
+
await client
|
|
191
|
+
.queue('test-queue-v2-consume-batch')
|
|
192
|
+
.push([{ data: { id: i } }])
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
let lastId = null
|
|
197
|
+
await client
|
|
198
|
+
.queue('test-queue-v2-consume-batch')
|
|
199
|
+
.batch(1)
|
|
200
|
+
.wait(false)
|
|
201
|
+
.limit(messagesToPush)
|
|
202
|
+
.each()
|
|
203
|
+
.consume(async msg => {
|
|
204
|
+
if (lastId === null) {
|
|
205
|
+
lastId = msg.data.id
|
|
206
|
+
} else {
|
|
207
|
+
if (msg.data.id !== lastId + 1) {
|
|
208
|
+
return { success: false, message: 'Message ordering violation' }
|
|
209
|
+
}
|
|
210
|
+
lastId = msg.data.id
|
|
211
|
+
}
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
return { success: lastId === messagesToPush - 1, message: 'Consumer test completed successfully' }
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export async function testConsumerOrderingBatch(client) {
|
|
218
|
+
const queue = await client.queue('test-queue-v2-consume-batch-100').create()
|
|
219
|
+
if (!queue.configured) {
|
|
220
|
+
return { success: false, message: 'Queue not created' }
|
|
221
|
+
}
|
|
222
|
+
let messagesToPush = 100
|
|
223
|
+
|
|
224
|
+
for (let i = 0; i < messagesToPush; i++) {
|
|
225
|
+
await client
|
|
226
|
+
.queue('test-queue-v2-consume-batch-100')
|
|
227
|
+
.push([{ data: { id: i } }])
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
let lastId = null
|
|
231
|
+
await client
|
|
232
|
+
.queue('test-queue-v2-consume-batch-100')
|
|
233
|
+
.batch(messagesToPush)
|
|
234
|
+
.wait(false)
|
|
235
|
+
.limit(1)
|
|
236
|
+
.consume(async msgs => {
|
|
237
|
+
for (const msg of msgs) {
|
|
238
|
+
if (lastId === null) {
|
|
239
|
+
lastId = msg.data.id
|
|
240
|
+
} else {
|
|
241
|
+
if (msg.data.id !== lastId + 1) {
|
|
242
|
+
return { success: false, message: 'Message ordering violation' }
|
|
243
|
+
}
|
|
244
|
+
lastId = msg.data.id
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
})
|
|
248
|
+
|
|
249
|
+
return { success: lastId === messagesToPush - 1, message: 'Consumer test completed successfully' }
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
export async function testConsumerBatchConsumeBatch(client) {
|
|
254
|
+
const queue = await client.queue('test-queue-v2-consume-batch').create()
|
|
255
|
+
if (!queue.configured) {
|
|
256
|
+
return { success: false, message: 'Queue not created' }
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
await client
|
|
260
|
+
.queue('test-queue-v2-consume-batch')
|
|
261
|
+
.push([
|
|
262
|
+
{ data: { message: 'Hello, world!' } },
|
|
263
|
+
{ data: { message: 'Hello, world 2!' } },
|
|
264
|
+
{ data: { message: 'Hello, world 3!' } }
|
|
265
|
+
])
|
|
266
|
+
|
|
267
|
+
let msgLength = 0
|
|
268
|
+
|
|
269
|
+
await client
|
|
270
|
+
.queue('test-queue-v2-consume-batch')
|
|
271
|
+
.batch(10)
|
|
272
|
+
.wait(false)
|
|
273
|
+
.limit(1)
|
|
274
|
+
.consume(async msgs => {
|
|
275
|
+
msgLength = msgs.length
|
|
276
|
+
})
|
|
277
|
+
|
|
278
|
+
return { success: msgLength === 3, message: 'Consumer test completed successfully' }
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export async function testConsumerOrderingConcurrency(client) {
|
|
282
|
+
const queue = await client.queue('test-queue-v2-consume-batch-concurrency').create()
|
|
283
|
+
if (!queue.configured) {
|
|
284
|
+
return { success: false, message: 'Queue not created' }
|
|
285
|
+
}
|
|
286
|
+
let messagesToPush = 100
|
|
287
|
+
|
|
288
|
+
for (let i = 0; i < messagesToPush; i++) {
|
|
289
|
+
await client
|
|
290
|
+
.queue('test-queue-v2-consume-batch-concurrency')
|
|
291
|
+
.push([{ data: { id: i } }])
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
let lastId = null
|
|
295
|
+
await client
|
|
296
|
+
.queue('test-queue-v2-consume-batch-concurrency')
|
|
297
|
+
.concurrency(10)
|
|
298
|
+
.batch(1)
|
|
299
|
+
.wait(false)
|
|
300
|
+
.limit(10)
|
|
301
|
+
.each()
|
|
302
|
+
.consume(async msg => {
|
|
303
|
+
if (lastId === null) {
|
|
304
|
+
lastId = msg.data.id
|
|
305
|
+
} else {
|
|
306
|
+
if (msg.data.id !== lastId + 1) {
|
|
307
|
+
return { success: false, message: 'Message ordering violation' }
|
|
308
|
+
}
|
|
309
|
+
lastId = msg.data.id
|
|
310
|
+
}
|
|
311
|
+
})
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
return { success: lastId === messagesToPush - 1, message: 'Consumer test completed successfully' }
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
export async function testConsumerOrderingConcurrencyWithBufferedPush(client) {
|
|
318
|
+
const queue = await client.queue('test-queue-v2-consume-batch-concurrency-with-buffered-push').create()
|
|
319
|
+
if (!queue.configured) {
|
|
320
|
+
return { success: false, message: 'Queue not created' }
|
|
321
|
+
}
|
|
322
|
+
let messagesToPush = 100
|
|
323
|
+
|
|
324
|
+
for (let i = 0; i < messagesToPush; i++) {
|
|
325
|
+
await client
|
|
326
|
+
.queue('test-queue-v2-consume-batch-concurrency-with-buffered-push')
|
|
327
|
+
.buffer({ messageCount: 100, timeMillis: 1000 })
|
|
328
|
+
.push([{ data: { id: i } }])
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
let lastId = null
|
|
332
|
+
await client
|
|
333
|
+
.queue('test-queue-v2-consume-batch-concurrency-with-buffered-push')
|
|
334
|
+
.concurrency(10)
|
|
335
|
+
.batch(10)
|
|
336
|
+
.wait(false)
|
|
337
|
+
.limit(10)
|
|
338
|
+
.each()
|
|
339
|
+
.consume(async msg => {
|
|
340
|
+
if (lastId === null) {
|
|
341
|
+
lastId = msg.data.id
|
|
342
|
+
} else {
|
|
343
|
+
if (msg.data.id !== lastId + 1) {
|
|
344
|
+
return { success: false, message: 'Message ordering violation' }
|
|
345
|
+
}
|
|
346
|
+
lastId = msg.data.id
|
|
347
|
+
}
|
|
348
|
+
})
|
|
349
|
+
|
|
350
|
+
return { success: lastId === messagesToPush - 1, message: 'Consumer test completed successfully' }
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
export async function consumerGroup(client) {
|
|
354
|
+
const queue = await client.queue('test-queue-v2-consume-group').create()
|
|
355
|
+
if (!queue.configured) {
|
|
356
|
+
return { success: false, message: 'Queue not created' }
|
|
357
|
+
}
|
|
358
|
+
let messagesToPush = 100
|
|
359
|
+
|
|
360
|
+
for (let i = 0; i < messagesToPush; i++) {
|
|
361
|
+
await client
|
|
362
|
+
.queue('test-queue-v2-consume-group')
|
|
363
|
+
.buffer({ messageCount: 100, timeMillis: 1000 })
|
|
364
|
+
.push([{ data: { id: i } }])
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
let group01Messages = 0
|
|
369
|
+
let group02Messages = 0
|
|
370
|
+
|
|
371
|
+
await client
|
|
372
|
+
.queue('test-queue-v2-consume-group')
|
|
373
|
+
.group('test-group-01')
|
|
374
|
+
.batch(messagesToPush)
|
|
375
|
+
.limit(1)
|
|
376
|
+
.wait(false)
|
|
377
|
+
.consume(async msgs => {
|
|
378
|
+
group01Messages = msgs.length
|
|
379
|
+
})
|
|
380
|
+
|
|
381
|
+
await client
|
|
382
|
+
.queue('test-queue-v2-consume-group')
|
|
383
|
+
.group('test-group-02')
|
|
384
|
+
.batch(messagesToPush)
|
|
385
|
+
.limit(1)
|
|
386
|
+
.wait(false)
|
|
387
|
+
.consume(async msgs => {
|
|
388
|
+
group02Messages = msgs.length
|
|
389
|
+
})
|
|
390
|
+
|
|
391
|
+
return { success: group01Messages === messagesToPush && group02Messages === messagesToPush, message: 'Consumer test completed successfully' }
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
export async function consumerGroupWithPartition(client) {
|
|
395
|
+
const queue = await client.queue('test-queue-v2-consume-group-with-partition').create()
|
|
396
|
+
if (!queue.configured) {
|
|
397
|
+
return { success: false, message: 'Queue not created' }
|
|
398
|
+
}
|
|
399
|
+
let messagesToPush = 100
|
|
400
|
+
|
|
401
|
+
for (let i = 0; i < messagesToPush; i++) {
|
|
402
|
+
await client
|
|
403
|
+
.queue('test-queue-v2-consume-group-with-partition')
|
|
404
|
+
.partition('test-partition-01')
|
|
405
|
+
.buffer({ messageCount: 100, timeMillis: 1000 })
|
|
406
|
+
.push([{ data: { id: i } }])
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
let group01Messages = 0
|
|
411
|
+
let group02Messages = 0
|
|
412
|
+
|
|
413
|
+
await client
|
|
414
|
+
.queue('test-queue-v2-consume-group-with-partition')
|
|
415
|
+
.partition('test-partition-01')
|
|
416
|
+
.group('test-group-01')
|
|
417
|
+
.batch(messagesToPush)
|
|
418
|
+
.limit(1)
|
|
419
|
+
.wait(false)
|
|
420
|
+
.consume(async msgs => {
|
|
421
|
+
group01Messages = msgs.length
|
|
422
|
+
})
|
|
423
|
+
|
|
424
|
+
await client
|
|
425
|
+
.queue('test-queue-v2-consume-group-with-partition')
|
|
426
|
+
.partition('test-partition-01')
|
|
427
|
+
.group('test-group-02')
|
|
428
|
+
.batch(messagesToPush)
|
|
429
|
+
.limit(1)
|
|
430
|
+
.wait(false)
|
|
431
|
+
.consume(async msgs => {
|
|
432
|
+
group02Messages = msgs.length
|
|
433
|
+
})
|
|
434
|
+
|
|
435
|
+
return { success: group01Messages === messagesToPush && group02Messages === messagesToPush, message: 'Consumer test completed successfully' }
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
export async function manualAck(client) {
|
|
439
|
+
const queue = await client
|
|
440
|
+
.queue('test-queue-v2-manual-ack')
|
|
441
|
+
.create()
|
|
442
|
+
if (!queue.configured) {
|
|
443
|
+
return { success: false, message: 'Queue not created' }
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const messagesToPush = 10000;
|
|
447
|
+
|
|
448
|
+
let messages = [];
|
|
449
|
+
for (let i = 0; i < messagesToPush; i++) {
|
|
450
|
+
messages.push({ data: { id: i } })
|
|
451
|
+
if (messages.length >= 1000) {
|
|
452
|
+
await client.queue('test-queue-v2-manual-ack').push(messages)
|
|
453
|
+
messages = [];
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
await client.queue('test-queue-v2-manual-ack').push(messages)
|
|
457
|
+
|
|
458
|
+
let uniqueIds = new Set();
|
|
459
|
+
let lastId = null;
|
|
460
|
+
|
|
461
|
+
await client
|
|
462
|
+
.queue('test-queue-v2-manual-ack')
|
|
463
|
+
.concurrency(10)
|
|
464
|
+
.batch(1000)
|
|
465
|
+
.wait(false)
|
|
466
|
+
.limit(1)
|
|
467
|
+
.consume(async msgs => {
|
|
468
|
+
for (const msg of msgs) {
|
|
469
|
+
if (lastId === null) {
|
|
470
|
+
lastId = msg.data.id
|
|
471
|
+
} else {
|
|
472
|
+
if (msg.data.id !== lastId + 1) {
|
|
473
|
+
throw new Error('Message ordering violation')
|
|
474
|
+
}
|
|
475
|
+
lastId = msg.data.id
|
|
476
|
+
}
|
|
477
|
+
uniqueIds.add(msg.data.id)
|
|
478
|
+
}
|
|
479
|
+
})
|
|
480
|
+
.onSuccess(async (msgs, result) => {
|
|
481
|
+
await client.ack(msgs, true)
|
|
482
|
+
})
|
|
483
|
+
.onError(async (msgs, error) => {
|
|
484
|
+
await client.ack(msgs, false)
|
|
485
|
+
})
|
|
486
|
+
|
|
487
|
+
const uniqueIdsCount = uniqueIds.size;
|
|
488
|
+
|
|
489
|
+
return { success: uniqueIdsCount === messagesToPush, message: 'Load test completed successfully' }
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
export async function retries(client) {
|
|
493
|
+
const queue = await client
|
|
494
|
+
.queue('test-queue-v2-retries')
|
|
495
|
+
.config({
|
|
496
|
+
retryLimit: 3
|
|
497
|
+
})
|
|
498
|
+
.create()
|
|
499
|
+
if (!queue.configured) {
|
|
500
|
+
return { success: false, message: 'Queue not created' }
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
const messagesToPush = 100;
|
|
504
|
+
|
|
505
|
+
let messages = [];
|
|
506
|
+
for (let i = 0; i < messagesToPush; i++) {
|
|
507
|
+
messages.push({ data: { id: i } })
|
|
508
|
+
}
|
|
509
|
+
await client.queue('test-queue-v2-retries').push(messages)
|
|
510
|
+
|
|
511
|
+
let attemptCount = 0
|
|
512
|
+
|
|
513
|
+
await client
|
|
514
|
+
.queue('test-queue-v2-retries')
|
|
515
|
+
.concurrency(1)
|
|
516
|
+
.batch(100)
|
|
517
|
+
.wait(false)
|
|
518
|
+
.limit(300) // Allow up to 300 messages (3 batches of 100)
|
|
519
|
+
.consume(async msgs => {
|
|
520
|
+
attemptCount++;
|
|
521
|
+
if (attemptCount < 3) {
|
|
522
|
+
// Fail first 2 attempts, succeed on 3rd
|
|
523
|
+
throw new Error('Test error - triggering retry')
|
|
524
|
+
}
|
|
525
|
+
// Third attempt succeeds (no error thrown)
|
|
526
|
+
})
|
|
527
|
+
|
|
528
|
+
return { success: attemptCount === 3, message: `Retry test completed successfully (attempts: ${attemptCount})` }
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
export async function retriesConsumerGroup(client) {
|
|
532
|
+
const queue = await client
|
|
533
|
+
.queue('test-queue-v2-retries-consumer-group')
|
|
534
|
+
.config({
|
|
535
|
+
retryLimit: 3
|
|
536
|
+
})
|
|
537
|
+
.create()
|
|
538
|
+
if (!queue.configured) {
|
|
539
|
+
return { success: false, message: 'Queue not created' }
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
const messagesToPush = 100;
|
|
543
|
+
|
|
544
|
+
let messages = [];
|
|
545
|
+
for (let i = 0; i < messagesToPush; i++) {
|
|
546
|
+
messages.push({ data: { id: i } })
|
|
547
|
+
}
|
|
548
|
+
await client.queue('test-queue-v2-retries-consumer-group').push(messages)
|
|
549
|
+
|
|
550
|
+
let attemptCount = 0
|
|
551
|
+
|
|
552
|
+
await client
|
|
553
|
+
.queue('test-queue-v2-retries-consumer-group')
|
|
554
|
+
.group('test-group-01')
|
|
555
|
+
.concurrency(1)
|
|
556
|
+
.batch(100)
|
|
557
|
+
.wait(false)
|
|
558
|
+
.limit(300) // Allow up to 300 messages (3 batches of 100)
|
|
559
|
+
.autoAck(true) // Auto-ack on success, auto-NACK on failure
|
|
560
|
+
.consume(async msgs => {
|
|
561
|
+
console.log('Group 01: ' + msgs.length)
|
|
562
|
+
attemptCount++;
|
|
563
|
+
if (attemptCount < 3) {
|
|
564
|
+
// Fail first 2 attempts, succeed on 3rd
|
|
565
|
+
throw new Error('Test error - triggering retry')
|
|
566
|
+
}
|
|
567
|
+
// Third attempt succeeds (no error thrown)
|
|
568
|
+
})
|
|
569
|
+
|
|
570
|
+
let group02Messages = 0
|
|
571
|
+
|
|
572
|
+
await client
|
|
573
|
+
.queue('test-queue-v2-retries-consumer-group')
|
|
574
|
+
.group('test-group-02')
|
|
575
|
+
.concurrency(1)
|
|
576
|
+
.batch(100)
|
|
577
|
+
.wait(false)
|
|
578
|
+
.limit(100) // Allow up to 300 messages (3 batches of 100)
|
|
579
|
+
.autoAck(true) // Auto-ack on success, auto-NACK on failure
|
|
580
|
+
.consume(async msgs => {
|
|
581
|
+
console.log('Group 02: ' + msgs.length)
|
|
582
|
+
group02Messages += msgs.length
|
|
583
|
+
})
|
|
584
|
+
|
|
585
|
+
return { success: attemptCount == 3 && group02Messages === messagesToPush, message: `Retry test completed successfully (attempts: ${attemptCount}, group02: ${group02Messages})` }
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
export async function autoRenewLease(client) {
|
|
589
|
+
const queue = await client
|
|
590
|
+
.queue('test-queue-v2-auto-renew-lease')
|
|
591
|
+
.config({
|
|
592
|
+
leaseTime: 3
|
|
593
|
+
})
|
|
594
|
+
.create()
|
|
595
|
+
if (!queue.configured) {
|
|
596
|
+
return { success: false, message: 'Queue not created' }
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
await client
|
|
600
|
+
.queue('test-queue-v2-auto-renew-lease')
|
|
601
|
+
.push([{ data: { message: 'Long processing task' } }])
|
|
602
|
+
|
|
603
|
+
let shouldFailHasFailed = false;
|
|
604
|
+
|
|
605
|
+
await client
|
|
606
|
+
.queue('test-queue-v2-auto-renew-lease')
|
|
607
|
+
.batch(1)
|
|
608
|
+
.wait(false)
|
|
609
|
+
.limit(1)
|
|
610
|
+
.each()
|
|
611
|
+
.consume(async msg => {
|
|
612
|
+
console.log('Message: ' + msg.data.message)
|
|
613
|
+
await new Promise(resolve => setTimeout(resolve, 5000))
|
|
614
|
+
})
|
|
615
|
+
.onSuccess(async (msgs, result) => {
|
|
616
|
+
// This shoudl fail if not auto-renewed
|
|
617
|
+
const resultAck = await client.ack(msgs, true)
|
|
618
|
+
if (resultAck.success === false && resultAck.includes('invalid_lease')) {
|
|
619
|
+
shouldFailHasFailed = true;
|
|
620
|
+
}
|
|
621
|
+
})
|
|
622
|
+
.onError(async (msgs, error) => {
|
|
623
|
+
await client.ack(msgs, false)
|
|
624
|
+
})
|
|
625
|
+
|
|
626
|
+
await client
|
|
627
|
+
.queue('test-queue-v2-auto-renew-lease')
|
|
628
|
+
.push([{ data: { message: 'Long processing task' } }])
|
|
629
|
+
|
|
630
|
+
let shouldPassHasPass = false;
|
|
631
|
+
|
|
632
|
+
await client
|
|
633
|
+
.queue('test-queue-v2-auto-renew-lease')
|
|
634
|
+
.batch(1)
|
|
635
|
+
.wait(false)
|
|
636
|
+
.limit(1)
|
|
637
|
+
.renewLease(true, 1000)
|
|
638
|
+
.each()
|
|
639
|
+
.consume(async msg => {
|
|
640
|
+
console.log('Message: ' + msg.data.message)
|
|
641
|
+
await new Promise(resolve => setTimeout(resolve, 5000))
|
|
642
|
+
})
|
|
643
|
+
.onSuccess(async (msgs, result) => {
|
|
644
|
+
// This shoudl pass, if auto-renewed
|
|
645
|
+
const resultAck = await client.ack(msgs, true)
|
|
646
|
+
if (resultAck.success === true) {
|
|
647
|
+
shouldPassHasPass = true;
|
|
648
|
+
}
|
|
649
|
+
})
|
|
650
|
+
.onError(async (msgs, error) => {
|
|
651
|
+
await client.ack(msgs, false)
|
|
652
|
+
})
|
|
653
|
+
|
|
654
|
+
return { success: shouldFailHasFailed === false && shouldPassHasPass === true, message: 'Auto renew lease test completed successfully' }
|
|
655
|
+
}
|