class CombinedStore
CombinedStore is a PersistingStoreInterface implementation able to manage and synchronize several StoreInterfaces.
@author Jérémy Derussé <jeremy@derusse.com>
Hierarchy
- class \Symfony\Component\Lock\Store\CombinedStore implements \Symfony\Component\Lock\SharedLockStoreInterface, \Psr\Log\LoggerAwareInterface uses \Symfony\Component\Lock\Store\ExpiringStoreTrait, \Psr\Log\LoggerAwareTrait
Expanded class hierarchy of CombinedStore
File
-
vendor/
symfony/ lock/ Store/ CombinedStore.php, line 28
Namespace
Symfony\Component\Lock\StoreView source
class CombinedStore implements SharedLockStoreInterface, LoggerAwareInterface {
use ExpiringStoreTrait;
use LoggerAwareTrait;
/**
* @param PersistingStoreInterface[] $stores The list of synchronized stores
*
* @throws InvalidArgumentException
*/
public function __construct(array $stores, StrategyInterface $strategy) {
foreach ($stores as $store) {
if (!$store instanceof PersistingStoreInterface) {
throw new InvalidArgumentException(\sprintf('The store must implement "%s". Got "%s".', PersistingStoreInterface::class, get_debug_type($store)));
}
}
}
public function save(Key $key) : void {
$successCount = 0;
$failureCount = 0;
$storesCount = \count($this->stores);
foreach ($this->stores as $store) {
try {
$store->save($key);
++$successCount;
} catch (\Exception $e) {
$this->logger?->debug('One store failed to save the "{resource}" lock.', [
'resource' => $key,
'store' => $store,
'exception' => $e,
]);
++$failureCount;
}
if (!$this->strategy
->canBeMet($failureCount, $storesCount)) {
break;
}
}
$this->checkNotExpired($key);
if ($this->strategy
->isMet($successCount, $storesCount)) {
return;
}
$this->logger?->info('Failed to store the "{resource}" lock. Quorum has not been met.', [
'resource' => $key,
'success' => $successCount,
'failure' => $failureCount,
]);
// clean up potential locks
$this->delete($key);
throw new LockConflictedException();
}
public function saveRead(Key $key) : void {
$successCount = 0;
$failureCount = 0;
$storesCount = \count($this->stores);
foreach ($this->stores as $store) {
try {
if ($store instanceof SharedLockStoreInterface) {
$store->saveRead($key);
}
else {
$store->save($key);
}
++$successCount;
} catch (\Exception $e) {
$this->logger?->debug('One store failed to save the "{resource}" lock.', [
'resource' => $key,
'store' => $store,
'exception' => $e,
]);
++$failureCount;
}
if (!$this->strategy
->canBeMet($failureCount, $storesCount)) {
break;
}
}
$this->checkNotExpired($key);
if ($this->strategy
->isMet($successCount, $storesCount)) {
return;
}
$this->logger?->info('Failed to store the "{resource}" lock. Quorum has not been met.', [
'resource' => $key,
'success' => $successCount,
'failure' => $failureCount,
]);
// clean up potential locks
$this->delete($key);
throw new LockConflictedException();
}
public function putOffExpiration(Key $key, float $ttl) : void {
$successCount = 0;
$failureCount = 0;
$storesCount = \count($this->stores);
$expireAt = microtime(true) + $ttl;
foreach ($this->stores as $store) {
try {
if (0.0 >= ($adjustedTtl = $expireAt - microtime(true))) {
$this->logger?->debug('Stores took to long to put off the expiration of the "{resource}" lock.', [
'resource' => $key,
'store' => $store,
'ttl' => $ttl,
]);
$key->reduceLifetime(0);
break;
}
$store->putOffExpiration($key, $adjustedTtl);
++$successCount;
} catch (\Exception $e) {
$this->logger?->debug('One store failed to put off the expiration of the "{resource}" lock.', [
'resource' => $key,
'store' => $store,
'exception' => $e,
]);
++$failureCount;
}
if (!$this->strategy
->canBeMet($failureCount, $storesCount)) {
break;
}
}
$this->checkNotExpired($key);
if ($this->strategy
->isMet($successCount, $storesCount)) {
return;
}
$this->logger?->notice('Failed to define the expiration for the "{resource}" lock. Quorum has not been met.', [
'resource' => $key,
'success' => $successCount,
'failure' => $failureCount,
]);
// clean up potential locks
$this->delete($key);
throw new LockConflictedException();
}
public function delete(Key $key) : void {
foreach ($this->stores as $store) {
try {
$store->delete($key);
} catch (\Exception $e) {
$this->logger?->notice('One store failed to delete the "{resource}" lock.', [
'resource' => $key,
'store' => $store,
'exception' => $e,
]);
}
}
}
public function exists(Key $key) : bool {
$successCount = 0;
$failureCount = 0;
$storesCount = \count($this->stores);
foreach ($this->stores as $store) {
try {
if ($store->exists($key)) {
++$successCount;
}
else {
++$failureCount;
}
} catch (\Exception $e) {
$this->logger?->debug('One store failed to check the "{resource}" lock.', [
'resource' => $key,
'store' => $store,
'exception' => $e,
]);
++$failureCount;
}
if ($this->strategy
->isMet($successCount, $storesCount)) {
return true;
}
if (!$this->strategy
->canBeMet($failureCount, $storesCount)) {
return false;
}
}
return false;
}
}
Members
Title Sort descending | Modifiers | Object type | Summary | Overriden Title |
---|---|---|---|---|
CombinedStore::delete | public | function | Removes a resource from the storage. | Overrides PersistingStoreInterface::delete |
CombinedStore::exists | public | function | Returns whether or not the resource exists in the storage. | Overrides PersistingStoreInterface::exists |
CombinedStore::putOffExpiration | public | function | Extends the TTL of a resource. | Overrides PersistingStoreInterface::putOffExpiration |
CombinedStore::save | public | function | Stores the resource if it's not locked by someone else. | Overrides PersistingStoreInterface::save |
CombinedStore::saveRead | public | function | Stores the resource if it's not locked for reading by someone else. | Overrides SharedLockStoreInterface::saveRead |
CombinedStore::__construct | public | function | ||
ExpiringStoreTrait::checkNotExpired | private | function | ||
LoggerAwareTrait::$logger | protected | property | The logger instance. | |
LoggerAwareTrait::setLogger | public | function | Sets a logger. |