@@ -542,6 +542,60 @@ export class MarQS {
542
542
) ;
543
543
}
544
544
545
+ public async releaseConcurrency ( messageId : string , releaseForRun : boolean = false ) {
546
+ return this . #trace(
547
+ "releaseConcurrency" ,
548
+ async ( span ) => {
549
+ span . setAttributes ( {
550
+ [ SemanticAttributes . MESSAGE_ID ] : messageId ,
551
+ } ) ;
552
+
553
+ const message = await this . readMessage ( messageId ) ;
554
+
555
+ if ( ! message ) {
556
+ return ;
557
+ }
558
+
559
+ span . setAttributes ( {
560
+ [ SemanticAttributes . QUEUE ] : message . queue ,
561
+ [ SemanticAttributes . MESSAGE_ID ] : message . messageId ,
562
+ [ SemanticAttributes . CONCURRENCY_KEY ] : message . concurrencyKey ,
563
+ [ SemanticAttributes . PARENT_QUEUE ] : message . parentQueue ,
564
+ } ) ;
565
+
566
+ const concurrencyKey = this . keys . currentConcurrencyKeyFromQueue ( message . queue ) ;
567
+ const envConcurrencyKey = this . keys . envCurrentConcurrencyKeyFromQueue ( message . queue ) ;
568
+ const orgConcurrencyKey = this . keys . orgCurrentConcurrencyKeyFromQueue ( message . queue ) ;
569
+
570
+ logger . debug ( "Calling releaseConcurrency" , {
571
+ messageId,
572
+ queue : message . queue ,
573
+ concurrencyKey,
574
+ envConcurrencyKey,
575
+ orgConcurrencyKey,
576
+ service : this . name ,
577
+ releaseForRun,
578
+ } ) ;
579
+
580
+ return this . redis . releaseConcurrency (
581
+ //don't release the for the run, it breaks concurrencyLimits
582
+ releaseForRun ? concurrencyKey : "" ,
583
+ envConcurrencyKey ,
584
+ orgConcurrencyKey ,
585
+ message . messageId
586
+ ) ;
587
+ } ,
588
+ {
589
+ kind : SpanKind . CONSUMER ,
590
+ attributes : {
591
+ [ SEMATTRS_MESSAGING_OPERATION ] : "releaseConcurrency" ,
592
+ [ SEMATTRS_MESSAGE_ID ] : messageId ,
593
+ [ SEMATTRS_MESSAGING_SYSTEM ] : "marqs" ,
594
+ } ,
595
+ }
596
+ ) ;
597
+ }
598
+
545
599
async #trace< T > (
546
600
name : string ,
547
601
fn : ( span : Span ) => Promise < T > ,
@@ -1488,6 +1542,24 @@ end
1488
1542
` ,
1489
1543
} ) ;
1490
1544
1545
+ this . redis . defineCommand ( "releaseConcurrency" , {
1546
+ numberOfKeys : 3 ,
1547
+ lua : `
1548
+ local concurrencyKey = KEYS[1]
1549
+ local envCurrentConcurrencyKey = KEYS[2]
1550
+ local orgCurrentConcurrencyKey = KEYS[3]
1551
+
1552
+ local messageId = ARGV[1]
1553
+
1554
+ -- Update the concurrency keys
1555
+ if concurrencyKey ~= "" then
1556
+ redis.call('SREM', concurrencyKey, messageId)
1557
+ end
1558
+ redis.call('SREM', envCurrentConcurrencyKey, messageId)
1559
+ redis.call('SREM', orgCurrentConcurrencyKey, messageId)
1560
+ ` ,
1561
+ } ) ;
1562
+
1491
1563
this . redis . defineCommand ( "heartbeatMessage" , {
1492
1564
numberOfKeys : 1 ,
1493
1565
lua : `
@@ -1699,6 +1771,14 @@ declare module "ioredis" {
1699
1771
callback ?: Callback < void >
1700
1772
) : Result < void , Context > ;
1701
1773
1774
+ releaseConcurrency (
1775
+ concurrencyKey : string ,
1776
+ envConcurrencyKey : string ,
1777
+ orgConcurrencyKey : string ,
1778
+ messageId : string ,
1779
+ callback ?: Callback < void >
1780
+ ) : Result < void , Context > ;
1781
+
1702
1782
heartbeatMessage (
1703
1783
visibilityQueue : string ,
1704
1784
messageId : string ,
0 commit comments