78 MainConfigNames::SQLiteDataDir,
79 MainConfigNames::UpdateRowsPerQuery,
80 MainConfigNames::MemCachedServers,
81 MainConfigNames::MemCachedPersistent,
82 MainConfigNames::MemCachedTimeout,
83 MainConfigNames::CachePrefix,
84 MainConfigNames::ObjectCaches,
85 MainConfigNames::MainCacheType,
86 MainConfigNames::MessageCacheType,
87 MainConfigNames::ParserCacheType,
95 private $instances = [];
96 private string $domainId;
98 private $dbLoadBalancerFactory;
109 callable $dbLoadBalancerFactory,
114 $this->options = $options;
115 $this->stats = $stats;
116 $this->logger = $loggerSpi;
117 $this->dbLoadBalancerFactory = $dbLoadBalancerFactory;
118 $this->domainId = $domainId;
119 $this->telemetry = $telemetry;
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,
207 'telemetry' => $this->telemetry,
210 if ( isset( $params[
'factory'] ) ) {
211 $args = $params[
'args'] ?? [ $params ];
213 return $params[
'factory']( ...$args );
216 if ( !isset( $params[
'class'] ) ) {
217 throw new InvalidArgumentException(
218 'No "factory" nor "class" provided; got "' . print_r( $params,
true ) .
'"'
225 if ( is_a( $class, SqlBagOStuff::class,
true ) ) {
226 $this->prepareSqlBagOStuffFromParams( $params );
230 if ( is_subclass_of( $class, MemcachedBagOStuff::class ) ) {
231 $this->prepareMemcachedBagOStuffFromParams( $params );
235 if ( is_a( $class, MultiWriteBagOStuff::class,
true ) ) {
236 $this->prepareMultiWriteBagOStuffFromParams( $params );
239 return new $class( $params );
242 private function prepareSqlBagOStuffFromParams( array &$params ): void {
244 throw new InvalidArgumentException(
245 'globalKeyLB in $wgObjectCaches is no longer supported' );
247 if ( isset( $params[
'server'] ) && !isset( $params[
'servers'] ) ) {
249 unset( $params[
'server'] );
251 if ( isset( $params[
'servers'] ) ) {
253 foreach ( $params[
'servers'] as &$server ) {
254 if ( $server[
'type'] ===
'sqlite' && !isset( $server[
'dbDirectory'] ) ) {
255 $server[
'dbDirectory'] = $this->options->get( MainConfigNames::SQLiteDataDir );
258 } elseif ( isset( $params[
'cluster'] ) ) {
260 $dbLbFactory = $this->dbLoadBalancerFactory;
261 $params[
'loadBalancerCallback'] =
static function () use ( $cluster, $dbLbFactory ) {
262 return $dbLbFactory()->getExternalLB( $cluster );
264 $params += [
'dbDomain' => false ];
266 $dbLbFactory = $this->dbLoadBalancerFactory;
267 $params[
'loadBalancerCallback'] =
static function () use ( $dbLbFactory ) {
268 return $dbLbFactory()->getMainLb();
270 $params += [
'dbDomain' => false ];
272 $params += [
'writeBatchSize' => $this->options->get( MainConfigNames::UpdateRowsPerQuery ) ];
275 private function prepareMemcachedBagOStuffFromParams( array &$params ): void {
278 'persistent' => $this->options->get(
MainConfigNames::MemCachedPersistent ),
283 private function prepareMultiWriteBagOStuffFromParams( array &$params ): void {
286 '@phan-var array{caches:array[]} $params';
287 foreach ( $params[
'caches'] ?? [] as $i => $cacheInfo ) {
290 $params[
'caches'][$i] = $this->newFromParams( $cacheInfo );
316 $cache = $this->getInstance(
$fallback );
326 $this->instances = [];
333 private static function getLocalServerCacheClass() {
334 if ( self::$localServerCacheClass !==
null ) {
335 return self::$localServerCacheClass;
337 if ( function_exists(
'apcu_fetch' ) ) {
339 if ( PHP_SAPI !==
'cli' || ini_get(
'apc.enable_cli' ) ) {
340 return APCUBagOStuff::class;
345 return EmptyBagOStuff::class;
356 $this->options->get( MainConfigNames::MainCacheType ),
357 $this->options->get( MainConfigNames::MessageCacheType ),
358 $this->options->get( MainConfigNames::ParserCacheType )
360 foreach ( $candidates as $candidate ) {
364 $class = self::getLocalServerCacheClass();
365 if ( $class !== EmptyBagOStuff::class ) {
373 $services = MediaWikiServices::getInstance();
375 if ( $services->isServiceDisabled(
'DBLoadBalancer' ) ) {
378 } elseif ( $services->isStorageDisabled() ) {
409 'reportDupes' =>
false,
411 'keyspace' => $keyspace,
413 $class = self::getLocalServerCacheClass();
414 return new $class( $params );
430 $id = $this->getAnythingId();
431 return $this->isDatabaseId( $id );
434 if ( !isset( $this->options->get( MainConfigNames::ObjectCaches )[$id] ) ) {
437 $cache = $this->options->get( MainConfigNames::ObjectCaches )[$id];
438 if ( ( $cache[
'class'] ??
'' ) === SqlBagOStuff::class ) {
452 return $this->getInstance(
453 $this->options->get( MainConfigNames::MainCacheType )
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
__construct(ServiceOptions $options, StatsFactory $stats, Spi $loggerSpi, callable $dbLoadBalancerFactory, string $domainId, TracerInterface $telemetry)