@@ -27,6 +27,7 @@ export type QueueItem<TMessageCatalog extends MessageCatalogSchema> = {
27
27
visibilityTimeoutMs : number ;
28
28
attempt : number ;
29
29
timestamp : Date ;
30
+ deduplicationKey ?: string ;
30
31
} ;
31
32
32
33
export type AnyQueueItem = {
@@ -36,6 +37,7 @@ export type AnyQueueItem = {
36
37
visibilityTimeoutMs : number ;
37
38
attempt : number ;
38
39
timestamp : Date ;
40
+ deduplicationKey ?: string ;
39
41
} ;
40
42
41
43
export class SimpleQueue < TMessageCatalog extends MessageCatalogSchema > {
@@ -98,11 +100,13 @@ export class SimpleQueue<TMessageCatalog extends MessageCatalogSchema> {
98
100
} ) : Promise < void > {
99
101
try {
100
102
const score = availableAt ? availableAt . getTime ( ) : Date . now ( ) ;
103
+ const deduplicationKey = nanoid ( ) ;
101
104
const serializedItem = JSON . stringify ( {
102
105
job,
103
106
item,
104
107
visibilityTimeoutMs,
105
108
attempt,
109
+ deduplicationKey,
106
110
} ) ;
107
111
108
112
const result = await this . redis . enqueueItem (
@@ -136,7 +140,7 @@ export class SimpleQueue<TMessageCatalog extends MessageCatalogSchema> {
136
140
return [ ] ;
137
141
}
138
142
139
- const dequeuedItems = [ ] ;
143
+ const dequeuedItems : Array < QueueItem < TMessageCatalog > > = [ ] ;
140
144
141
145
for ( const [ id , serializedItem , score ] of results ) {
142
146
const parsedItem = JSON . parse ( serializedItem ) as any ;
@@ -186,6 +190,7 @@ export class SimpleQueue<TMessageCatalog extends MessageCatalogSchema> {
186
190
visibilityTimeoutMs,
187
191
attempt : parsedItem . attempt ?? 0 ,
188
192
timestamp,
193
+ deduplicationKey : parsedItem . deduplicationKey ,
189
194
} ) ;
190
195
}
191
196
@@ -200,14 +205,26 @@ export class SimpleQueue<TMessageCatalog extends MessageCatalogSchema> {
200
205
}
201
206
}
202
207
203
- async ack ( id : string ) : Promise < void > {
208
+ async ack ( id : string , deduplicationKey ?: string ) : Promise < void > {
204
209
try {
205
- await this . redis . ackItem ( `queue` , `items` , id ) ;
210
+ const result = await this . redis . ackItem ( `queue` , `items` , id , deduplicationKey ?? "" ) ;
211
+ if ( result !== 1 ) {
212
+ this . logger . debug (
213
+ `SimpleQueue ${ this . name } .ack(): ack operation returned ${ result } . This means it was not removed from the queue.` ,
214
+ {
215
+ queue : this . name ,
216
+ id,
217
+ deduplicationKey,
218
+ result,
219
+ }
220
+ ) ;
221
+ }
206
222
} catch ( e ) {
207
223
this . logger . error ( `SimpleQueue ${ this . name } .ack(): error acknowledging item` , {
208
224
queue : this . name ,
209
225
error : e ,
210
226
id,
227
+ deduplicationKey,
211
228
} ) ;
212
229
throw e ;
213
230
}
@@ -367,15 +384,32 @@ export class SimpleQueue<TMessageCatalog extends MessageCatalogSchema> {
367
384
this . redis . defineCommand ( "ackItem" , {
368
385
numberOfKeys : 2 ,
369
386
lua : `
370
- local queue = KEYS[1]
371
- local items = KEYS[2]
387
+ local queueKey = KEYS[1]
388
+ local itemsKey = KEYS[2]
372
389
local id = ARGV[1]
390
+ local deduplicationKey = ARGV[2]
373
391
374
- redis.call('ZREM', queue, id)
375
- redis.call('HDEL', items, id)
392
+ -- Get the item from the hash
393
+ local item = redis.call('HGET', itemsKey, id)
394
+ if not item then
395
+ return -1
396
+ end
376
397
398
+ -- Only check deduplicationKey if a non-empty one was passed in
399
+ if deduplicationKey and deduplicationKey ~= "" then
400
+ local success, parsed = pcall(cjson.decode, item)
401
+ if success then
402
+ if parsed.deduplicationKey and parsed.deduplicationKey ~= deduplicationKey then
403
+ return 0
404
+ end
405
+ end
406
+ end
407
+
408
+ -- Remove from sorted set and hash
409
+ redis.call('ZREM', queueKey, id)
410
+ redis.call('HDEL', itemsKey, id)
377
411
return 1
378
- ` ,
412
+ ` ,
379
413
} ) ;
380
414
381
415
this . redis . defineCommand ( "moveToDeadLetterQueue" , {
@@ -468,6 +502,7 @@ declare module "@internal/redis" {
468
502
queue : string ,
469
503
items : string ,
470
504
id : string ,
505
+ deduplicationKey : string ,
471
506
callback ?: Callback < number >
472
507
) : Result < number , Context > ;
473
508
0 commit comments