mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Echo
synced 2024-11-23 23:44:53 +00:00
ef50bfeda5
Singletons are bad, amongst other reasons, because they're never reset in tests. They can therefore occasionally cause test failures if the cached data stored in one of these singletons becomes stale. As noted on the task, ideally these two classes shouldn't exist at all, and core should be responsible for caching the information it deems expensive to compute. As a temporary (TM) workaround, make both classes actual services, so that the setUp/tearDown logic in MediaWikiIntegrationTestCase can properly reset them between tests. Dependencies are intentionally not being injected, precisely because these classes should just be deleted, not improved. Bug: T344124 Change-Id: I58b8d9610f9447468235b94d25732528ab6acce6
101 lines
2 KiB
PHP
101 lines
2 KiB
PHP
<?php
|
|
|
|
namespace MediaWiki\Extension\Notifications\Cache;
|
|
|
|
use Iterator;
|
|
use MapCacheLRU;
|
|
|
|
/**
|
|
* Base Local cache object, which borrows the concept from Flow user listener
|
|
*/
|
|
abstract class LocalCache {
|
|
|
|
/**
|
|
* Max number of objects to hold in $targets. In theory, 1000
|
|
* is very hard to reach in a normal web request. We need to
|
|
* put cap, so it doesn't reach memory limit when running email
|
|
* digest against large amount of notifications
|
|
*/
|
|
private const TARGET_MAX_NUM = 1000;
|
|
|
|
/**
|
|
* Target object cache
|
|
* @var MapCacheLRU
|
|
*/
|
|
protected $targets;
|
|
|
|
/**
|
|
* Lookup ids that have not been resolved for a target
|
|
* @var bool[]
|
|
*/
|
|
private $lookups = [];
|
|
|
|
/**
|
|
* Resolve ids in lookups to targets
|
|
*
|
|
* @param int[] $lookups
|
|
* @return Iterator
|
|
*/
|
|
abstract protected function resolve( array $lookups );
|
|
|
|
/**
|
|
* Instances should be obtained via EchoServices / MediaWikiServices.
|
|
*
|
|
* @private
|
|
*/
|
|
public function __construct() {
|
|
$this->targets = new MapCacheLRU( self::TARGET_MAX_NUM );
|
|
}
|
|
|
|
/**
|
|
* Add a key to the lookup and the key is used to resolve cache target
|
|
*
|
|
* @param int $key
|
|
*/
|
|
public function add( $key ) {
|
|
if (
|
|
count( $this->lookups ) < self::TARGET_MAX_NUM
|
|
&& !$this->targets->get( (string)$key )
|
|
) {
|
|
$this->lookups[$key] = true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get the cache target based on the key
|
|
*
|
|
* @param int $key
|
|
* @return mixed|null
|
|
*/
|
|
public function get( $key ) {
|
|
$target = $this->targets->get( (string)$key );
|
|
if ( $target ) {
|
|
return $target;
|
|
}
|
|
|
|
if ( isset( $this->lookups[ $key ] ) ) {
|
|
// Resolve the lookup batch and store results in the cache
|
|
$targets = $this->resolve( array_keys( $this->lookups ) );
|
|
foreach ( $targets as $id => $val ) {
|
|
$this->targets->set( $id, $val );
|
|
}
|
|
$this->lookups = [];
|
|
$target = $this->targets->get( (string)$key );
|
|
if ( $target ) {
|
|
return $target;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Clear everything in local cache
|
|
*/
|
|
public function clearAll() {
|
|
$this->targets->clear();
|
|
$this->lookups = [];
|
|
}
|
|
|
|
}
|