Skip to content

Commit d4dd340

Browse files
committed
feat(run-engine): enforce per-key limit overrides at admit time
The ck dequeue admit and both enqueue fast paths read the queue's ckLimits HASH for the variant being admitted and use the env-clamped override in place of the queue's per-key limit, behind the totalConcurrencyEnabled flag. Covered by tests for lowered and raised keys, removal, the cardinality cap, and flag-off behavior.
1 parent b8f9e21 commit d4dd340

2 files changed

Lines changed: 304 additions & 4 deletions

File tree

‎internal-packages/run-engine/src/run-queue/index.ts‎

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2449,6 +2449,7 @@ export class RunQueue {
24492449
const totalConcurrencyLimitKey = this.keys.queueTotalConcurrencyLimitKeyFromQueue(
24502450
message.queue
24512451
);
2452+
const ckLimitsKey = this.keys.queueCkLimitsKeyFromQueue(message.queue);
24522453
const totalConcurrencyEnabledArg = this.options.totalConcurrencyEnabled ? "1" : "0";
24532454

24542455
if (ttlInfo) {
@@ -2472,6 +2473,7 @@ export class RunQueue {
24722473
baseQueueKey,
24732474
groupConcurrencyKey,
24742475
totalConcurrencyLimitKey,
2476+
ckLimitsKey,
24752477
// args
24762478
queueName,
24772479
messageId,
@@ -2511,6 +2513,7 @@ export class RunQueue {
25112513
baseQueueKey,
25122514
groupConcurrencyKey,
25132515
totalConcurrencyLimitKey,
2516+
ckLimitsKey,
25142517
// args
25152518
queueName,
25162519
messageId,
@@ -2798,6 +2801,7 @@ export class RunQueue {
27982801
runningCounterKey,
27992802
this.keys.queueGroupConcurrencyKeyFromQueue(ckWildcardQueue),
28002803
this.keys.queueTotalConcurrencyLimitKeyFromQueue(ckWildcardQueue),
2804+
this.keys.queueCkLimitsKeyFromQueue(ckWildcardQueue),
28012805
//args
28022806
ckWildcardQueue,
28032807
String(Date.now()),
@@ -4086,7 +4090,7 @@ return __qmret(0)
40864090
// *Tracked variants of dequeueMessageFromKey and the ack/nack/dlq/release/clear
40874091
// scripts.
40884092
this.redis.defineCommand("enqueueMessageCkTracked", {
4089-
numberOfKeys: 17,
4093+
numberOfKeys: 18,
40904094
lua: `
40914095
local masterQueueKey = KEYS[1]
40924096
local queueKey = KEYS[2]
@@ -4108,6 +4112,7 @@ local baseQueueKey = KEYS[15]
41084112
-- Total-cap keys (KEYS 16-17)
41094113
local groupConcurrencyKey = KEYS[16]
41104114
local totalConcurrencyLimitKey = KEYS[17]
4115+
local ckLimitsKey = KEYS[18]
41114116
41124117
local queueName = ARGV[1]
41134118
local messageId = ARGV[2]
@@ -4145,6 +4150,12 @@ if enableFastPath == '1' then
41454150
tonumber(redis.call('GET', queueConcurrencyLimitKey) or '1000000'),
41464151
envLimit
41474152
)
4153+
if totalConcurrencyEnabled then
4154+
local perKeyOverride = redis.call('HGET', ckLimitsKey, queueName)
4155+
if perKeyOverride then
4156+
queueLimit = math.min(tonumber(perKeyOverride), envLimit)
4157+
end
4158+
end
41484159
41494160
if queueCurrent < queueLimit then
41504161
-- Total-cap gate: a fast-path admit consumes a group slot, so it must
@@ -4256,7 +4267,7 @@ return __qmret(0)
42564267
});
42574268

42584269
this.redis.defineCommand("enqueueMessageWithTtlCkTracked", {
4259-
numberOfKeys: 18,
4270+
numberOfKeys: 19,
42604271
lua: `
42614272
local masterQueueKey = KEYS[1]
42624273
local queueKey = KEYS[2]
@@ -4279,6 +4290,7 @@ local baseQueueKey = KEYS[16]
42794290
-- Total-cap keys (KEYS 17-18)
42804291
local groupConcurrencyKey = KEYS[17]
42814292
local totalConcurrencyLimitKey = KEYS[18]
4293+
local ckLimitsKey = KEYS[19]
42824294
42834295
local queueName = ARGV[1]
42844296
local messageId = ARGV[2]
@@ -4318,6 +4330,12 @@ if enableFastPath == '1' then
43184330
tonumber(redis.call('GET', queueConcurrencyLimitKey) or '1000000'),
43194331
envLimit
43204332
)
4333+
if totalConcurrencyEnabled then
4334+
local perKeyOverride = redis.call('HGET', ckLimitsKey, queueName)
4335+
if perKeyOverride then
4336+
queueLimit = math.min(tonumber(perKeyOverride), envLimit)
4337+
end
4338+
end
43214339
43224340
if queueCurrent < queueLimit then
43234341
-- Total-cap gate: see enqueueMessageCkTracked.
@@ -4942,7 +4960,7 @@ return results
49424960
// (normal dequeue, TTL-expired, or stale-orphan path — all of which were
49434961
// counted at enqueue time).
49444962
this.redis.defineCommand("dequeueMessagesFromCkQueueTracked", {
4945-
numberOfKeys: 13,
4963+
numberOfKeys: 14,
49464964
lua: `
49474965
local ckIndexKey = KEYS[1]
49484966
local queueConcurrencyLimitKey = KEYS[2]
@@ -4957,6 +4975,7 @@ local lengthCounterKey = KEYS[10]
49574975
local runningCounterKey = KEYS[11]
49584976
local groupConcurrencyKey = KEYS[12]
49594977
local totalConcurrencyLimitKey = KEYS[13]
4978+
local ckLimitsKey = KEYS[14]
49604979
49614980
local ckWildcardName = ARGV[1]
49624981
local currentTime = tonumber(ARGV[2])
@@ -5046,7 +5065,15 @@ for _, ckQueueName in ipairs(ckQueues) do
50465065
local ckConcurrencyKey = fullQueueKey .. ':currentConcurrency'
50475066
local ckCurrentConcurrency = tonumber(redis.call('SCARD', ckConcurrencyKey) or '0')
50485067
5049-
if ckCurrentConcurrency < queueConcurrencyLimit then
5068+
local perKeyLimit = queueConcurrencyLimit
5069+
if totalConcurrencyEnabled then
5070+
local perKeyOverride = redis.call('HGET', ckLimitsKey, ckQueueName)
5071+
if perKeyOverride then
5072+
perKeyLimit = math.min(tonumber(perKeyOverride), envConcurrencyLimit)
5073+
end
5074+
end
5075+
5076+
if ckCurrentConcurrency < perKeyLimit then
50505077
local messages = redis.call('ZRANGEBYSCORE', fullQueueKey, '-inf', tostring(currentTime), 'WITHSCORES', 'LIMIT', 0, 1)
50515078
50525079
if #messages >= 2 then
@@ -6537,6 +6564,7 @@ declare module "@internal/redis" {
65376564
baseQueueKey: string,
65386565
groupConcurrencyKey: string,
65396566
totalConcurrencyLimitKey: string,
6567+
ckLimitsKey: string,
65406568
queueName: string,
65416569
messageId: string,
65426570
messageData: string,
@@ -6574,6 +6602,7 @@ declare module "@internal/redis" {
65746602
baseQueueKey: string,
65756603
groupConcurrencyKey: string,
65766604
totalConcurrencyLimitKey: string,
6605+
ckLimitsKey: string,
65776606
queueName: string,
65786607
messageId: string,
65796608
messageData: string,
@@ -6608,6 +6637,7 @@ declare module "@internal/redis" {
66086637
runningCounterKey: string,
66096638
groupConcurrencyKey: string,
66106639
totalConcurrencyLimitKey: string,
6640+
ckLimitsKey: string,
66116641
ckWildcardName: string,
66126642
currentTime: string,
66136643
defaultEnvConcurrencyLimit: string,

0 commit comments

Comments
 (0)