wiki.techinc.nl/includes/deferred/DeferredUpdates.php

133 lines
3.6 KiB
PHP
Raw Normal View History

<?php
/**
* Interface and manager for deferred updates.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* http://www.gnu.org/copyleft/gpl.html
*
* @file
*/
/**
* Interface that deferrable updates should implement. Basically required so we
* can validate input on DeferredUpdates::addUpdate()
*
* @since 1.19
*/
interface DeferrableUpdate {
/**
* Perform the actual work
*/
function doUpdate();
}
/**
* Class for managing the deferred updates.
*
* @since 1.19
*/
class DeferredUpdates {
/**
* Store of updates to be deferred until the end of the request.
*/
private static $updates = array();
/**
* Add an update to the deferred list
* @param DeferrableUpdate $update Some object that implements doUpdate()
*/
public static function addUpdate( DeferrableUpdate $update ) {
array_push( self::$updates, $update );
}
/**
* HTMLCacheUpdates are the most common deferred update people use. This
* is a shortcut method for that.
* @see HTMLCacheUpdate::__construct()
* @param Title $title
* @param string $table
*/
public static function addHTMLCacheUpdate( $title, $table ) {
self::addUpdate( new HTMLCacheUpdate( $title, $table ) );
}
/**
* 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 = '' ) {
global $wgDeferredUpdateList;
wfProfileIn( __METHOD__ );
$updates = array_merge( $wgDeferredUpdateList, self::$updates );
// No need to get master connections in case of empty updates array
if ( !count( $updates ) ) {
wfProfileOut( __METHOD__ );
return;
}
$dbw = false;
$doCommit = $commit == 'commit';
if ( $doCommit ) {
$dbw = wfGetDB( DB_MASTER );
}
/** @var DeferrableUpdate $update */
foreach ( $updates as $update ) {
try {
$update->doUpdate();
if ( $doCommit && $dbw->trxLevel() ) {
$dbw->commit( __METHOD__, 'flush' );
}
} catch ( MWException $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 ) {
exception: Use MWExceptionHandler::logException in more places Most code replaced wasn't exactly like what logException does but most probably should be. A few implementation differences with the code it replaced in various places: * MWException if-guards Was there only to prevent a crash because getLogMessage is an MWException method. Now that logException is generic, it seems sensible to start logging those as well (follows-up a97f3550a0). * Exception::getTraceAsString Now using MWExceptionHandler::formatRedactedTrace instead. It wasn't using it because that method didn't exist yet. Notes: * DatabaseError::getLogMessage Removed as this override was no longer doing anything (we're using MWExceptionHandler::getLogMessage instead of $e->getLogMessage). Introduced isLoggable() to take over the responsibility of indicating when an exception should not be logged (follows-up bcb9f9e1c0d). * DeferredUpdates and Wiki.php Both specificy MWException. Though ApiMain intends to catch all and only logged MWException because it couldn't otherwise, these actually only catch MWException (as opposed to catching all and having an if-statement inside). Left those as-is to have them continue propagate other exceptions. * JobQueueFederated and JobQueueGroup All specify to catch JobQueueError only. Not sure whether it should catch other exceptions. It now can, but I'll leave it as is in case it intends to have those be handled elsewhere (or fatal). Change-Id: I4578a0fe7d95a080f1a3b292ce7ae73a4d5fcaca
2013-10-11 19:22:40 +00:00
MWExceptionHandler::logException( $e );
}
}
}
self::clearPendingUpdates();
wfProfileOut( __METHOD__ );
}
/**
* 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() {
global $wgDeferredUpdateList;
$wgDeferredUpdateList = self::$updates = array();
}
}