Skip to content

Commit

Permalink
feat: add negative compare-and-delete to imemcache
Browse files Browse the repository at this point in the history
Signed-off-by: Robin Appelman <[email protected]>
  • Loading branch information
icewind1991 committed Aug 15, 2024
1 parent 601b3b1 commit adf6c6a
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 0 deletions.
16 changes: 16 additions & 0 deletions lib/private/Memcache/CADTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,20 @@ public function cad($key, $old) {
return false;
}
}

public function ncad(string $key, $old): bool {
//no native cas, emulate with locking
if ($this->add($key . '_lock', true)) {
if ($this->get($key) !== $old) {
$this->remove($key);
$this->remove($key . '_lock');
return true;
} else {
$this->remove($key . '_lock');
return false;
}
} else {
return false;
}
}
}
11 changes: 11 additions & 0 deletions lib/private/Memcache/LoggerWrapperCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,17 @@ public function cad($key, $old) {
return $this->wrappedCache->cad($key, $old);
}

/** @inheritDoc */
public function ncad(string $key, $old): bool {
file_put_contents(
$this->logFile,
$this->getNameSpace() . '::ncad::' . $key . "\n",
FILE_APPEND
);

return $this->wrappedCache->cad($key, $old);
}

/** @inheritDoc */
public function setTTL(string $key, int $ttl) {
$this->wrappedCache->setTTL($key, $ttl);
Expand Down
5 changes: 5 additions & 0 deletions lib/private/Memcache/NullCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ public function cad($key, $old) {
return true;
}

public function ncad(string $key, $old): bool {
return true;
}


public function clear($prefix = '') {
return true;
}
Expand Down
12 changes: 12 additions & 0 deletions lib/private/Memcache/ProfilerWrapperCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,18 @@ public function cad($key, $old) {
return $ret;
}

/** @inheritDoc */
public function ncad(string $key, $old): bool {
$start = microtime(true);
$ret = $this->wrappedCache->ncad($key, $old);
$this->data['queries'][] = [
'start' => $start,
'end' => microtime(true),
'op' => $this->getPrefix() . '::ncad::' . $key,
];
return $ret;
}

/** @inheritDoc */
public function setTTL(string $key, int $ttl) {
$this->wrappedCache->setTTL($key, $ttl);
Expand Down
10 changes: 10 additions & 0 deletions lib/private/Memcache/Redis.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,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',
],
'ncad' => [
'if redis.call("get", KEYS[1]) ~= ARGV[1] then return redis.call("del", KEYS[1]) else return 0 end',
'75526f8048b13ce94a41b58eee59c664b4990ab2',
],
'caSetTtl' => [
'if redis.call("get", KEYS[1]) == ARGV[1] then redis.call("expire", KEYS[1], ARGV[2]) return 1 else return 0 end',
'fa4acbc946d23ef41d7d3910880b60e6e4972d72',
Expand Down Expand Up @@ -164,6 +168,12 @@ public function cad($key, $old) {
return $this->evalLua('cad', [$key], [$old]) > 0;
}

public function ncad(string $key, $old): bool {
$old = self::encodeValue($old);

return $this->evalLua('ncad', [$key], [$old]) > 0;
}

public function setTTL($key, $ttl) {
if ($ttl === 0) {
// having infinite TTL can lead to leaked keys as the prefix changes with version upgrades
Expand Down
14 changes: 14 additions & 0 deletions lib/public/IMemcache.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,24 @@ public function cas($key, $old, $new);
/**
* Compare and delete
*
* Delete $key if the stored value is equal to $old
*
* @param string $key
* @param mixed $old
* @return bool
* @since 8.1.0
*/
public function cad($key, $old);

/**
* Negative compare and delete
*
* Delete $key if the stored value is not equal to $old
*
* @param string $key
* @param mixed $old
* @return bool
* @since 30.0.0
*/
public function ncad(string $key, $old): bool;
}
12 changes: 12 additions & 0 deletions tests/lib/Memcache/Cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,18 @@ public function testCadChanged() {
$this->assertTrue($this->instance->hasKey('foo'));
}

public function testNcadNotChanged() {
$this->instance->set('foo', 'bar');
$this->assertFalse($this->instance->ncad('foo', 'bar'));
$this->assertTrue($this->instance->hasKey('foo'));
}

public function testNcadChanged() {
$this->instance->set('foo', 'bar1');
$this->assertTrue($this->instance->ncad('foo', 'bar'));
$this->assertFalse($this->instance->hasKey('foo'));
}


protected function tearDown(): void {
if ($this->instance) {
Expand Down

0 comments on commit adf6c6a

Please sign in to comment.