feat(admin): 统一后台 API 资源鉴权并完善投注风控快照与回补
This commit is contained in:
@@ -136,10 +136,10 @@ 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);
|
||||
Redis::eval($this->initLua(), 1, $key, (int) $pool->total_cap_amount, (int) $pool->locked_amount, (int) $pool->version);
|
||||
|
||||
$result = (int) Redis::eval($this->acquireLua(), 1, $key, $amount);
|
||||
if ($result !== 1) {
|
||||
$result = $this->normalizeLuaResult(Redis::eval($this->acquireLua(), 1, $key, $amount, (int) $pool->version));
|
||||
if (($result['code'] ?? null) !== 'OK') {
|
||||
throw new TicketOperationException('risk_sold_out', ErrorCode::RiskPoolSoldOut->value);
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ final class RiskPoolService
|
||||
{
|
||||
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])
|
||||
redis.call('HMSET', KEYS[1], 'total', ARGV[1], 'locked', ARGV[2], 'remaining', ARGV[1] - ARGV[2], 'version', ARGV[3])
|
||||
end
|
||||
return 1
|
||||
LUA;
|
||||
@@ -200,13 +200,25 @@ LUA;
|
||||
{
|
||||
return <<<'LUA'
|
||||
local amount = tonumber(ARGV[1])
|
||||
local expectedVersion = tonumber(ARGV[2])
|
||||
if amount == nil or amount <= 0 then
|
||||
return {'INVALID_ARGUMENT', 0, 0, 0}
|
||||
end
|
||||
if redis.call('EXISTS', KEYS[1]) == 0 then
|
||||
return {'POOL_NOT_INITIALIZED', 0, 0, 0}
|
||||
end
|
||||
local version = tonumber(redis.call('HGET', KEYS[1], 'version') or '0')
|
||||
if expectedVersion ~= nil and version ~= expectedVersion then
|
||||
return {'VERSION_CONFLICT', tonumber(redis.call('HGET', KEYS[1], 'remaining') or '0'), tonumber(redis.call('HGET', KEYS[1], 'locked') or '0'), version}
|
||||
end
|
||||
local remaining = tonumber(redis.call('HGET', KEYS[1], 'remaining') or '0')
|
||||
if remaining < amount then
|
||||
return 0
|
||||
return {'INSUFFICIENT_CAP', remaining, tonumber(redis.call('HGET', KEYS[1], 'locked') or '0'), version}
|
||||
end
|
||||
redis.call('HINCRBY', KEYS[1], 'locked', amount)
|
||||
redis.call('HINCRBY', KEYS[1], 'remaining', -amount)
|
||||
return 1
|
||||
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)
|
||||
return {'OK', remaining, locked, version}
|
||||
LUA;
|
||||
}
|
||||
|
||||
@@ -265,6 +277,28 @@ LUA;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{code:string, remaining:int, locked:int, version:int}
|
||||
*/
|
||||
private function normalizeLuaResult(mixed $result): array
|
||||
{
|
||||
if (! is_array($result)) {
|
||||
return [
|
||||
'code' => (int) $result === 1 ? 'OK' : 'INSUFFICIENT_CAP',
|
||||
'remaining' => 0,
|
||||
'locked' => 0,
|
||||
'version' => 0,
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
'code' => (string) ($result[0] ?? 'INSUFFICIENT_CAP'),
|
||||
'remaining' => (int) ($result[1] ?? 0),
|
||||
'locked' => (int) ($result[2] ?? 0),
|
||||
'version' => (int) ($result[3] ?? 0),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<array{number_4d:string, amount:int}> $locks
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user