// 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 );
}
}
}
// Fake initial check key to be set in the past. Otherwise we'd have to sleep for
// several seconds during the test to assert the behaviour.
foreach ( array( $checkAll, $check1, $check2 ) as $checkKey ) {
- $this->internalCache->set( $cache::TIME_KEY_PREFIX . $checkKey,
- $cache::PURGE_VAL_PREFIX . microtime( true ) - $cache::HOLDOFF_TTL, $cache::CHECK_KEY_TTL );
+ $cache->touchCheckKey( $checkKey, WANObjectCache::HOLDOFF_NONE );
}
+ usleep( 100 );
$cache->set( 'key1', $value1, 10 );
$cache->set( 'key2', $value2, 10 );
$result,
'Initial values'
);
- $this->assertEquals(
- array( 'key1' => 0, 'key2' => 0 ),
- $curTTLs,
- 'Initial ttls'
- );
+ $this->assertGreaterThanOrEqual( 9.5, $curTTLs['key1'], 'Initial ttls' );
+ $this->assertLessThanOrEqual( 10.5, $curTTLs['key1'], 'Initial ttls' );
+ $this->assertGreaterThanOrEqual( 9.5, $curTTLs['key2'], 'Initial ttls' );
+ $this->assertLessThanOrEqual( 10.5, $curTTLs['key2'], 'Initial ttls' );
$cache->touchCheckKey( $check1 );
- usleep( 100 );
$curTTLs = array();
$result = $cache->getMulti( array( 'key1', 'key2', 'key3' ), $curTTLs, array(
'key1 expired by check1, but value still provided'
);
$this->assertLessThan( 0, $curTTLs['key1'], 'key1 TTL expired' );
- $this->assertEquals( 0, $curTTLs['key2'], 'key2 still valid' );
+ $this->assertGreaterThan( 0, $curTTLs['key2'], 'key2 still valid' );
$cache->touchCheckKey( $checkAll );
- usleep( 100 );
$curTTLs = array();
$result = $cache->getMulti( array( 'key1', 'key2', 'key3' ), $curTTLs, array(
$this->assertLessThan( 0, $curTTLs['key2'], 'key2 expired by checkAll' );
}
+ /**
+ * @covers WANObjectCache::get()
+ * @covers WANObjectCache::processCheckKeys()
+ */
+ public function testCheckKeyInitHoldoff() {
+ $cache = $this->cache;
+
+ for ( $i = 0; $i < 500; ++$i ) {
+ $key = wfRandomString();
+ $checkKey = wfRandomString();
+ // miss, set, hit
+ $cache->get( $key, $curTTL, array( $checkKey ) );
+ $cache->set( $key, 'val', 10 );
+ $curTTL = null;
+ $v = $cache->get( $key, $curTTL, array( $checkKey ) );
+
+ $this->assertEquals( 'val', $v );
+ $this->assertLessThan( 0, $curTTL, "Step $i: CTL < 0 (miss/set/hit)" );
+ }
+
+ for ( $i = 0; $i < 500; ++$i ) {
+ $key = wfRandomString();
+ $checkKey = wfRandomString();
+ // set, hit
+ $cache->set( $key, 'val', 10 );
+ $curTTL = null;
+ $v = $cache->get( $key, $curTTL, array( $checkKey ) );
+
+ $this->assertEquals( 'val', $v );
+ $this->assertLessThan( 0, $curTTL, "Step $i: CTL < 0 (set/hit)" );
+ }
+ }
+
/**
* @covers WANObjectCache::delete()
*/