Skip to content

Commit ff0b8f3

Browse files
committed
adjust redis compareSetTTL to use a lua script
Signed-off-by: Robin Appelman <robin@icewind.nl>
1 parent 0461529 commit ff0b8f3

File tree

2 files changed

+28
-9
lines changed

2 files changed

+28
-9
lines changed

lib/private/Memcache/Redis.php

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ class Redis extends Cache implements IMemcacheTTL {
4646
'if redis.call("get", KEYS[1]) == ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end',
4747
'cf0e94b2e9ffc7e04395cf88f7583fc309985910',
4848
],
49+
'caSetTtl' => [
50+
'if redis.call("get", KEYS[1]) == ARGV[1] then redis.call("expire", KEYS[1], ARGV[2]) return 1 else return 0 end',
51+
'fa4acbc946d23ef41d7d3910880b60e6e4972d72',
52+
],
4953
];
5054

5155
/**
@@ -187,15 +191,9 @@ public function getTTL(string $key): int|false {
187191
}
188192

189193
public function compareSetTTL(string $key, mixed $value, int $ttl): bool {
190-
$fullKey = $this->getPrefix() . $key;
191-
$redis = $this->getCache();
192-
if ($this->get($key) === $value) {
193-
$result = $redis->multi()
194-
->expire($fullKey, $ttl)
195-
->exec();
196-
return $result !== false;
197-
}
198-
return false;
194+
$value = self::encodeValue($value);
195+
196+
return $this->evalLua('caSetTtl', [$key], [$value, $ttl]) > 0;
199197
}
200198

201199
public static function isAvailable(): bool {

tests/lib/Memcache/RedisTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,18 @@
99

1010
namespace Test\Memcache;
1111

12+
use OC\Memcache\Redis;
13+
1214
/**
1315
* @group Memcache
1416
* @group Redis
1517
*/
1618
class RedisTest extends Cache {
19+
/**
20+
* @var Redis cache;
21+
*/
22+
protected $instance;
23+
1724
public static function setUpBeforeClass(): void {
1825
parent::setUpBeforeClass();
1926

@@ -62,4 +69,18 @@ public function testScriptHashes() {
6269
$this->assertEquals(sha1($script[0]), $script[1]);
6370
}
6471
}
72+
73+
public function testCasTtlNotChanged() {
74+
$this->instance->set('foo', 'bar', 50);
75+
$this->assertTrue($this->instance->compareSetTTL('foo', 'bar', 100));
76+
// allow for 1s of inaccuracy due to time moving forward
77+
$this->assertLessThan(1, 100 - $this->instance->getTTL('foo'));
78+
}
79+
80+
public function testCasTtlChanged() {
81+
$this->instance->set('foo', 'bar1', 50);
82+
$this->assertFalse($this->instance->compareSetTTL('foo', 'bar', 100));
83+
// allow for 1s of inaccuracy due to time moving forward
84+
$this->assertLessThan(1, 50 - $this->instance->getTTL('foo'));
85+
}
6586
}

0 commit comments

Comments
 (0)