Commit 3b645a48 authored by bdragon's avatar bdragon Committed by bdragon
Browse files

Issue #2996620 by bdragon, Fabianx: Fix clock skew tolerance in deleteAll;...

Issue #2996620 by bdragon, Fabianx: Fix clock skew tolerance in deleteAll; make it configurable [Follow-up: Add mechanism to support invalidateAll and deleteAll]
parent 00b288a4
......@@ -162,13 +162,18 @@ if ($memcache_exists || $memcached_exists) {
'class' => 'Drupal\memcache\MemcacheSettings',
'arguments' => ['@settings'],
],
'memcache.backend.cache.factory' => [
'memcache.factory' => [
'class' => 'Drupal\memcache\Driver\MemcacheDriverFactory',
'arguments' => ['@memcache.settings']
'arguments' => ['@memcache.settings'],
],
'memcache.timestamp.invalidator.bin' => [
'class' => 'Drupal\memcache\Invalidator\MemcacheTimestampInvalidator',
# Adjust tolerance factor as appropriate when not running memcache on localhost.
'arguments' => ['@memcache.factory', 'memcache_bin_timestamps', 0.001],
],
'memcache.backend.cache.container' => [
'class' => 'Drupal\memcache\DrupalMemcacheInterface',
'factory' => ['@memcache.backend.cache.factory', 'get'],
'factory' => ['@memcache.factory', 'get'],
'arguments' => ['container'],
],
'cache_tags_provider.container' => [
......@@ -177,7 +182,7 @@ if ($memcache_exists || $memcached_exists) {
],
'cache.container' => [
'class' => 'Drupal\memcache\MemcacheBackend',
'arguments' => ['container', '@memcache.backend.cache.container', '@cache_tags_provider.container'],
'arguments' => ['container', '@memcache.backend.cache.container', '@cache_tags_provider.container', '@memcache.timestamp.invalidator.bin'],
],
],
];
......@@ -211,26 +216,31 @@ if ($memcache_exists || $memcached_exists) {
'class' => 'Drupal\memcache\Driver\MemcacheDriverFactory',
'arguments' => ['@memcache.settings'],
],
'memcache.timestamp.invalidator.bin' => [
'class' => 'Drupal\memcache\Invalidator\MemcacheTimestampInvalidator',
# Adjust tolerance factor as appropriate when not running memcache on localhost.
'arguments' => ['@memcache.factory', 'memcache_bin_timestamps', 0.001],
],
'memcache.timestamp.invalidator.tag' => [
'class' => 'Drupal\memcache\Invalidator\MemcacheTimestampInvalidator',
# Remember to update your main service definition in sync with this!
# Adjust tolerance factor as appropriate when not running memcache on localhost.
'arguments' => ['@memcache.factory', 'memcache_tag_timestamps', 0.001],
],
'memcache.backend.cache.container' => [
'class' => 'Drupal\memcache\DrupalMemcacheInterface',
'factory' => ['@memcache.factory', 'get'],
# Actual cache bin to use for the container cache.
'arguments' => ['container'],
],
'memcache.backend.timestamp.invalidator' => [
'class' => 'Drupal\memcache\Invalidator\MemcacheTimestampInvalidator',
# Remember to use the same bin as the memcache.timestamp.bin service!
# Adjust tolerance factor as appropriate when not running memcache on localhost.
'arguments' => ['@memcache.factory', 'memcache_invalidation_timestamps', 0.001],
],
# Define a custom cache tags invalidator for the bootstrap container.
'cache_tags_provider.container' => [
'class' => 'Drupal\memcache\Cache\TimestampCacheTagsChecksum',
'arguments' => ['@memcache.backend.timestamp.invalidator'],
'arguments' => ['@memcache.timestamp.invalidator.tag'],
],
'cache.container' => [
'class' => 'Drupal\memcache\MemcacheBackend',
'arguments' => ['container', '@memcache.backend.cache.container', '@cache_tags_provider.container'],
'arguments' => ['container', '@memcache.backend.cache.container', '@cache_tags_provider.container', '@memcache.timestamp.invalidator.bin'],
],
],
];
......
......@@ -9,17 +9,17 @@
services:
# Timestamp invalidation service used for invalidation logic.
memcache.timestamp.invalidator:
memcache.timestamp.invalidator.tag:
class: Drupal\memcache\Invalidator\MemcacheTimestampInvalidator
# Remember to use the same bin as the bootstrap container if you are using it!
# Adjust tolerance factor as appropriate when not running memcache on localhost.
arguments: ['@memcache.factory', 'memcache_invalidation_timestamps', 0.001]
arguments: ['@memcache.factory', 'memcache_tag_timestamps', 0.001]
# Cache tag checksum backend. Used by memcache and most other cache backends
# to deal with cache tag invalidations.
cache_tags.invalidator.checksum:
class: Drupal\memcache\Cache\TimestampCacheTagsChecksum
arguments: ['@memcache.timestamp.invalidator']
arguments: ['@memcache.timestamp.invalidator.tag']
tags:
- { name: cache_tags_invalidator }
......
......@@ -5,9 +5,13 @@ services:
memcache.factory:
class: Drupal\memcache\Driver\MemcacheDriverFactory
arguments: ['@memcache.settings']
memcache.timestamp.invalidator.bin:
class: Drupal\memcache\Invalidator\MemcacheTimestampInvalidator
# Override this service and adjust tolerance if necessary.
arguments: ['@memcache.factory', 'memcache_bin_timestamps', 0.001]
cache.backend.memcache:
class: Drupal\memcache\MemcacheBackendFactory
arguments: ['@memcache.factory', '@cache_tags.invalidator.checksum']
arguments: ['@memcache.factory', '@cache_tags.invalidator.checksum', '@memcache.timestamp.invalidator.bin']
memcache.lock.factory:
class: Drupal\memcache\Lock\MemcacheLockFactory
arguments: ['@memcache.factory']
......@@ -21,7 +21,7 @@ class MemcacheTimestampInvalidator extends TimestampInvalidatorBase {
* @param string $bin Memcache bin to store the timestamps in.
* @param float $tolerance Allowed clock skew between servers, in decimal seconds.
*/
public function __construct(MemcacheDriverFactory $memcache_factory, $bin = 'memcache_invalidation_timestamps', $tolerance = 0.001) {
public function __construct(MemcacheDriverFactory $memcache_factory, $bin, $tolerance = 0.001) {
parent::__construct($tolerance);
$this->memcache = $memcache_factory->get($bin);
}
......
......@@ -5,7 +5,9 @@ namespace Drupal\memcache;
use Drupal\Component\Assertion\Inspector;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Cache\CacheTagsChecksumInterface;
use Drupal\Core\Cache\CacheTagsInvalidatorInterface;
use Drupal\Core\Lock\LockBackendInterface;
use Drupal\memcache\Invalidator\TimestampInvalidatorInterface;
/**
* Defines a Memcache cache backend.
......@@ -36,24 +38,34 @@ class MemcacheBackend implements CacheBackendInterface {
/**
* The cache tags checksum provider.
*
* @var \Drupal\Core\Cache\CacheTagsChecksumInterface
* @var CacheTagsChecksumInterface|CacheTagsInvalidatorInterface
*/
protected $checksumProvider;
/**
* The timestamp invalidation provider.
*
* @var \Drupal\memcache\Invalidator\TimestampInvalidatorInterface
*/
protected $timestampInvalidator;
/**
* Constructs a MemcacheBackend object.
*\Drupal\Core\Site\Settings
*
* @param string $bin
* The bin name.
* @param \Drupal\memcache\DrupalMemcacheInterface $memcache
* The memcache object.
* @param \Drupal\Core\Cache\CacheTagsChecksumInterface $checksum_provider
* @param CacheTagsChecksumInterface $checksum_provider
* The cache tags checksum service.
* @param \Drupal\memcache\Invalidator\TimestampInvalidatorInterface $timestamp_invalidator
*/
public function __construct($bin, DrupalMemcacheInterface $memcache, CacheTagsChecksumInterface $checksum_provider) {
public function __construct($bin, DrupalMemcacheInterface $memcache, CacheTagsChecksumInterface $checksum_provider, TimestampInvalidatorInterface $timestamp_invalidator) {
$this->bin = $bin;
$this->memcache = $memcache;
$this->checksumProvider = $checksum_provider;
$this->timestampInvalidator = $timestamp_invalidator;
$this->ensureBinDeletionTimeIsSet();
}
......@@ -178,14 +190,14 @@ class MemcacheBackend implements CacheBackendInterface {
* {@inheritdoc}
*/
public function deleteAll() {
$this->updateBinLastDeletionTime();
$this->lastBinDeletionTime = $this->timestampInvalidator->invalidateTimestamp($this->bin);
}
/**
* {@inheritdoc}
*/
public function invalidate($cid) {
$this->invalidateMultiple((array) $cid);
$this->invalidateMultiple([$cid]);
}
/**
......@@ -229,7 +241,7 @@ class MemcacheBackend implements CacheBackendInterface {
* {@inheritdoc}
*/
public function removeBin() {
$this->updateBinLastDeletionTime();
$this->lastBinDeletionTime = $this->timestampInvalidator->invalidateTimestamp($this->bin);
}
/**
......@@ -266,14 +278,7 @@ class MemcacheBackend implements CacheBackendInterface {
return FALSE;
}
// Clocks on a single server can drift. Multiple servers may have slightly
// differing opinions about the current time. Given that, do not assume
// 'now' on this server is always later than our stored timestamp.
// Also add 1 millisecond, to ensure that caches written earlier in the same
// millisecond are invalidated. It is possible that caches will be later in
// the same millisecond and are then incorrectly invalidated, but that only
// costs one additional roundtrip to the persistent cache.
return (($item_microtime + .001) > $last_bin_deletion);
return $item_microtime > $last_bin_deletion;
}
/**
......@@ -285,29 +290,12 @@ class MemcacheBackend implements CacheBackendInterface {
*/
protected function getBinLastDeletionTime() {
if (!isset($this->lastBinDeletionTime)) {
$this->lastBinDeletionTime = $this->memcache->get($this->getBinLastDeletionTimeKey());
$this->lastBinDeletionTime = $this->timestampInvalidator->getLastInvalidationTimestamp($this->bin);
}
return $this->lastBinDeletionTime;
}
/**
* Updates the last invalidation time for the bin.
*
* @internal
*
* @return bool|\Drupal\memcache\DrupalMemcacheInterface
*/
protected function updateBinLastDeletionTime() {
$now = round(microtime(TRUE), 3);
$return = $this->memcache->set($this->getBinLastDeletionTimeKey(), $now);
$this->lastBinDeletionTime = $now;
return $return;
}
/**
* Ensures a last bin deletion time has been set.
*
......@@ -315,19 +303,8 @@ class MemcacheBackend implements CacheBackendInterface {
*/
protected function ensureBinDeletionTimeIsSet() {
if (!$this->getBinLastDeletionTime()) {
$this->updateBinLastDeletionTime();
$this->lastBinDeletionTime = $this->timestampInvalidator->invalidateTimestamp($this->bin);
}
}
/**
* Gets the invalidation time cache key.
*
* @internal
*
* @return string
*/
protected function getBinLastDeletionTimeKey() {
return sprintf('bin_deletion:%s', $this->bin);
}
}
......@@ -10,6 +10,7 @@ namespace Drupal\memcache;
use Drupal\Core\Cache\CacheFactoryInterface;
use Drupal\Core\Cache\CacheTagsChecksumInterface;
use Drupal\memcache\Driver\MemcacheDriverFactory;
use Drupal\memcache\Invalidator\TimestampInvalidatorInterface;
/**
* Class MemcacheBackendFactory.
......@@ -30,15 +31,24 @@ class MemcacheBackendFactory implements CacheFactoryInterface {
*/
protected $checksumProvider;
/**
* The timestamp invalidation provider.
*
* @var \Drupal\memcache\Invalidator\TimestampInvalidatorInterface
*/
protected $timestampInvalidator;
/**
* Constructs the DatabaseBackendFactory object.
*
* @param \Drupal\memcache\Driver\MemcacheDriverFactory $memcache_factory
* @param \Drupal\Core\Cache\CacheTagsChecksumInterface $checksum_provider
* @param \Drupal\memcache\Invalidator\TimestampInvalidatorInterface $timestamp_invalidator
*/
function __construct(MemcacheDriverFactory $memcache_factory, CacheTagsChecksumInterface $checksum_provider) {
function __construct(MemcacheDriverFactory $memcache_factory, CacheTagsChecksumInterface $checksum_provider, TimestampInvalidatorInterface $timestamp_invalidator) {
$this->memcacheFactory = $memcache_factory;
$this->checksumProvider = $checksum_provider;
$this->timestampInvalidator = $timestamp_invalidator;
}
/**
......@@ -54,7 +64,8 @@ class MemcacheBackendFactory implements CacheFactoryInterface {
return new MemcacheBackend(
$bin,
$this->memcacheFactory->get($bin),
$this->checksumProvider
$this->checksumProvider,
$this->timestampInvalidator
);
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment