getAnyOpenConnection( $lb->getWriterIndex() ); // Do the update as soon as there is no transaction if ( $dbw && $dbw->trxLevel() ) { $waitingOnTrx = true; $dbw->onTransactionIdle( function() use ( &$waitingOnTrx ) { DeferredUpdates::doUpdates(); $waitingOnTrx = false; } ); } else { self::doUpdates(); } } } /** * Add a callable update. In a lot of cases, we just need a callback/closure, * defining a new DeferrableUpdate object is not necessary * @see MWCallableUpdate::__construct() * @param callable $callable */ public static function addCallableUpdate( $callable ) { self::addUpdate( new MWCallableUpdate( $callable ) ); } /** * Do any deferred updates and clear the list * * @param string $commit Set to 'commit' to commit after every update to * prevent lock contention */ public static function doUpdates( $commit = '' ) { $updates = self::$updates; while ( count( $updates ) ) { self::clearPendingUpdates(); /** @var DeferrableUpdate $update */ foreach ( $updates as $update ) { try { $update->doUpdate(); if ( $commit === 'commit' ) { wfGetLBFactory()->commitMasterChanges(); } } catch ( Exception $e ) { // We don't want exceptions thrown during deferred updates to // be reported to the user since the output is already sent. // Instead we just log them. if ( !$e instanceof ErrorPageError ) { MWExceptionHandler::logException( $e ); } } } $updates = self::$updates; } } /** * Clear all pending updates without performing them. Generally, you don't * want or need to call this. Unit tests need it though. */ public static function clearPendingUpdates() { self::$updates = array(); } }