// Fetch all of the raw values
$wrappedValues = $this->cache->getMulti( array_merge( $valueKeys, $checkKeysFlat ) );
+ // Time used to compare/init "check" keys (derived after getMulti() to be pessimistic)
$now = microtime( true );
// Collect timestamps from all "check" keys
foreach ( $purgeValues as $purge ) {
$safeTimestamp = $purge[self::FLD_TIME] + $purge[self::FLD_HOLDOFF];
if ( $safeTimestamp >= $wrappedValues[$vKey][self::FLD_TIME] ) {
- $curTTL = min( $curTTL, $purge[self::FLD_TIME] - $now );
+ // How long ago this value was expired by *this* check key
+ $ago = min( $purge[self::FLD_TIME] - $now, self::TINY_NEGATIVE );
+ // How long ago this value was expired by *any* known check key
+ $curTTL = min( $curTTL, $ago );
}
}
}
$wrapExtra = array(); // additional wrapped value fields
// Check if there's a risk of writing stale data after the purge tombstone expired
- if ( ( $lag + $age ) > self::MAX_READ_LAG ) {
+ if ( $lag === false || ( $lag + $age ) > self::MAX_READ_LAG ) {
// Case A: read lag with "lockTSE"; save but record value as stale
if ( $lockTSE >= 0 ) {
$ttl = max( 1, (int)$lockTSE ); // set() expects seconds
return true; // no-op the write for being unsafe
// Case C: high replication lag; lower TTL instead of ignoring all set()s
- } elseif ( $lag > self::MAX_READ_LAG ) {
+ } elseif ( $lag === false || $lag > self::MAX_READ_LAG ) {
$ttl = $ttl ? min( $ttl, self::TTL_LAGGED ) : self::TTL_LAGGED;
$this->logger->warning( "Lowered set() TTL for $key due to replication lag." );
// Case D: medium length request with medium replication lag; ignore this set()
* @see WANObjectCache::resetCheckKey()
*
* @param string $key Cache key
+ * @param int $holdoff HOLDOFF_TTL or HOLDOFF_NONE constant
* @return bool True if the item was purged or not found, false on failure
*/
- final public function touchCheckKey( $key ) {
+ final public function touchCheckKey( $key, $holdoff = self::HOLDOFF_TTL ) {
$key = self::TIME_KEY_PREFIX . $key;
// Update the local datacenter immediately
$ok = $this->cache->set( $key,
- $this->makePurgeValue( microtime( true ), self::HOLDOFF_TTL ),
+ $this->makePurgeValue( microtime( true ), $holdoff ),
self::CHECK_KEY_TTL
);
// Publish the purge to all datacenters
- return $this->relayPurge( $key, self::CHECK_KEY_TTL, self::HOLDOFF_TTL ) && $ok;
+ return $this->relayPurge( $key, self::CHECK_KEY_TTL, $holdoff ) && $ok;
}
/**
*
* @param string $key Cache key
* @param integer $ttl How long to keep the tombstone [seconds]
- * @param holdoff $ttl HOLDOFF_* constant controlling how long to ignore sets for this key
+ * @param integer $holdoff HOLDOFF_* constant controlling how long to ignore sets for this key
* @return bool Success
*/
protected function relayPurge( $key, $ttl, $holdoff ) {
* @param int $holdoff In seconds
* @return string Wrapped purge value
*/
- protected static function makePurgeValue( $timestamp, $holdoff ) {
+ protected function makePurgeValue( $timestamp, $holdoff ) {
return self::PURGE_VAL_PREFIX . (float)$timestamp . ':' . (int)$holdoff;
}
}