feat: 增强风险池 Redis 操作,添加 TTL 支持并更新相关 Lua 脚本;新增 API 异常响应测试
This commit is contained in:
@@ -151,9 +151,24 @@ final class RiskPoolService
|
||||
$pool = $this->firstOrMakePool($drawId, $number4d);
|
||||
$key = $this->redisPoolKey($drawId, $number4d);
|
||||
|
||||
Redis::eval($this->initLua(), 1, $key, (int) $pool->total_cap_amount, (int) $pool->locked_amount, (int) $pool->version);
|
||||
Redis::eval(
|
||||
$this->initLua(),
|
||||
1,
|
||||
$key,
|
||||
(int) $pool->total_cap_amount,
|
||||
(int) $pool->locked_amount,
|
||||
(int) $pool->version,
|
||||
$this->redisPoolTtlSeconds(),
|
||||
);
|
||||
|
||||
$result = $this->normalizeLuaResult(Redis::eval($this->acquireLua(), 1, $key, $amount, (int) $pool->version));
|
||||
$result = $this->normalizeLuaResult(Redis::eval(
|
||||
$this->acquireLua(),
|
||||
1,
|
||||
$key,
|
||||
$amount,
|
||||
(int) $pool->version,
|
||||
$this->redisPoolTtlSeconds(),
|
||||
));
|
||||
if (($result['code'] ?? null) !== 'OK') {
|
||||
throw new TicketOperationException('risk_sold_out', ErrorCode::RiskPoolSoldOut->value);
|
||||
}
|
||||
@@ -211,6 +226,7 @@ final class RiskPoolService
|
||||
$locked,
|
||||
$remaining,
|
||||
(int) $pool->version,
|
||||
$this->redisPoolTtlSeconds(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -228,11 +244,17 @@ final class RiskPoolService
|
||||
return "risk_pool:draw:{$drawId}:number:{$number4d}";
|
||||
}
|
||||
|
||||
private function redisPoolTtlSeconds(): int
|
||||
{
|
||||
return max(60, (int) config('lottery.risk_pool.redis_ttl_seconds', 86400));
|
||||
}
|
||||
|
||||
private function initLua(): string
|
||||
{
|
||||
return <<<'LUA'
|
||||
if redis.call('EXISTS', KEYS[1]) == 0 then
|
||||
redis.call('HMSET', KEYS[1], 'total', ARGV[1], 'locked', ARGV[2], 'remaining', ARGV[1] - ARGV[2], 'version', ARGV[3])
|
||||
redis.call('EXPIRE', KEYS[1], tonumber(ARGV[4]))
|
||||
end
|
||||
return 1
|
||||
LUA;
|
||||
@@ -242,6 +264,7 @@ LUA;
|
||||
{
|
||||
return <<<'LUA'
|
||||
redis.call('HMSET', KEYS[1], 'total', ARGV[1], 'locked', ARGV[2], 'remaining', ARGV[3], 'version', ARGV[4])
|
||||
redis.call('EXPIRE', KEYS[1], tonumber(ARGV[5]))
|
||||
return 1
|
||||
LUA;
|
||||
}
|
||||
@@ -268,6 +291,7 @@ end
|
||||
local locked = redis.call('HINCRBY', KEYS[1], 'locked', amount)
|
||||
remaining = redis.call('HINCRBY', KEYS[1], 'remaining', -amount)
|
||||
version = redis.call('HINCRBY', KEYS[1], 'version', 1)
|
||||
redis.call('EXPIRE', KEYS[1], tonumber(ARGV[3]))
|
||||
return {'OK', remaining, locked, version}
|
||||
LUA;
|
||||
}
|
||||
@@ -283,6 +307,7 @@ if locked < releaseAmount then
|
||||
end
|
||||
redis.call('HINCRBY', KEYS[1], 'locked', -releaseAmount)
|
||||
redis.call('HINCRBY', KEYS[1], 'remaining', releaseAmount)
|
||||
redis.call('EXPIRE', KEYS[1], tonumber(ARGV[2]))
|
||||
return releaseAmount
|
||||
LUA;
|
||||
}
|
||||
@@ -336,7 +361,13 @@ LUA;
|
||||
private function releaseRedisLocks(int $drawId, array $locks): void
|
||||
{
|
||||
foreach ($locks as $lock) {
|
||||
Redis::eval($this->releaseLua(), 1, $this->redisPoolKey($drawId, $lock['number_4d']), (int) $lock['amount']);
|
||||
Redis::eval(
|
||||
$this->releaseLua(),
|
||||
1,
|
||||
$this->redisPoolKey($drawId, $lock['number_4d']),
|
||||
(int) $lock['amount'],
|
||||
$this->redisPoolTtlSeconds(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user