MediaWiki  1.28.0
LBFactory.php
Go to the documentation of this file.
1 <?php
26 
31 abstract class LBFactory implements ILBFactory {
33  protected $chronProt;
35  protected $profiler;
37  protected $trxProfiler;
39  protected $replLogger;
41  protected $connLogger;
43  protected $queryLogger;
45  protected $perfLogger;
47  protected $errorLogger;
49  protected $srvCache;
51  protected $memCache;
53  protected $wanCache;
54 
56  protected $localDomain;
58  protected $hostname;
60  protected $requestInfo;
61 
63  protected $ticket;
65  protected $trxRoundId = false;
67  protected $readOnlyReason = false;
69  protected $replicationWaitCallbacks = [];
70 
72  protected $cliMode;
74  protected $agent;
75 
76  private static $loggerFields =
77  [ 'replLogger', 'connLogger', 'queryLogger', 'perfLogger' ];
78 
79  public function __construct( array $conf ) {
80  $this->localDomain = isset( $conf['localDomain'] )
81  ? DatabaseDomain::newFromId( $conf['localDomain'] )
83 
84  if ( isset( $conf['readOnlyReason'] ) && is_string( $conf['readOnlyReason'] ) ) {
85  $this->readOnlyReason = $conf['readOnlyReason'];
86  }
87 
88  $this->srvCache = isset( $conf['srvCache'] ) ? $conf['srvCache'] : new EmptyBagOStuff();
89  $this->memCache = isset( $conf['memCache'] ) ? $conf['memCache'] : new EmptyBagOStuff();
90  $this->wanCache = isset( $conf['wanCache'] )
91  ? $conf['wanCache']
93 
94  foreach ( self::$loggerFields as $key ) {
95  $this->$key = isset( $conf[$key] ) ? $conf[$key] : new \Psr\Log\NullLogger();
96  }
97  $this->errorLogger = isset( $conf['errorLogger'] )
98  ? $conf['errorLogger']
99  : function ( Exception $e ) {
100  trigger_error( E_USER_WARNING, get_class( $e ) . ': ' . $e->getMessage() );
101  };
102 
103  $this->profiler = isset( $params['profiler'] ) ? $params['profiler'] : null;
104  $this->trxProfiler = isset( $conf['trxProfiler'] )
105  ? $conf['trxProfiler']
106  : new TransactionProfiler();
107 
108  $this->requestInfo = [
109  'IPAddress' => isset( $_SERVER[ 'REMOTE_ADDR' ] ) ? $_SERVER[ 'REMOTE_ADDR' ] : '',
110  'UserAgent' => isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : '',
111  'ChronologyProtection' => 'true'
112  ];
113 
114  $this->cliMode = isset( $params['cliMode'] ) ? $params['cliMode'] : PHP_SAPI === 'cli';
115  $this->hostname = isset( $conf['hostname'] ) ? $conf['hostname'] : gethostname();
116  $this->agent = isset( $params['agent'] ) ? $params['agent'] : '';
117 
118  $this->ticket = mt_rand();
119  }
120 
121  public function destroy() {
122  $this->shutdown( self::SHUTDOWN_NO_CHRONPROT );
123  $this->forEachLBCallMethod( 'disable' );
124  }
125 
126  public function shutdown(
127  $mode = self::SHUTDOWN_CHRONPROT_SYNC, callable $workCallback = null
128  ) {
130  if ( $mode === self::SHUTDOWN_CHRONPROT_SYNC ) {
131  $this->shutdownChronologyProtector( $chronProt, $workCallback, 'sync' );
132  } elseif ( $mode === self::SHUTDOWN_CHRONPROT_ASYNC ) {
133  $this->shutdownChronologyProtector( $chronProt, null, 'async' );
134  }
135 
136  $this->commitMasterChanges( __METHOD__ ); // sanity
137  }
138 
144  abstract public function newMainLB( $domain = false );
145 
151  abstract public function getMainLB( $domain = false );
152 
158  abstract public function newExternalLB( $cluster );
159 
165  abstract public function getExternalLB( $cluster );
166 
173  protected function forEachLBCallMethod( $methodName, array $args = [] ) {
174  $this->forEachLB(
175  function ( ILoadBalancer $loadBalancer, $methodName, array $args ) {
176  call_user_func_array( [ $loadBalancer, $methodName ], $args );
177  },
178  [ $methodName, $args ]
179  );
180  }
181 
182  public function flushReplicaSnapshots( $fname = __METHOD__ ) {
183  $this->forEachLBCallMethod( 'flushReplicaSnapshots', [ $fname ] );
184  }
185 
186  public function commitAll( $fname = __METHOD__, array $options = [] ) {
188  $this->forEachLBCallMethod( 'commitAll', [ $fname ] );
189  }
190 
191  public function beginMasterChanges( $fname = __METHOD__ ) {
192  if ( $this->trxRoundId !== false ) {
193  throw new DBTransactionError(
194  null,
195  "$fname: transaction round '{$this->trxRoundId}' already started."
196  );
197  }
198  $this->trxRoundId = $fname;
199  // Set DBO_TRX flags on all appropriate DBs
200  $this->forEachLBCallMethod( 'beginMasterChanges', [ $fname ] );
201  }
202 
203  public function commitMasterChanges( $fname = __METHOD__, array $options = [] ) {
204  if ( $this->trxRoundId !== false && $this->trxRoundId !== $fname ) {
205  throw new DBTransactionError(
206  null,
207  "$fname: transaction round '{$this->trxRoundId}' still running."
208  );
209  }
211  $scope = $this->getScopedPHPBehaviorForCommit(); // try to ignore client aborts
212  // Run pre-commit callbacks and suppress post-commit callbacks, aborting on failure
213  $this->forEachLBCallMethod( 'finalizeMasterChanges' );
214  $this->trxRoundId = false;
215  // Perform pre-commit checks, aborting on failure
216  $this->forEachLBCallMethod( 'approveMasterChanges', [ $options ] );
217  // Log the DBs and methods involved in multi-DB transactions
218  $this->logIfMultiDbTransaction();
219  // Actually perform the commit on all master DB connections and revert DBO_TRX
220  $this->forEachLBCallMethod( 'commitMasterChanges', [ $fname ] );
221  // Run all post-commit callbacks
223  $e = null; // first callback exception
224  $this->forEachLB( function ( ILoadBalancer $lb ) use ( &$e ) {
225  $ex = $lb->runMasterPostTrxCallbacks( IDatabase::TRIGGER_COMMIT );
226  $e = $e ?: $ex;
227  } );
228  // Commit any dangling DBO_TRX transactions from callbacks on one DB to another DB
229  $this->forEachLBCallMethod( 'commitMasterChanges', [ $fname ] );
230  // Throw any last post-commit callback error
231  if ( $e instanceof Exception ) {
232  throw $e;
233  }
234  }
235 
236  public function rollbackMasterChanges( $fname = __METHOD__ ) {
237  $this->trxRoundId = false;
238  $this->forEachLBCallMethod( 'suppressTransactionEndCallbacks' );
239  $this->forEachLBCallMethod( 'rollbackMasterChanges', [ $fname ] );
240  // Run all post-rollback callbacks
241  $this->forEachLB( function ( ILoadBalancer $lb ) {
242  $lb->runMasterPostTrxCallbacks( IDatabase::TRIGGER_ROLLBACK );
243  } );
244  }
245 
249  private function logIfMultiDbTransaction() {
250  $callersByDB = [];
251  $this->forEachLB( function ( ILoadBalancer $lb ) use ( &$callersByDB ) {
252  $masterName = $lb->getServerName( $lb->getWriterIndex() );
253  $callers = $lb->pendingMasterChangeCallers();
254  if ( $callers ) {
255  $callersByDB[$masterName] = $callers;
256  }
257  } );
258 
259  if ( count( $callersByDB ) >= 2 ) {
260  $dbs = implode( ', ', array_keys( $callersByDB ) );
261  $msg = "Multi-DB transaction [{$dbs}]:\n";
262  foreach ( $callersByDB as $db => $callers ) {
263  $msg .= "$db: " . implode( '; ', $callers ) . "\n";
264  }
265  $this->queryLogger->info( $msg );
266  }
267  }
268 
269  public function hasMasterChanges() {
270  $ret = false;
271  $this->forEachLB( function ( ILoadBalancer $lb ) use ( &$ret ) {
272  $ret = $ret || $lb->hasMasterChanges();
273  } );
274 
275  return $ret;
276  }
277 
278  public function laggedReplicaUsed() {
279  $ret = false;
280  $this->forEachLB( function ( ILoadBalancer $lb ) use ( &$ret ) {
281  $ret = $ret || $lb->laggedReplicaUsed();
282  } );
283 
284  return $ret;
285  }
286 
287  public function hasOrMadeRecentMasterChanges( $age = null ) {
288  $ret = false;
289  $this->forEachLB( function ( ILoadBalancer $lb ) use ( $age, &$ret ) {
290  $ret = $ret || $lb->hasOrMadeRecentMasterChanges( $age );
291  } );
292  return $ret;
293  }
294 
295  public function waitForReplication( array $opts = [] ) {
296  $opts += [
297  'domain' => false,
298  'cluster' => false,
299  'timeout' => 60,
300  'ifWritesSince' => null
301  ];
302 
303  if ( $opts['domain'] === false && isset( $opts['wiki'] ) ) {
304  $opts['domain'] = $opts['wiki']; // b/c
305  }
306 
307  // Figure out which clusters need to be checked
309  $lbs = [];
310  if ( $opts['cluster'] !== false ) {
311  $lbs[] = $this->getExternalLB( $opts['cluster'] );
312  } elseif ( $opts['domain'] !== false ) {
313  $lbs[] = $this->getMainLB( $opts['domain'] );
314  } else {
315  $this->forEachLB( function ( ILoadBalancer $lb ) use ( &$lbs ) {
316  $lbs[] = $lb;
317  } );
318  if ( !$lbs ) {
319  return; // nothing actually used
320  }
321  }
322 
323  // Get all the master positions of applicable DBs right now.
324  // This can be faster since waiting on one cluster reduces the
325  // time needed to wait on the next clusters.
326  $masterPositions = array_fill( 0, count( $lbs ), false );
327  foreach ( $lbs as $i => $lb ) {
328  if ( $lb->getServerCount() <= 1 ) {
329  // Bug 27975 - Don't try to wait for replica DBs if there are none
330  // Prevents permission error when getting master position
331  continue;
332  } elseif ( $opts['ifWritesSince']
333  && $lb->lastMasterChangeTimestamp() < $opts['ifWritesSince']
334  ) {
335  continue; // no writes since the last wait
336  }
337  $masterPositions[$i] = $lb->getMasterPos();
338  }
339 
340  // Run any listener callbacks *after* getting the DB positions. The more
341  // time spent in the callbacks, the less time is spent in waitForAll().
342  foreach ( $this->replicationWaitCallbacks as $callback ) {
343  $callback();
344  }
345 
346  $failed = [];
347  foreach ( $lbs as $i => $lb ) {
348  if ( $masterPositions[$i] ) {
349  // The DBMS may not support getMasterPos()
350  if ( !$lb->waitForAll( $masterPositions[$i], $opts['timeout'] ) ) {
351  $failed[] = $lb->getServerName( $lb->getWriterIndex() );
352  }
353  }
354  }
355 
356  if ( $failed ) {
357  throw new DBReplicationWaitError(
358  "Could not wait for replica DBs to catch up to " .
359  implode( ', ', $failed )
360  );
361  }
362  }
363 
364  public function setWaitForReplicationListener( $name, callable $callback = null ) {
365  if ( $callback ) {
366  $this->replicationWaitCallbacks[$name] = $callback;
367  } else {
368  unset( $this->replicationWaitCallbacks[$name] );
369  }
370  }
371 
372  public function getEmptyTransactionTicket( $fname ) {
373  if ( $this->hasMasterChanges() ) {
374  $this->queryLogger->error( __METHOD__ . ": $fname does not have outer scope.\n" .
375  ( new RuntimeException() )->getTraceAsString() );
376 
377  return null;
378  }
379 
380  return $this->ticket;
381  }
382 
383  public function commitAndWaitForReplication( $fname, $ticket, array $opts = [] ) {
384  if ( $ticket !== $this->ticket ) {
385  $this->perfLogger->error( __METHOD__ . ": $fname does not have outer scope.\n" .
386  ( new RuntimeException() )->getTraceAsString() );
387 
388  return;
389  }
390 
391  // The transaction owner and any caller with the empty transaction ticket can commit
392  // so that getEmptyTransactionTicket() callers don't risk seeing DBTransactionError.
393  if ( $this->trxRoundId !== false && $fname !== $this->trxRoundId ) {
394  $this->queryLogger->info( "$fname: committing on behalf of {$this->trxRoundId}." );
395  $fnameEffective = $this->trxRoundId;
396  } else {
397  $fnameEffective = $fname;
398  }
399 
400  $this->commitMasterChanges( $fnameEffective );
401  $this->waitForReplication( $opts );
402  // If a nested caller committed on behalf of $fname, start another empty $fname
403  // transaction, leaving the caller with the same empty transaction state as before.
404  if ( $fnameEffective !== $fname ) {
405  $this->beginMasterChanges( $fnameEffective );
406  }
407  }
408 
409  public function getChronologyProtectorTouched( $dbName ) {
410  return $this->getChronologyProtector()->getTouched( $dbName );
411  }
412 
413  public function disableChronologyProtection() {
414  $this->getChronologyProtector()->setEnabled( false );
415  }
416 
420  protected function getChronologyProtector() {
421  if ( $this->chronProt ) {
422  return $this->chronProt;
423  }
424 
425  $this->chronProt = new ChronologyProtector(
426  $this->memCache,
427  [
428  'ip' => $this->requestInfo['IPAddress'],
429  'agent' => $this->requestInfo['UserAgent'],
430  ],
431  isset( $_GET['cpPosTime'] ) ? $_GET['cpPosTime'] : null
432  );
433  $this->chronProt->setLogger( $this->replLogger );
434 
435  if ( $this->cliMode ) {
436  $this->chronProt->setEnabled( false );
437  } elseif ( $this->requestInfo['ChronologyProtection'] === 'false' ) {
438  // Request opted out of using position wait logic. This is useful for requests
439  // done by the job queue or background ETL that do not have a meaningful session.
440  $this->chronProt->setWaitEnabled( false );
441  }
442 
443  $this->replLogger->debug( __METHOD__ . ': using request info ' .
444  json_encode( $this->requestInfo, JSON_PRETTY_PRINT ) );
445 
446  return $this->chronProt;
447  }
448 
456  protected function shutdownChronologyProtector(
457  ChronologyProtector $cp, $workCallback, $mode
458  ) {
459  // Record all the master positions needed
460  $this->forEachLB( function ( ILoadBalancer $lb ) use ( $cp ) {
461  $cp->shutdownLB( $lb );
462  } );
463  // Write them to the persistent stash. Try to do something useful by running $work
464  // while ChronologyProtector waits for the stash write to replicate to all DCs.
465  $unsavedPositions = $cp->shutdown( $workCallback, $mode );
466  if ( $unsavedPositions && $workCallback ) {
467  // Invoke callback in case it did not cache the result yet
468  $workCallback(); // work now to block for less time in waitForAll()
469  }
470  // If the positions failed to write to the stash, at least wait on local datacenter
471  // replica DBs to catch up before responding. Even if there are several DCs, this increases
472  // the chance that the user will see their own changes immediately afterwards. As long
473  // as the sticky DC cookie applies (same domain), this is not even an issue.
474  $this->forEachLB( function ( ILoadBalancer $lb ) use ( $unsavedPositions ) {
475  $masterName = $lb->getServerName( $lb->getWriterIndex() );
476  if ( isset( $unsavedPositions[$masterName] ) ) {
477  $lb->waitForAll( $unsavedPositions[$masterName] );
478  }
479  } );
480  }
481 
486  final protected function baseLoadBalancerParams() {
487  return [
488  'localDomain' => $this->localDomain,
489  'readOnlyReason' => $this->readOnlyReason,
490  'srvCache' => $this->srvCache,
491  'wanCache' => $this->wanCache,
492  'profiler' => $this->profiler,
493  'trxProfiler' => $this->trxProfiler,
494  'queryLogger' => $this->queryLogger,
495  'connLogger' => $this->connLogger,
496  'replLogger' => $this->replLogger,
497  'errorLogger' => $this->errorLogger,
498  'hostname' => $this->hostname,
499  'cliMode' => $this->cliMode,
500  'agent' => $this->agent
501  ];
502  }
503 
507  protected function initLoadBalancer( ILoadBalancer $lb ) {
508  if ( $this->trxRoundId !== false ) {
509  $lb->beginMasterChanges( $this->trxRoundId ); // set DBO_TRX
510  }
511  }
512 
513  public function setDomainPrefix( $prefix ) {
514  $this->localDomain = new DatabaseDomain(
515  $this->localDomain->getDatabase(),
516  null,
517  $prefix
518  );
519 
520  $this->forEachLB( function( ILoadBalancer $lb ) use ( $prefix ) {
521  $lb->setDomainPrefix( $prefix );
522  } );
523  }
524 
525  public function closeAll() {
526  $this->forEachLBCallMethod( 'closeAll', [] );
527  }
528 
529  public function setAgentName( $agent ) {
530  $this->agent = $agent;
531  }
532 
533  public function appendPreShutdownTimeAsQuery( $url, $time ) {
534  $usedCluster = 0;
535  $this->forEachLB( function ( ILoadBalancer $lb ) use ( &$usedCluster ) {
536  $usedCluster |= ( $lb->getServerCount() > 1 );
537  } );
538 
539  if ( !$usedCluster ) {
540  return $url; // no master/replica clusters touched
541  }
542 
543  return strpos( $url, '?' ) === false ? "$url?cpPosTime=$time" : "$url&cpPosTime=$time";
544  }
545 
546  public function setRequestInfo( array $info ) {
547  $this->requestInfo = $info + $this->requestInfo;
548  }
549 
556  final protected function getScopedPHPBehaviorForCommit() {
557  if ( PHP_SAPI != 'cli' ) { // http://bugs.php.net/bug.php?id=47540
558  $old = ignore_user_abort( true ); // avoid half-finished operations
559  return new ScopedCallback( function () use ( $old ) {
560  ignore_user_abort( $old );
561  } );
562  }
563 
564  return null;
565  }
566 
567  function __destruct() {
568  $this->destroy();
569  }
570 }
beginMasterChanges($fname=__METHOD__)
Flush any master transaction snapshots and set DBO_TRX (if DBO_DEFAULT is set)
Definition: LBFactory.php:191
runMasterPostTrxCallbacks($type)
Issue all pending post-COMMIT/ROLLBACK callbacks.
mixed $ticket
Definition: LBFactory.php:63
the array() calling protocol came about after MediaWiki 1.4rc1.
static newUnspecified()
LoggerInterface $perfLogger
Definition: LBFactory.php:45
LoggerInterface $queryLogger
Definition: LBFactory.php:43
baseLoadBalancerParams()
Base parameters to LoadBalancer::__construct()
Definition: LBFactory.php:486
beginMasterChanges($fname=__METHOD__)
Flush any master transaction snapshots and set DBO_TRX (if DBO_DEFAULT is set)
bool $cliMode
Whether this PHP instance is for a CLI script.
Definition: LBFactory.php:72
setAgentName($agent)
Definition: LBFactory.php:529
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses & $ret
Definition: hooks.txt:1936
Apache License January AND DISTRIBUTION Definitions License shall mean the terms and conditions for use
newMainLB($domain=false)
div flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException'returning false will NOT prevent logging $e
Definition: hooks.txt:2102
__construct(array $conf)
Construct a manager of ILoadBalancer objects.
Definition: LBFactory.php:79
An interface for generating database load balancers.
Definition: ILBFactory.php:29
callable[] $replicationWaitCallbacks
Definition: LBFactory.php:69
commitAll($fname=__METHOD__, array $options=[])
Commit open transactions on all connections.
Definition: LBFactory.php:186
BagOStuff $srvCache
Definition: LBFactory.php:49
shutdownLB(ILoadBalancer $lb)
Notify the ChronologyProtector that the ILoadBalancer is about to shut down.
forEachLB($callback, array $params=[])
Execute a function for each tracked load balancer The callback is called with the load balancer as th...
getChronologyProtectorTouched($dbName)
Definition: LBFactory.php:409
getMainLB($domain=false)
object string $profiler
Class name or object With profileIn/profileOut methods.
Definition: LBFactory.php:35
laggedReplicaUsed()
Detemine if any lagged replica DB connection was used.
Definition: LBFactory.php:278
shutdownChronologyProtector(ChronologyProtector $cp, $workCallback, $mode)
Get and record all of the staged DB positions into persistent memory storage.
Definition: LBFactory.php:456
commitMasterChanges($fname=__METHOD__, array $options=[])
Commit changes on all master connections.
Definition: LBFactory.php:203
if($line===false) $args
Definition: cdb.php:64
Class to handle database/prefix specification for IDatabase domains.
shutdown(callable $workCallback=null, $mode= 'sync')
Notify the ChronologyProtector that the LBFactory is done calling shutdownLB() for now...
getExternalLB($cluster)
shutdown($mode=self::SHUTDOWN_CHRONPROT_SYNC, callable $workCallback=null)
Prepare all tracked load balancers for shutdown.
Definition: LBFactory.php:126
static newEmpty()
Get an instance that wraps EmptyBagOStuff.
initLoadBalancer(ILoadBalancer $lb)
Definition: LBFactory.php:507
array $requestInfo
Web request information about the client.
Definition: LBFactory.php:60
waitForAll($pos, $timeout=null)
Set the master wait position and wait for ALL replica DBs to catch up to it.
rollbackMasterChanges($fname=__METHOD__)
Rollback changes on all master connections.
Definition: LBFactory.php:236
DatabaseDomain $localDomain
Local domain.
Definition: LBFactory.php:56
newExternalLB($cluster)
Exception class for replica DB wait timeouts.
callable $errorLogger
Error logger.
Definition: LBFactory.php:47
hasMasterChanges()
Determine if there are pending changes in a transaction by this thread.
appendPreShutdownTimeAsQuery($url, $time)
Append ?cpPosTime parameter to a URL for ChronologyProtector purposes if needed.
Definition: LBFactory.php:533
waitForReplication(array $opts=[])
Waits for the replica DBs to catch up to the current master position.
Definition: LBFactory.php:295
string $agent
Agent name for query profiling.
Definition: LBFactory.php:74
Database cluster connection, tracking, load balancing, and transaction manager interface.
Helper class that detects high-contention DB queries via profiling calls.
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist e g Watchlist removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set and then return false from the hook function Ensure you consume the ChangeTagAfterDelete hook to carry out custom deletion actions as context called by AbstractContent::getParserOutput May be used to override the normal model specific rendering of page content as context as context $options
Definition: hooks.txt:1046
hasMasterChanges()
Determine if any master connection has pending changes.
Definition: LBFactory.php:269
string bool $trxRoundId
String if a requested DBO_TRX transaction round is active.
Definition: LBFactory.php:65
$params
string bool $readOnlyReason
Reason all LBs are read-only or false if not.
Definition: LBFactory.php:67
pendingMasterChangeCallers()
Get the list of callers that have pending master changes.
closeAll()
Close all open database connections on all open load balancers.
Definition: LBFactory.php:525
A BagOStuff object with no objects in it.
WANObjectCache $wanCache
Definition: LBFactory.php:53
BagOStuff $memCache
Definition: LBFactory.php:51
disableChronologyProtection()
Disable the ChronologyProtector for all load balancers.
Definition: LBFactory.php:413
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
setDomainPrefix($prefix)
Set a new table prefix for the existing local domain ID for testing.
Definition: LBFactory.php:513
getServerCount()
Get the number of defined servers (not the number of open connections)
LoggerInterface $replLogger
Definition: LBFactory.php:39
forEachLBCallMethod($methodName, array $args=[])
Call a method of each tracked load balancer.
Definition: LBFactory.php:173
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:35
commitAndWaitForReplication($fname, $ticket, array $opts=[])
Convenience method for safely running commitMasterChanges()/waitForReplication()
Definition: LBFactory.php:383
Class for ensuring a consistent ordering of events as seen by the user, despite replication.
if(!defined( 'MEDIAWIKI')) $fname
This file is not a valid entry point, perform no further processing unless MEDIAWIKI is defined...
Definition: Setup.php:36
hasOrMadeRecentMasterChanges($age=null)
Check if this load balancer object had any recent or still pending writes issued against it by this P...
hasOrMadeRecentMasterChanges($age=null)
Determine if any master connection has pending/written changes from this request. ...
Definition: LBFactory.php:287
static newFromId($domain)
setWaitForReplicationListener($name, callable $callback=null)
Add a callback to be run in every call to waitForReplication() before waiting.
Definition: LBFactory.php:364
destroy()
Disables all load balancers.
Definition: LBFactory.php:121
setDomainPrefix($prefix)
Set a new table prefix for the existing local domain ID for testing.
getScopedPHPBehaviorForCommit()
Make PHP ignore user aborts/disconnects until the returned value leaves scope.
Definition: LBFactory.php:556
string $hostname
Local hostname of the app server.
Definition: LBFactory.php:58
static $loggerFields
Definition: LBFactory.php:76
LoggerInterface $connLogger
Definition: LBFactory.php:41
TransactionProfiler $trxProfiler
Definition: LBFactory.php:37
getServerName($i)
Get the host name or IP address of the server with the specified index Prefer a readable name if avai...
getChronologyProtector()
Definition: LBFactory.php:420
setRequestInfo(array $info)
Definition: LBFactory.php:546
flushReplicaSnapshots($fname=__METHOD__)
Commit all replica DB transactions so as to flush any REPEATABLE-READ or SSI snapshot.
Definition: LBFactory.php:182
logIfMultiDbTransaction()
Log query info if multi DB transactions are going to be committed now.
Definition: LBFactory.php:249
see documentation in includes Linker php for Linker::makeImageLink & $time
Definition: hooks.txt:1749
getEmptyTransactionTicket($fname)
Get a token asserting that no transaction writes are active.
Definition: LBFactory.php:372
ChronologyProtector $chronProt
Definition: LBFactory.php:33
Allows to change the fields on the form that will be generated $name
Definition: hooks.txt:300