SpecialRunJobs: Use MediaWiki's built-in async/post-send mode
Disabling OutputPage is fine, but disabling MediaWiki's own output handling from MediaWiki.php as well (with ignore_user_abort and ob_flush) made this code incompatible with becoming an API module. Make use of DeferredUpdates instead, MediaWiki's built-in post-send mechanism. Bug: T175146 Change-Id: Ia131341d447fd6501a070da89cd3a2af470e0f7d
This commit is contained in:
parent
e994e89e76
commit
bfa2cf4246
1 changed files with 31 additions and 32 deletions
|
|
@ -39,17 +39,21 @@ class SpecialRunJobs extends UnlistedSpecialPage {
|
|||
|
||||
public function execute( $par = '' ) {
|
||||
$this->getOutput()->disable();
|
||||
|
||||
if ( wfReadOnly() ) {
|
||||
wfHttpError( 423, 'Locked', 'Wiki is in read-only mode.' );
|
||||
return;
|
||||
} elseif ( !$this->getRequest()->wasPosted() ) {
|
||||
}
|
||||
|
||||
// Validate request method
|
||||
if ( !$this->getRequest()->wasPosted() ) {
|
||||
wfHttpError( 400, 'Bad Request', 'Request must be POSTed.' );
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate request parameters
|
||||
$optional = [ 'maxjobs' => 0, 'maxtime' => 30, 'type' => false, 'async' => true ];
|
||||
$required = array_flip( [ 'title', 'tasks', 'signature', 'sigexpiry' ] );
|
||||
|
||||
$params = array_intersect_key( $this->getRequest()->getValues(), $required + $optional );
|
||||
$missing = array_diff_key( $required, $params );
|
||||
if ( count( $missing ) ) {
|
||||
|
|
@ -59,11 +63,11 @@ class SpecialRunJobs extends UnlistedSpecialPage {
|
|||
return;
|
||||
}
|
||||
|
||||
// Validate request signature
|
||||
$squery = $params;
|
||||
unset( $squery['signature'] );
|
||||
$correctSignature = self::getQuerySignature( $squery, $this->getConfig()->get( 'SecretKey' ) );
|
||||
$providedSignature = $params['signature'];
|
||||
|
||||
$verified = is_string( $providedSignature )
|
||||
&& hash_equals( $correctSignature, $providedSignature );
|
||||
if ( !$verified || $params['sigexpiry'] < time() ) {
|
||||
|
|
@ -75,39 +79,34 @@ class SpecialRunJobs extends UnlistedSpecialPage {
|
|||
$params += $optional;
|
||||
|
||||
if ( $params['async'] ) {
|
||||
// Client will usually disconnect before checking the response,
|
||||
// but it needs to know when it is safe to disconnect. Until this
|
||||
// reaches ignore_user_abort(), it is not safe as the jobs won't run.
|
||||
ignore_user_abort( true ); // jobs may take a bit of time
|
||||
// HTTP 202 Accepted
|
||||
HttpStatus::header( 202 );
|
||||
ob_flush();
|
||||
flush();
|
||||
// Once the client receives this response, it can disconnect
|
||||
set_error_handler( function ( $errno, $errstr ) {
|
||||
if ( strpos( $errstr, 'Cannot modify header information' ) !== false ) {
|
||||
return true; // bug T115413
|
||||
}
|
||||
// Delegate unhandled errors to the default MediaWiki handler
|
||||
// so that fatal errors get proper logging (T89169)
|
||||
return call_user_func_array(
|
||||
'MWExceptionHandler::handleError', func_get_args()
|
||||
);
|
||||
} );
|
||||
// Clients are meant to disconnect without waiting for the full response.
|
||||
// Let the page output happen before the jobs start, so that clients know it's
|
||||
// safe to disconnect. MediaWiki::preOutputCommit() calls ignore_user_abort()
|
||||
// or similar to make sure we stay alive to run the deferred update.
|
||||
DeferredUpdates::addUpdate(
|
||||
new TransactionRoundDefiningUpdate(
|
||||
function () use ( $params ) {
|
||||
$this->doRun( $params );
|
||||
},
|
||||
__METHOD__
|
||||
),
|
||||
DeferredUpdates::POSTSEND
|
||||
);
|
||||
} else {
|
||||
$this->doRun( $params );
|
||||
print "Done\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Do all of the specified tasks...
|
||||
if ( in_array( 'jobs', explode( '|', $params['tasks'] ) ) ) {
|
||||
$runner = new JobRunner( LoggerFactory::getInstance( 'runJobs' ) );
|
||||
$runner->run( [
|
||||
'type' => $params['type'],
|
||||
'maxJobs' => $params['maxjobs'] ? $params['maxjobs'] : 1,
|
||||
'maxTime' => $params['maxtime'] ? $params['maxjobs'] : 30
|
||||
] );
|
||||
if ( !$params['async'] ) {
|
||||
print "Done\n";
|
||||
}
|
||||
}
|
||||
protected function doRun( array $params ) {
|
||||
$runner = new JobRunner( LoggerFactory::getInstance( 'runJobs' ) );
|
||||
$runner->run( [
|
||||
'type' => $params['type'],
|
||||
'maxJobs' => $params['maxjobs'] ?: 1,
|
||||
'maxTime' => $params['maxtime'] ?: 30
|
||||
] );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue