Allow setting max execution time to several special pages
These special pages and their counter-part APIs are: - Special:RecentChanges - Special:Watchlist - Special:Log - Special:Contributions This also changes the way MAX_EXECUTION_TIME works from taking the value as milliseconds, it takes seconds which is more intuitive for users. Bug: T297708 Depends-On: I126e7181422d8da1a63afc3717faa4f72a687dd9 Change-Id: I3ff78751c3df3b6342f1865d35c2075f4415185d
This commit is contained in:
parent
72b63c75dc
commit
627c1c2c30
12 changed files with 52 additions and 4 deletions
|
|
@ -2370,6 +2370,13 @@ $wgDatabaseReplicaLagWarning = 10;
|
|||
*/
|
||||
$wgDatabaseReplicaLagCritical = 30;
|
||||
|
||||
/**
|
||||
* Max execution time for queries of several expensive special pages such as RecentChanges
|
||||
* in milliseconds.
|
||||
* @since 1.38
|
||||
*/
|
||||
$wgMaxExecutionTimeForExpensiveQueries = 0;
|
||||
|
||||
/**
|
||||
* RevisionStore table schema migration stage (content, slots, content_models & slot_roles tables).
|
||||
* Use the SCHEMA_COMPAT_XXX flags. Supported values:
|
||||
|
|
|
|||
|
|
@ -1877,7 +1877,8 @@ return [
|
|||
$services->getCommentStore(),
|
||||
$services->getWatchedItemStore(),
|
||||
$services->getHookContainer(),
|
||||
$services->getMainConfig()->get( 'WatchlistExpiry' )
|
||||
$services->getMainConfig()->get( 'WatchlistExpiry' ),
|
||||
$services->getMainConfig()->get( 'MaxExecutionTimeForExpensiveQueries' )
|
||||
);
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -259,6 +259,11 @@ class ApiQueryLogEvents extends ApiQueryBase {
|
|||
$this->addOption( 'STRAIGHT_JOIN' );
|
||||
}
|
||||
|
||||
$this->addOption(
|
||||
'MAX_EXECUTION_TIME',
|
||||
$this->getConfig()->get( 'MaxExecutionTimeForExpensiveQueries' )
|
||||
);
|
||||
|
||||
$count = 0;
|
||||
$res = $this->select( __METHOD__ );
|
||||
|
||||
|
|
|
|||
|
|
@ -416,6 +416,10 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
|
|||
}
|
||||
|
||||
$this->addOption( 'LIMIT', $params['limit'] + 1 );
|
||||
$this->addOption(
|
||||
'MAX_EXECUTION_TIME',
|
||||
$this->getConfig()->get( 'MaxExecutionTimeForExpensiveQueries' )
|
||||
);
|
||||
|
||||
$hookData = [];
|
||||
$count = 0;
|
||||
|
|
|
|||
|
|
@ -486,6 +486,10 @@ class ApiQueryUserContribs extends ApiQueryBase {
|
|||
$this->addWhere( '1=0' );
|
||||
}
|
||||
}
|
||||
$this->addOption(
|
||||
'MAX_EXECUTION_TIME',
|
||||
$this->getConfig()->get( 'MaxExecutionTimeForExpensiveQueries' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -388,6 +388,17 @@ class SelectQueryBuilder extends JoinGroupBase {
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set MAX_EXECUTION_TIME for queries.
|
||||
*
|
||||
* @param int $time maximum allowed time in milliseconds
|
||||
* @return $this
|
||||
*/
|
||||
public function setMaxExecutionTime( int $time ) {
|
||||
$this->options['MAX_EXECUTION_TIME'] = $time;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a GROUP BY clause. May be either an SQL fragment string naming a
|
||||
* field or expression to group by, or an array of such SQL fragments.
|
||||
|
|
|
|||
|
|
@ -380,6 +380,8 @@ class LogPager extends ReverseChronologicalPager {
|
|||
$options[] = 'STRAIGHT_JOIN';
|
||||
}
|
||||
|
||||
$options['MAX_EXECUTION_TIME'] = $this->getConfig()->get( 'MaxExecutionTimeForExpensiveQueries' );
|
||||
|
||||
$info = [
|
||||
'tables' => $tables,
|
||||
'fields' => $fields,
|
||||
|
|
|
|||
|
|
@ -398,6 +398,7 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
|
|||
// MediaWiki 1.26 this used to use the plus operator instead, which meant
|
||||
// that extensions weren't able to change these conditions
|
||||
$query_options = array_merge( $orderByAndLimit, $query_options );
|
||||
$query_options['MAX_EXECUTION_TIME'] = $this->getConfig()->get( 'MaxExecutionTimeForExpensiveQueries' );
|
||||
$rows = $dbr->select(
|
||||
$tables,
|
||||
$fields,
|
||||
|
|
|
|||
|
|
@ -249,7 +249,6 @@ class SpecialRecentChangesLinked extends SpecialRecentChanges {
|
|||
' ORDER BY rc_timestamp DESC';
|
||||
$sql = $dbr->limitResult( $sql, $limit, false );
|
||||
}
|
||||
|
||||
return $dbr->query( $sql, __METHOD__ );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -459,6 +459,7 @@ class SpecialWatchlist extends ChangesListSpecialPage {
|
|||
// array_merge() is used intentionally here so that hooks can, should
|
||||
// they so desire, override the ORDER BY / LIMIT condition(s)
|
||||
$query_options = array_merge( $orderByAndLimit, $query_options );
|
||||
$query_options['MAX_EXECUTION_TIME'] = $this->getConfig()->get( 'MaxExecutionTimeForExpensiveQueries' );
|
||||
|
||||
return $dbr->select(
|
||||
$tables,
|
||||
|
|
|
|||
|
|
@ -276,6 +276,7 @@ class ContribsPager extends RangeChronologicalPager {
|
|||
$order
|
||||
);
|
||||
|
||||
$options['MAX_EXECUTION_TIME'] = $this->getConfig()->get( 'MaxExecutionTimeForExpensiveQueries' );
|
||||
/*
|
||||
* This hook will allow extensions to add in additional queries, so they can get their data
|
||||
* in My Contributions as well. Extensions should append their results to the $data array.
|
||||
|
|
|
|||
|
|
@ -78,18 +78,25 @@ class WatchedItemQueryService {
|
|||
*/
|
||||
private $expiryEnabled;
|
||||
|
||||
/**
|
||||
* @var int Max query execution time
|
||||
*/
|
||||
private $maxQueryExecutionTime;
|
||||
|
||||
public function __construct(
|
||||
ILoadBalancer $loadBalancer,
|
||||
CommentStore $commentStore,
|
||||
WatchedItemStoreInterface $watchedItemStore,
|
||||
HookContainer $hookContainer,
|
||||
bool $expiryEnabled = false
|
||||
bool $expiryEnabled = false,
|
||||
int $maxQueryExecutionTime = 0
|
||||
) {
|
||||
$this->loadBalancer = $loadBalancer;
|
||||
$this->commentStore = $commentStore;
|
||||
$this->watchedItemStore = $watchedItemStore;
|
||||
$this->hookRunner = new HookRunner( $hookContainer );
|
||||
$this->expiryEnabled = $expiryEnabled;
|
||||
$this->maxQueryExecutionTime = $maxQueryExecutionTime;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -712,7 +719,9 @@ class WatchedItemQueryService {
|
|||
if ( array_key_exists( 'limit', $options ) ) {
|
||||
$dbOptions['LIMIT'] = (int)$options['limit'] + 1;
|
||||
}
|
||||
|
||||
if ( $this->maxQueryExecutionTime ) {
|
||||
$dbOptions['MAX_EXECUTION_TIME'] = $this->maxQueryExecutionTime;
|
||||
}
|
||||
return $dbOptions;
|
||||
}
|
||||
|
||||
|
|
@ -730,6 +739,9 @@ class WatchedItemQueryService {
|
|||
if ( array_key_exists( 'limit', $options ) ) {
|
||||
$dbOptions['LIMIT'] = (int)$options['limit'];
|
||||
}
|
||||
if ( $this->maxQueryExecutionTime ) {
|
||||
$dbOptions['MAX_EXECUTION_TIME'] = $this->maxQueryExecutionTime;
|
||||
}
|
||||
return $dbOptions;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue