merge( $update ); } else { $queue[$class] = $update; } } else { $queue[] = $update; } // CLI scripts may forget to periodically flush these updates, // so try to handle that rather than OOMing and losing them entirely. // Try to run the updates as soon as there is no current wiki transaction. static $waitingOnTrx = false; // de-duplicate callback if ( $wgCommandLineMode && !$waitingOnTrx ) { $lb = wfGetLB(); $dbw = $lb->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(); } } } public static function execute( array &$queue, $mode ) { $updates = $queue; // snapshot of queue // Keep doing rounds of updates until none get enqueued while ( count( $updates ) ) { $queue = []; // clear the queue /** @var DataUpdate[] $dataUpdates */ $dataUpdates = []; /** @var DeferrableUpdate[] $otherUpdates */ $otherUpdates = []; 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( __METHOD__ ); } catch ( Exception $e ) { // We don't want exceptions thrown during deferred updates to // be reported to the user since the output is already sent if ( !$e instanceof ErrorPageError ) { MWExceptionHandler::logException( $e ); } // Make sure incomplete transactions are not committed and end any // open atomic sections so that other DB updates have a chance to run wfGetLBFactory()->rollbackMasterChanges( __METHOD__ ); } } $updates = $queue; // new snapshot of queue (check for new entries) } } /** * 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::$preSendUpdates = []; self::$postSendUpdates = []; } }