]> source.dussan.org Git - nextcloud-server.git/commitdiff
adjust redis compareSetTTL to use a lua script 42450/head
authorRobin Appelman <robin@icewind.nl>
Tue, 5 Dec 2023 15:01:46 +0000 (16:01 +0100)
committerbackportbot-nextcloud[bot] <backportbot-nextcloud[bot]@users.noreply.github.com>
Fri, 22 Dec 2023 09:54:13 +0000 (09:54 +0000)
Signed-off-by: Robin Appelman <robin@icewind.nl>
lib/private/Memcache/Redis.php
tests/lib/Memcache/RedisTest.php

index 7bd29d1cecfdb0f8cb2d771e3f10e85376f4b83c..6634f3250054477fd83e6c41929005fbfb574352 100644 (file)
@@ -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 {
index b94b69a5e6ac9da6f5efbe5183209c7f11857777..27c6fc11ee86abb17d1b06c69ceeae39696ffefd 100644 (file)
@@ -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'));
+       }
 }