diff options
author | Robin Appelman <robin@icewind.nl> | 2023-12-05 16:01:46 +0100 |
---|---|---|
committer | backportbot-nextcloud[bot] <backportbot-nextcloud[bot]@users.noreply.github.com> | 2023-12-22 09:54:13 +0000 |
commit | 2078ad79bdc996494f0de49fcd04d56457296c47 (patch) | |
tree | 2fd2bd470943e9d619303266b033017301c88e72 | |
parent | 6ba6c95bab863197fd2922ac2e83567d643ebecc (diff) | |
download | nextcloud-server-2078ad79bdc996494f0de49fcd04d56457296c47.tar.gz nextcloud-server-2078ad79bdc996494f0de49fcd04d56457296c47.zip |
adjust redis compareSetTTL to use a lua script
Signed-off-by: Robin Appelman <robin@icewind.nl>
-rw-r--r-- | lib/private/Memcache/Redis.php | 16 | ||||
-rw-r--r-- | tests/lib/Memcache/RedisTest.php | 21 |
2 files changed, 28 insertions, 9 deletions
diff --git a/lib/private/Memcache/Redis.php b/lib/private/Memcache/Redis.php index 7bd29d1cecf..6634f325005 100644 --- a/lib/private/Memcache/Redis.php +++ b/lib/private/Memcache/Redis.php @@ -46,6 +46,10 @@ class Redis extends Cache implements IMemcacheTTL { 'if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end', 'cf0e94b2e9ffc7e04395cf88f7583fc309985910', ], + 'caSetTtl' => [ + 'if redis.call("get", KEYS[1]) == ARGV[1] then redis.call("expire", KEYS[1], ARGV[2]) return 1 else return 0 end', + 'fa4acbc946d23ef41d7d3910880b60e6e4972d72', + ], ]; /** @@ -187,15 +191,9 @@ class Redis extends Cache implements IMemcacheTTL { } public function compareSetTTL(string $key, mixed $value, int $ttl): bool { - $fullKey = $this->getPrefix() . $key; - $redis = $this->getCache(); - if ($this->get($key) === $value) { - $result = $redis->multi() - ->expire($fullKey, $ttl) - ->exec(); - return $result !== false; - } - return false; + $value = self::encodeValue($value); + + return $this->evalLua('caSetTtl', [$key], [$value, $ttl]) > 0; } public static function isAvailable(): bool { diff --git a/tests/lib/Memcache/RedisTest.php b/tests/lib/Memcache/RedisTest.php index b94b69a5e6a..27c6fc11ee8 100644 --- a/tests/lib/Memcache/RedisTest.php +++ b/tests/lib/Memcache/RedisTest.php @@ -9,11 +9,18 @@ namespace Test\Memcache; +use OC\Memcache\Redis; + /** * @group Memcache * @group Redis */ class RedisTest extends Cache { + /** + * @var Redis cache; + */ + protected $instance; + public static function setUpBeforeClass(): void { parent::setUpBeforeClass(); @@ -62,4 +69,18 @@ class RedisTest extends Cache { $this->assertEquals(sha1($script[0]), $script[1]); } } + + public function testCasTtlNotChanged() { + $this->instance->set('foo', 'bar', 50); + $this->assertTrue($this->instance->compareSetTTL('foo', 'bar', 100)); + // allow for 1s of inaccuracy due to time moving forward + $this->assertLessThan(1, 100 - $this->instance->getTTL('foo')); + } + + public function testCasTtlChanged() { + $this->instance->set('foo', 'bar1', 50); + $this->assertFalse($this->instance->compareSetTTL('foo', 'bar', 100)); + // allow for 1s of inaccuracy due to time moving forward + $this->assertLessThan(1, 50 - $this->instance->getTTL('foo')); + } } |