lib/Phpfastcache/Cluster/Drivers/MasterSlaveReplication/Driver.php
<?php
/**
*
* This file is part of Phpfastcache.
*
* @license MIT License (MIT)
*
* For full copyright and license information, please see the docs/CREDITS.txt file.
*
* @author Georges.L (Geolim4) <contact@geolim4.com>
*
*/
declare(strict_types=1);
namespace Phpfastcache\Cluster\Drivers\MasterSlaveReplication;
use Phpfastcache\Cluster\AggregatablePoolInterface;
use Phpfastcache\Cluster\ClusterPoolAbstract;
use Phpfastcache\Core\Item\ExtendedCacheItemInterface;
use Phpfastcache\Core\Pool\ExtendedCacheItemPoolInterface;
use Phpfastcache\Event\Event;
use Phpfastcache\Event\EventManagerInterface;
use Phpfastcache\Exceptions\PhpfastcacheCoreException;
use Phpfastcache\Exceptions\PhpfastcacheDriverCheckException;
use Phpfastcache\Exceptions\PhpfastcacheDriverConnectException;
use Phpfastcache\Exceptions\PhpfastcacheDriverException;
use Phpfastcache\Exceptions\PhpfastcacheExceptionInterface;
use Phpfastcache\Exceptions\PhpfastcacheInvalidArgumentException;
use Phpfastcache\Exceptions\PhpfastcacheIOException;
use Phpfastcache\Exceptions\PhpfastcacheReplicationException;
use Psr\Cache\CacheItemInterface;
class Driver extends ClusterPoolAbstract
{
/**
* MasterSlaveReplicationCluster constructor.
* @param string $clusterName
* @param EventManagerInterface $em
* @param AggregatablePoolInterface ...$driverPools
* @throws PhpfastcacheDriverCheckException
* @throws PhpfastcacheDriverConnectException
* @throws PhpfastcacheInvalidArgumentException
* @throws PhpfastcacheCoreException
* @throws PhpfastcacheDriverException
* @throws PhpfastcacheIOException
*/
public function __construct(string $clusterName, EventManagerInterface $em, AggregatablePoolInterface ...$driverPools)
{
if (\count($driverPools) !== 2) {
throw new PhpfastcacheInvalidArgumentException('A "master/slave" cluster requires exactly two pools to be working.');
}
parent::__construct($clusterName, $em, ...$driverPools);
}
/**
* @inheritDoc
*/
public function getItem(string $key): ExtendedCacheItemInterface
{
return $this->getStandardizedItem(
$this->makeOperation(static function (ExtendedCacheItemPoolInterface $pool) use ($key) {
return $pool->getItem($key);
}) ?? (new Item($this, $key, $this->getEventManager()))->expiresAfter((int) abs($this->getConfig()->getDefaultTtl())),
$this
);
}
/**
* @param callable $operation
* @return mixed
* @throws PhpfastcacheReplicationException
*/
protected function makeOperation(callable $operation)
{
try {
return $operation($this->getMasterPool());
} catch (PhpfastcacheExceptionInterface $e) {
try {
$this->eventManager->dispatch(
Event::CACHE_REPLICATION_SLAVE_FALLBACK,
$this,
\debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['function']
);
return $operation($this->getSlavePool());
} catch (PhpfastcacheExceptionInterface $e) {
throw new PhpfastcacheReplicationException('Master and Slave thrown an exception !');
}
}
}
/**
* @return AggregatablePoolInterface
*/
protected function getMasterPool(): AggregatablePoolInterface
{
return $this->clusterPools[0];
}
/**
* @return AggregatablePoolInterface
*/
protected function getSlavePool(): AggregatablePoolInterface
{
return $this->clusterPools[1];
}
/**
* @inheritDoc
*/
public function hasItem(string $key): bool
{
return $this->makeOperation(
static fn (ExtendedCacheItemPoolInterface $pool) => $pool->hasItem($key)
);
}
/**
* @inheritDoc
*/
public function clear(): bool
{
return $this->makeOperation(
static fn (ExtendedCacheItemPoolInterface $pool) => $pool->clear()
);
}
/**
* @inheritDoc
*/
public function deleteItem(string $key): bool
{
return $this->makeOperation(
static fn (ExtendedCacheItemPoolInterface $pool) => $pool->deleteItem($key)
);
}
/**
* @inheritDoc
*/
public function save(CacheItemInterface $item): bool
{
return $this->makeOperation(
function (ExtendedCacheItemPoolInterface $pool) use ($item) {
/** @var ExtendedCacheItemInterface $item */
$item->setHit(true);
return $pool->save($this->getStandardizedItem($item, $pool));
}
);
}
/**
* @inheritDoc
*/
public function commit(): bool
{
return $this->makeOperation(
static fn (ExtendedCacheItemPoolInterface $pool) => $pool->commit()
);
}
}