index/src/Cache/Memcached/MemcachedProviderModern.php
2024-04-10 22:23:34 +00:00

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->getPath();
$port = 0;
} elseif($endPointInfo[0] instanceof DnsEndPoint) {
$host = $endPointInfo->getHost();
$port = $endPointInfo->getPort();
} elseif($endPointInfo[0] instanceof IPEndPoint) {
$host = $endPointInfo->getAddress()->getCleanAddress();
$port = $endPointInfo->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();
}
}