From 31c8fde33641daf76ce2f427006f06a048588f9d Mon Sep 17 00:00:00 2001 From: yumoqing Date: Wed, 5 Aug 2026 12:05:30 +0800 Subject: [PATCH] fix(balance): replace GETDEL with GET+DEL in Lua scripts for Redis 6.0 compat GETDEL requires Redis 6.2+; server runs 6.0.16, so every finalize_balance and refund_balance call failed silently ('Unknown Redis command called from Lua script'). Consequences observed under concurrent load test: - reserve:* keys leaked until 600s TTL instead of being released at finalize - balance:{org} never reconciled with actual cost (over-deduction by max_cost-actual accumulated per call) - FAILED-request refunds silently lost GET+DEL inside a Lua script executes atomically (single-threaded), so the pop semantics are unchanged. --- llmage/balance.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/llmage/balance.py b/llmage/balance.py index 7ba1be2..1506deb 100644 --- a/llmage/balance.py +++ b/llmage/balance.py @@ -98,11 +98,12 @@ local cost_key = KEYS[1] local reserve_key = KEYS[2] local actual_cost = tonumber(ARGV[1]) --- Atomically pop reserve -local reserve_val = redis.call('GETDEL', reserve_key) +-- Atomically pop reserve (GET+DEL is atomic inside a Lua script; GETDEL needs Redis 6.2+) +local reserve_val = redis.call('GET', reserve_key) if not reserve_val then return {0, 'no reserve'} end +redis.call('DEL', reserve_key) -- Parse: userorgid|llmid|max_cost local i = 1 @@ -135,10 +136,11 @@ return {1, userorgid, max_cost, actual_cost, diff} REFUND_LUA = """ local reserve_key = KEYS[1] -local reserve_val = redis.call('GETDEL', reserve_key) +local reserve_val = redis.call('GET', reserve_key) if not reserve_val then return {0, 'no reserve'} end +redis.call('DEL', reserve_key) local i = 1 local userorgid, llmid, max_cost