From 6315dea09463f767764ff519f35600c8d861f9b9 Mon Sep 17 00:00:00 2001 From: erio Date: Fri, 6 Mar 2026 18:04:52 +0800 Subject: [PATCH] fix: prevent reverse affinity index from premature expiration The reverse index account_affinity:{accountID} was using the same 1h EXPIRE as the forward index. But the forward key EXPIRE refreshes on every client request, while the reverse key only refreshes when a request is routed to that specific account. This caused reverse keys to expire prematurely. Fix: set reverse key EXPIRE to 24h as safety net, rely on ZREMRANGEBYSCORE for member-level expiration. Also clean up empty keys after member cleanup. Co-Authored-By: Claude Opus 4.6 --- backend/cmd/server/VERSION | 2 +- backend/internal/repository/gateway_cache.go | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/backend/cmd/server/VERSION b/backend/cmd/server/VERSION index dea646b9cb..469ff9055c 100644 --- a/backend/cmd/server/VERSION +++ b/backend/cmd/server/VERSION @@ -1 +1 @@ -0.1.92.5 +0.1.92.6 diff --git a/backend/internal/repository/gateway_cache.go b/backend/internal/repository/gateway_cache.go index 6ca8319e44..462a51b7a2 100644 --- a/backend/internal/repository/gateway_cache.go +++ b/backend/internal/repository/gateway_cache.go @@ -86,7 +86,7 @@ redis.call('ZREMRANGEBYSCORE', KEYS[1], '-inf', ARGV[4]) redis.call('ZADD', KEYS[1], ARGV[1], ARGV[3]) redis.call('EXPIRE', KEYS[1], ARGV[2]) redis.call('ZADD', KEYS[2], ARGV[1], ARGV[5]) -redis.call('EXPIRE', KEYS[2], ARGV[2]) +redis.call('EXPIRE', KEYS[2], 86400) return 1 `) @@ -144,12 +144,16 @@ func buildAccountAffinityKey(accountID int64) string { return fmt.Sprintf("%s%d", accountAffinityPrefix, accountID) } -// getAccountAffinityScript: 清理过期成员后返回 ZCARD +// getAccountAffinityScript: 清理过期成员后返回 ZCARD,空 key 自动删除 // KEYS[1] = account_affinity:{accountID} // ARGV[1] = 过期阈值时间戳 (now - ttl) var getAccountAffinityScript = redis.NewScript(` redis.call('ZREMRANGEBYSCORE', KEYS[1], '-inf', ARGV[1]) -return redis.call('ZCARD', KEYS[1]) +local count = redis.call('ZCARD', KEYS[1]) +if count == 0 then + redis.call('DEL', KEYS[1]) +end +return count `) func (c *gatewayCache) GetAccountAffinityCount(ctx context.Context, accountID int64, ttl time.Duration) (int, error) {