79 MainConfigNames::SQLiteDataDir,
80 MainConfigNames::UpdateRowsPerQuery,
81 MainConfigNames::MemCachedServers,
82 MainConfigNames::MemCachedPersistent,
83 MainConfigNames::MemCachedTimeout,
84 MainConfigNames::CachePrefix,
85 MainConfigNames::ObjectCaches,
86 MainConfigNames::MainCacheType,
87 MainConfigNames::MessageCacheType,
88 MainConfigNames::ParserCacheType,
95 private $instances = [];
96 private string $domainId;
98 private $dbLoadBalancerFactory;
109 callable $dbLoadBalancerFactory,
113 $this->options = $options;
114 $this->stats = $stats;
115 $this->logger = $loggerSpi;
116 $this->dbLoadBalancerFactory = $dbLoadBalancerFactory;
117 $this->domainId = $domainId;
129 private function getDefaultKeyspace(): string {
131 if ( is_string( $cachePrefix ) && $cachePrefix !==
'' ) {
135 return $this->domainId;
144 private function newFromId( $id ):
BagOStuff {
146 $id = $this->getAnythingId();
149 if ( !isset( $this->options->get( MainConfigNames::ObjectCaches )[$id] ) ) {
156 return self::makeLocalServerCache( $this->getDefaultKeyspace() );
157 } elseif ( $id ===
'wincache' ) {
158 wfDeprecated( __METHOD__ .
' with cache ID "wincache"',
'1.43' );
159 return self::makeLocalServerCache( $this->getDefaultKeyspace() );
162 throw new InvalidArgumentException(
"Invalid object cache type \"$id\" requested. " .
163 "It is not present in \$wgObjectCaches." );
166 return $this->newFromParams( $this->options->get( MainConfigNames::ObjectCaches )[$id] );
176 if ( !isset( $this->instances[$id] ) ) {
177 $this->instances[$id] = $this->newFromId( $id );
180 return $this->instances[$id];
199 $logger = $this->logger->getLogger(
$params[
'loggroup'] ??
'objectcache' );
203 'keyspace' => $this->getDefaultKeyspace(),
204 'asyncHandler' => [ DeferredUpdates::class,
'addCallableUpdate' ],
205 'reportDupes' =>
true,
206 'stats' => $this->stats,
209 if ( isset(
$params[
'factory'] ) ) {
212 return call_user_func(
$params[
'factory'], ...$args );
215 if ( !isset(
$params[
'class'] ) ) {
216 throw new InvalidArgumentException(
217 'No "factory" nor "class" provided; got "' . print_r(
$params,
true ) .
'"'
224 if ( is_a( $class, SqlBagOStuff::class,
true ) ) {
225 $this->prepareSqlBagOStuffFromParams(
$params );
229 if ( is_subclass_of( $class, MemcachedBagOStuff::class ) ) {
230 $this->prepareMemcachedBagOStuffFromParams(
$params );
234 if ( is_a( $class, MultiWriteBagOStuff::class,
true ) ) {
235 $this->prepareMultiWriteBagOStuffFromParams(
$params );
237 if ( is_a( $class, RESTBagOStuff::class,
true ) ) {
238 $this->prepareRESTBagOStuffFromParams(
$params );
244 private function prepareSqlBagOStuffFromParams( array &
$params ): void {
246 throw new InvalidArgumentException(
247 'globalKeyLB in $wgObjectCaches is no longer supported' );
249 if ( isset(
$params[
'server'] ) && !isset(
$params[
'servers'] ) ) {
253 if ( isset(
$params[
'servers'] ) ) {
255 foreach (
$params[
'servers'] as &$server ) {
256 if ( $server[
'type'] ===
'sqlite' && !isset( $server[
'dbDirectory'] ) ) {
257 $server[
'dbDirectory'] = $this->options->get( MainConfigNames::SQLiteDataDir );
260 } elseif ( isset(
$params[
'cluster'] ) ) {
262 $dbLbFactory = $this->dbLoadBalancerFactory;
263 $params[
'loadBalancerCallback'] =
static function () use ( $cluster, $dbLbFactory ) {
264 return $dbLbFactory()->getExternalLB( $cluster );
266 $params += [
'dbDomain' => false ];
268 $dbLbFactory = $this->dbLoadBalancerFactory;
269 $params[
'loadBalancerCallback'] =
static function () use ( $dbLbFactory ) {
270 return $dbLbFactory()->getMainLb();
272 $params += [
'dbDomain' => false ];
274 $params += [
'writeBatchSize' => $this->options->get( MainConfigNames::UpdateRowsPerQuery ) ];
277 private function prepareMemcachedBagOStuffFromParams( array &
$params ): void {
280 'persistent' => $this->options->get(
MainConfigNames::MemCachedPersistent ),
285 private function prepareMultiWriteBagOStuffFromParams( array &
$params ): void {
288 '@phan-var array{caches:array[]} $params';
289 foreach (
$params[
'caches'] ?? [] as $i => $cacheInfo ) {
292 $params[
'caches'][$i] = $this->newFromParams( $cacheInfo );
296 private function prepareRESTBagOStuffFromParams( array &
$params ): void {
322 $cache = $this->getInstance(
$fallback );
332 $this->instances = [];
339 private static function getLocalServerCacheClass() {
340 if ( self::$localServerCacheClass !==
null ) {
341 return self::$localServerCacheClass;
343 if ( function_exists(
'apcu_fetch' ) ) {
345 if ( PHP_SAPI !==
'cli' || ini_get(
'apc.enable_cli' ) ) {
346 return APCUBagOStuff::class;
351 return EmptyBagOStuff::class;
362 $this->options->get( MainConfigNames::MainCacheType ),
363 $this->options->get( MainConfigNames::MessageCacheType ),
364 $this->options->get( MainConfigNames::ParserCacheType )
366 foreach ( $candidates as $candidate ) {
370 $class = self::getLocalServerCacheClass();
371 if ( $class !== EmptyBagOStuff::class ) {
379 $services = MediaWikiServices::getInstance();
381 if ( $services->isServiceDisabled(
'DBLoadBalancer' ) ) {
384 } elseif ( $services->isStorageDisabled() ) {
415 'reportDupes' =>
false,
417 'keyspace' => $keyspace,
419 $class = self::getLocalServerCacheClass();
436 $id = $this->getAnythingId();
437 return $this->isDatabaseId( $id );
440 if ( !isset( $this->options->get( MainConfigNames::ObjectCaches )[$id] ) ) {
443 $cache = $this->options->get( MainConfigNames::ObjectCaches )[$id];
444 if ( ( $cache[
'class'] ??
'' ) === SqlBagOStuff::class ) {
458 return $this->getInstance(
459 $this->options->get( MainConfigNames::MainCacheType )
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.