Inline lua scripts used by semaphore
This commit is contained in:
parent
1ed5e0ca46
commit
0d6666aac2
@ -50,7 +50,49 @@ class RedisStore implements PersistingStoreInterface
|
||||
throw new InvalidArgumentException("The TTL should be greater than 0, '$ttlInSecond' given.");
|
||||
}
|
||||
|
||||
$script = file_get_contents(__DIR__.'/Resources/redis_save.lua');
|
||||
$script = '
|
||||
local key = KEYS[1]
|
||||
local weightKey = key .. ":weight"
|
||||
local timeKey = key .. ":time"
|
||||
local identifier = ARGV[1]
|
||||
local now = tonumber(ARGV[2])
|
||||
local ttlInSecond = tonumber(ARGV[3])
|
||||
local limit = tonumber(ARGV[4])
|
||||
local weight = tonumber(ARGV[5])
|
||||
|
||||
-- Remove expired values
|
||||
redis.call("ZREMRANGEBYSCORE", timeKey, "-inf", now)
|
||||
redis.call("ZINTERSTORE", weightKey, 2, weightKey, timeKey, "WEIGHTS", 1, 0)
|
||||
|
||||
-- Semaphore already acquired?
|
||||
if redis.call("ZSCORE", timeKey, identifier) then
|
||||
return true
|
||||
end
|
||||
|
||||
-- Try to get a semaphore
|
||||
local semaphores = redis.call("ZRANGE", weightKey, 0, -1, "WITHSCORES")
|
||||
local count = 0
|
||||
|
||||
for i = 1, #semaphores, 2 do
|
||||
count = count + semaphores[i+1]
|
||||
end
|
||||
|
||||
-- Could we get the semaphore ?
|
||||
if count + weight > limit then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Acquire the semaphore
|
||||
redis.call("ZADD", timeKey, now + ttlInSecond, identifier)
|
||||
redis.call("ZADD", weightKey, weight, identifier)
|
||||
|
||||
-- Extend the TTL
|
||||
local maxExpiration = redis.call("ZREVRANGE", timeKey, 0, 0, "WITHSCORES")[2]
|
||||
redis.call("EXPIREAT", weightKey, maxExpiration + 10)
|
||||
redis.call("EXPIREAT", timeKey, maxExpiration + 10)
|
||||
|
||||
return true
|
||||
';
|
||||
|
||||
$args = [
|
||||
$this->getUniqueToken($key),
|
||||
@ -74,7 +116,28 @@ class RedisStore implements PersistingStoreInterface
|
||||
throw new InvalidArgumentException("The TTL should be greater than 0, '$ttlInSecond' given.");
|
||||
}
|
||||
|
||||
$script = file_get_contents(__DIR__.'/Resources/redis_put_off_expiration.lua');
|
||||
$script = '
|
||||
local key = KEYS[1]
|
||||
local weightKey = key .. ":weight"
|
||||
local timeKey = key .. ":time"
|
||||
|
||||
local added = redis.call("ZADD", timeKey, ARGV[1], ARGV[2])
|
||||
if added == 1 then
|
||||
redis.call("ZREM", timeKey, ARGV[2])
|
||||
redis.call("ZREM", weightKey, ARGV[2])
|
||||
end
|
||||
|
||||
-- Extend the TTL
|
||||
local maxExpiration = redis.call("ZREVRANGE", timeKey, 0, 0, "WITHSCORES")[2]
|
||||
if nil == maxExpiration then
|
||||
return 1
|
||||
end
|
||||
|
||||
redis.call("EXPIREAT", weightKey, maxExpiration + 10)
|
||||
redis.call("EXPIREAT", timeKey, maxExpiration + 10)
|
||||
|
||||
return added
|
||||
';
|
||||
|
||||
$ret = $this->evaluate($script, sprintf('{%s}', $key), [time() + $ttlInSecond, $this->getUniqueToken($key)]);
|
||||
|
||||
@ -94,7 +157,15 @@ class RedisStore implements PersistingStoreInterface
|
||||
*/
|
||||
public function delete(Key $key)
|
||||
{
|
||||
$script = file_get_contents(__DIR__.'/Resources/redis_delete.lua');
|
||||
$script = '
|
||||
local key = KEYS[1]
|
||||
local weightKey = key .. ":weight"
|
||||
local timeKey = key .. ":time"
|
||||
local identifier = ARGV[1]
|
||||
|
||||
redis.call("ZREM", timeKey, identifier)
|
||||
return redis.call("ZREM", weightKey, identifier)
|
||||
';
|
||||
|
||||
$this->evaluate($script, sprintf('{%s}', $key), [$this->getUniqueToken($key)]);
|
||||
}
|
||||
|
@ -1,7 +0,0 @@
|
||||
local key = KEYS[1]
|
||||
local weightKey = key .. ":weight"
|
||||
local timeKey = key .. ":time"
|
||||
local identifier = ARGV[1]
|
||||
|
||||
redis.call("ZREM", timeKey, identifier)
|
||||
return redis.call("ZREM", weightKey, identifier)
|
@ -1,20 +0,0 @@
|
||||
local key = KEYS[1]
|
||||
local weightKey = key .. ":weight"
|
||||
local timeKey = key .. ":time"
|
||||
|
||||
local added = redis.call("ZADD", timeKey, ARGV[1], ARGV[2])
|
||||
if added == 1 then
|
||||
redis.call("ZREM", timeKey, ARGV[2])
|
||||
redis.call("ZREM", weightKey, ARGV[2])
|
||||
end
|
||||
|
||||
-- Extend the TTL
|
||||
local maxExpiration = redis.call("ZREVRANGE", timeKey, 0, 0, "WITHSCORES")[2]
|
||||
if nil == maxExpiration then
|
||||
return 1
|
||||
end
|
||||
|
||||
redis.call("EXPIREAT", weightKey, maxExpiration + 10)
|
||||
redis.call("EXPIREAT", timeKey, maxExpiration + 10)
|
||||
|
||||
return added
|
@ -1,41 +0,0 @@
|
||||
local key = KEYS[1]
|
||||
local weightKey = key .. ":weight"
|
||||
local timeKey = key .. ":time"
|
||||
local identifier = ARGV[1]
|
||||
local now = tonumber(ARGV[2])
|
||||
local ttlInSecond = tonumber(ARGV[3])
|
||||
local limit = tonumber(ARGV[4])
|
||||
local weight = tonumber(ARGV[5])
|
||||
|
||||
-- Remove expired values
|
||||
redis.call("ZREMRANGEBYSCORE", timeKey, "-inf", now)
|
||||
redis.call("ZINTERSTORE", weightKey, 2, weightKey, timeKey, "WEIGHTS", 1, 0)
|
||||
|
||||
-- Semaphore already acquired?
|
||||
if redis.call("ZSCORE", timeKey, identifier) then
|
||||
return true
|
||||
end
|
||||
|
||||
-- Try to get a semaphore
|
||||
local semaphores = redis.call("ZRANGE", weightKey, 0, -1, "WITHSCORES")
|
||||
local count = 0
|
||||
|
||||
for i = 1, #semaphores, 2 do
|
||||
count = count + semaphores[i+1]
|
||||
end
|
||||
|
||||
-- Could we get the semaphore ?
|
||||
if count + weight > limit then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Acquire the semaphore
|
||||
redis.call("ZADD", timeKey, now + ttlInSecond, identifier)
|
||||
redis.call("ZADD", weightKey, weight, identifier)
|
||||
|
||||
-- Extend the TTL
|
||||
local maxExpiration = redis.call("ZREVRANGE", timeKey, 0, 0, "WITHSCORES")[2]
|
||||
redis.call("EXPIREAT", weightKey, maxExpiration + 10)
|
||||
redis.call("EXPIREAT", timeKey, maxExpiration + 10)
|
||||
|
||||
return true
|
Reference in New Issue
Block a user