119 lines
4.3 KiB
PHP
119 lines
4.3 KiB
PHP
<?php
|
|
// MemcachedProviderModern.php
|
|
// Created: 2024-04-10
|
|
// Updated: 2024-04-10
|
|
|
|
namespace Index\Cache\Memcached;
|
|
|
|
use InvalidArgumentException;
|
|
use Memcached;
|
|
use RuntimeException;
|
|
use Index\Net\{DnsEndPoint,IPEndPoint,UnixEndPoint};
|
|
|
|
/**
|
|
* Base Memcached provider implementation.
|
|
*/
|
|
class MemcachedProviderModern extends MemcachedProvider {
|
|
private Memcached $memcached;
|
|
|
|
public function __construct(MemcachedProviderInfo $providerInfo) {
|
|
$this->memcached = new Memcached($providerInfo->getPersistentName());
|
|
$this->memcached->setOption(Memcached::OPT_BINARY_PROTOCOL, $providerInfo->shouldUseBinaryProtocol());
|
|
$this->memcached->setOption(Memcached::OPT_COMPRESSION, $providerInfo->shouldEnableCompression());
|
|
$this->memcached->setOption(Memcached::OPT_TCP_NODELAY, $providerInfo->shouldTcpNoDelay());
|
|
$this->memcached->setOption(Memcached::OPT_PREFIX_KEY, $providerInfo->getPrefixKey());
|
|
|
|
foreach($providerInfo->getEndPoints() as $endPointInfo) {
|
|
if($endPointInfo[0] instanceof UnixEndPoint) {
|
|
$host = $endPointInfo[0]->getPath();
|
|
$port = 0;
|
|
} elseif($endPointInfo[0] instanceof DnsEndPoint) {
|
|
$host = $endPointInfo[0]->getHost();
|
|
$port = $endPointInfo[0]->getPort();
|
|
} elseif($endPointInfo[0] instanceof IPEndPoint) {
|
|
$host = $endPointInfo[0]->getAddress()->getCleanAddress();
|
|
$port = $endPointInfo[0]->getPort();
|
|
} else throw new InvalidArgumentException('One of the servers specified in $providerInfo is not a supported endpoint.');
|
|
|
|
$this->memcached->addServer($host, $port, $endPointInfo[1]);
|
|
}
|
|
}
|
|
|
|
public function get(string $key): mixed {
|
|
$result = $this->memcached->get($key);
|
|
|
|
if($result === false) {
|
|
$result = $this->memcached->getResultCode();
|
|
if($result === Memcached::RES_NOTFOUND)
|
|
return null;
|
|
|
|
throw new RuntimeException("[Memcached] Error during get: {$result}", $result);
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
public function set(string $key, mixed $value, int $ttl = 0): void {
|
|
if($ttl < 0)
|
|
throw new InvalidArgumentException('$ttl must be equal to or greater than 0.');
|
|
if($ttl > MemcachedProvider::MAX_TTL)
|
|
throw new InvalidArgumentException('$ttl may not be greater than 30 days.');
|
|
|
|
$result = $this->memcached->set($key, $value, $ttl);
|
|
|
|
if(!$result) {
|
|
$result = $this->memcached->getResultCode();
|
|
throw new RuntimeException("[Memcached] Error during set: {$result}", $result);
|
|
}
|
|
}
|
|
|
|
public function delete(string $key): void {
|
|
$result = $this->memcached->delete($key);
|
|
|
|
if(!$result) {
|
|
$result = $this->memcached->getResultCode();
|
|
if($result !== Memcached::RES_NOTFOUND)
|
|
throw new RuntimeException("[Memcached] Error during delete: {$result}", $result);
|
|
}
|
|
}
|
|
|
|
public function touch(string $key, int $ttl = 0): void {
|
|
if($ttl < 0)
|
|
throw new InvalidArgumentException('$ttl must be equal to or greater than 0.');
|
|
if($ttl > MemcachedProvider::MAX_TTL)
|
|
throw new InvalidArgumentException('$ttl may not be greater than 30 days.');
|
|
|
|
$result = $this->memcached->touch($key, $ttl);
|
|
|
|
if(!$result) {
|
|
$result = $this->memcached->getResultCode();
|
|
throw new RuntimeException("[Memcached] Error during set: {$result}", $result);
|
|
}
|
|
}
|
|
|
|
public function increment(string $key, int $amount = 1): int {
|
|
$result = $this->memcached->increment($key, $amount);
|
|
if($result === false) {
|
|
$result = $this->memcached->getResultCode();
|
|
throw new RuntimeException("[Memcached] Error during increment: {$result}", $result);
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
public function decrement(string $key, int $amount = 1): int {
|
|
$result = $this->memcached->decrement($key, $amount);
|
|
if($result === false) {
|
|
$result = $this->memcached->getResultCode();
|
|
throw new RuntimeException("[Memcached] Error during decrement: {$result}", $result);
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
public function close(): void {
|
|
if(!$this->memcached->isPersistent())
|
|
$this->memcached->quit();
|
|
}
|
|
}
|