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 $mode Use "enqueue" to use the job queue when possible [Default: run] * prevent lock contention * @param string $oldMode Unused */ public static function doUpdates( $mode = 'run', $oldMode = '' ) { // B/C for ( $commit, $mode ) args $mode = $oldMode ?: $mode; if ( $mode === 'commit' ) { $mode = 'run'; } $updates = self::$updates; while ( count( $updates ) ) { self::clearPendingUpdates(); /** @var DataUpdate[] $dataUpdates */ $dataUpdates = array(); /** @var DeferrableUpdate[] $otherUpdates */ $otherUpdates = array(); foreach ( $updates as $update ) { if ( $update instanceof DataUpdate ) { $dataUpdates[] = $update; } else { $otherUpdates[] = $update; } } // Delegate DataUpdate execution to the DataUpdate class DataUpdate::runUpdates( $dataUpdates, $mode ); // Execute the non-DataUpdate tasks foreach ( $otherUpdates as $update ) { try { $update->doUpdate(); 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(); } /** * @note This method is intended for testing purposes * @param bool $value Whether to *always* defer updates, even in CLI mode * @since 1.27 */ public static function forceDeferral( $value ) { self::$forceDeferral = $value; } }