fix(run-engine): keep the ck vtime floor alive alongside the tags it scores

The gated-registration path in the vtime dequeue was the one writer that touched
:ckVtime without also touching :ckVtimeFloor. Everything else keeps the pair
alive together: the enqueue and nack registrations EXPIRE both, and a serving
dequeue SETs the floor with its own TTL. That path runs on calls that serve
nothing, so the floor-persist block, which is guarded on having served, is
skipped.

A base queue whose variants are all sat at their per-key ceiling therefore
refreshes the tags on every poll while the floor's TTL runs down underneath them.
Once it expires the next registration reads GET ckVtimeFloorKey back as '0' and
starts a brand-new variant below every established tag, so it leads pass 1 until
it catches up. Same hole as the one the enqueue floor-TTL test was added to close,
reached by a different path.

Reported by Devin on #4367.
This commit is contained in:
Wes Mason
2026-08-20 00:04:11 +01:00
parent ac5b103a07
commit 0c6992eb4a
@@ -5643,6 +5643,13 @@ if gatedPending ~= nil then
end
end
redis.call('EXPIRE', ckVtimeKey, stateTtl)
-- This is the one write path that touches ckVtime without going through the
-- floor-persist block below, which only runs when the call served something. Left
-- alone, a queue whose variants are all gated refreshes ckVtime's TTL here on every
-- poll while the floor's runs down, and once the floor expires out from under a live
-- ckVtime the next registration reads it back as 0 and starts a brand-new variant
-- below every established tag.
redis.call('SET', ckVtimeFloorKey, tostring(floor), 'EX', stateTtl)
end
end