The `SettingsBuilder` now accepts a PSR-16 cache interface with which to store and query settings before attempting to load from each source. By default, no cache is used, but any object that implements the `Psr\SimpleCache\CacheInterface` may be provided to the constructor. An explicit dependency on "psr/simple-cache" has been added to `composer.json`. Note that this dependency already existed in vendor albeit it as a transitive one. An APCu based `SharedMemoryCache` adapter is provided as a canonical PSR-16 compliant interface for production use. Sources are now queued by the `SettingsBuilder` when calling `load()`. If a cache interface has been provided, and the source is considered cacheable (implements `CacheableSource`), then it is wrapped as a `CachedSource` which will query the cache first before loading from the wrapped source. Cache stampedes are mitigated using probabilistic early expiry. The implementation for this was partially based on symfony/cache-contract source code but also from the Wikipedia article and paper referenced therein. See https://en.wikipedia.org/wiki/Cache_stampede#Probabilistic_early_expiration Bug: T294748 Change-Id: I52ab3899731546876ee58265bd4a1927886746dc
94 lines
2.2 KiB
PHP
94 lines
2.2 KiB
PHP
<?php
|
|
|
|
namespace MediaWiki\Tests\Unit\Settings\Cache;
|
|
|
|
use DateInterval;
|
|
use Psr\SimpleCache\CacheInterface;
|
|
|
|
trait CacheInterfaceTestTrait {
|
|
abstract protected function newCache(): CacheInterface;
|
|
|
|
public function testSetAndGet() {
|
|
$cache = $this->newCache();
|
|
|
|
$cache->set( 'one', 'fish1' );
|
|
$cache->set( 'two', 'fish2', 60 );
|
|
$cache->set( 'red', 'fish3', DateInterval::createFromDateString( '@60' ) );
|
|
|
|
$this->assertSame( 'fish1', $cache->get( 'one' ) );
|
|
$this->assertSame( 'fish2', $cache->get( 'two' ) );
|
|
$this->assertSame( 'fish3', $cache->get( 'red' ) );
|
|
$this->assertSame( 'fish4', $cache->get( 'blue', 'fish4' ) );
|
|
}
|
|
|
|
public function testSetAndGetMultiple() {
|
|
$cache = $this->newCache();
|
|
|
|
$cache->setMultiple(
|
|
[
|
|
'one' => 'fish1',
|
|
'two' => 'fish2',
|
|
'red' => 'fish3',
|
|
]
|
|
);
|
|
|
|
$this->assertSame(
|
|
[
|
|
'one' => 'fish1',
|
|
'two' => 'fish2',
|
|
'red' => 'fish3',
|
|
'blue' => 'fish4',
|
|
],
|
|
$cache->getMultiple( [ 'one', 'two', 'red', 'blue' ], 'fish4' )
|
|
);
|
|
}
|
|
|
|
public function testDeleteAndHas() {
|
|
$cache = $this->newCache();
|
|
|
|
$cache->set( 'red', 'fish' );
|
|
$cache->set( 'blue', 'fish' );
|
|
|
|
$cache->delete( 'red' );
|
|
|
|
$this->assertFalse( $cache->has( 'red' ) );
|
|
$this->assertTrue( $cache->has( 'blue' ) );
|
|
}
|
|
|
|
public function testDeleteMultiple() {
|
|
$cache = $this->newCache();
|
|
|
|
$cache->set( 'one', 'fish' );
|
|
$cache->set( 'two', 'fish' );
|
|
$cache->set( 'red', 'fish' );
|
|
$cache->set( 'blue', 'fish' );
|
|
|
|
$cache->deleteMultiple( [ 'two', 'red' ] );
|
|
|
|
$this->assertTrue( $cache->has( 'one' ) );
|
|
$this->assertFalse( $cache->has( 'two' ) );
|
|
$this->assertFalse( $cache->has( 'red' ) );
|
|
$this->assertTrue( $cache->has( 'blue' ) );
|
|
}
|
|
|
|
public function testClear() {
|
|
$cache = $this->newCache();
|
|
|
|
$cache->set( 'one', 'fish' );
|
|
$cache->set( 'two', 'fish' );
|
|
$cache->set( 'red', 'fish' );
|
|
$cache->set( 'blue', 'fish' );
|
|
|
|
$this->assertTrue( $cache->has( 'one' ) );
|
|
$this->assertTrue( $cache->has( 'two' ) );
|
|
$this->assertTrue( $cache->has( 'red' ) );
|
|
$this->assertTrue( $cache->has( 'blue' ) );
|
|
|
|
$cache->clear();
|
|
|
|
$this->assertFalse( $cache->has( 'one' ) );
|
|
$this->assertFalse( $cache->has( 'two' ) );
|
|
$this->assertFalse( $cache->has( 'red' ) );
|
|
$this->assertFalse( $cache->has( 'blue' ) );
|
|
}
|
|
}
|