diff options
author | Amir Sarabadani <ladsgroup@gmail.com> | 2021-12-14 10:08:51 +0100 |
---|---|---|
committer | Ladsgroup <Ladsgroup@gmail.com> | 2021-12-16 14:18:22 +0000 |
commit | 9dd073b0e390669712ae9b486d0bad2dba6a3414 (patch) | |
tree | 1d9962e6bc8b16fd8f41eb998b1743a077020d35 | |
parent | 50a8a49735cbfac2ac41b8741a4867cca8d50fd4 (diff) |
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
(cherry picked from commit 627c1c2c308fe5d07692b3430fd847f5b470663d)
-rw-r--r-- | includes/DefaultSettings.php | 7 | ||||
-rw-r--r-- | includes/ServiceWiring.php | 3 | ||||
-rw-r--r-- | includes/api/ApiQueryLogEvents.php | 5 | ||||
-rw-r--r-- | includes/api/ApiQueryRecentChanges.php | 4 | ||||
-rw-r--r-- | includes/api/ApiQueryUserContribs.php | 4 | ||||
-rw-r--r-- | includes/libs/rdbms/querybuilder/SelectQueryBuilder.php | 11 | ||||
-rw-r--r-- | includes/logging/LogPager.php | 2 | ||||
-rw-r--r-- | includes/specials/SpecialRecentChanges.php | 1 | ||||
-rw-r--r-- | includes/specials/SpecialRecentChangesLinked.php | 1 | ||||
-rw-r--r-- | includes/specials/SpecialWatchlist.php | 1 | ||||
-rw-r--r-- | includes/specials/pagers/ContribsPager.php | 1 | ||||
-rw-r--r-- | includes/watcheditem/WatchedItemQueryService.php | 16 |
12 files changed, 52 insertions, 4 deletions
diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 24f9c7f9d188..d7fa6829a30c 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -2371,6 +2371,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: * diff --git a/includes/ServiceWiring.php b/includes/ServiceWiring.php index 4f86fda33de1..765f6533b257 100644 --- a/includes/ServiceWiring.php +++ b/includes/ServiceWiring.php @@ -1877,7 +1877,8 @@ return [ $services->getCommentStore(), $services->getWatchedItemStore(), $services->getHookContainer(), - $services->getMainConfig()->get( 'WatchlistExpiry' ) + $services->getMainConfig()->get( 'WatchlistExpiry' ), + $services->getMainConfig()->get( 'MaxExecutionTimeForExpensiveQueries' ) ); }, diff --git a/includes/api/ApiQueryLogEvents.php b/includes/api/ApiQueryLogEvents.php index eaeecc081390..a2f6d15ed367 100644 --- a/includes/api/ApiQueryLogEvents.php +++ b/includes/api/ApiQueryLogEvents.php @@ -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__ ); diff --git a/includes/api/ApiQueryRecentChanges.php b/includes/api/ApiQueryRecentChanges.php index 3e34ef70a6eb..52199ae8db4b 100644 --- a/includes/api/ApiQueryRecentChanges.php +++ b/includes/api/ApiQueryRecentChanges.php @@ -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; diff --git a/includes/api/ApiQueryUserContribs.php b/includes/api/ApiQueryUserContribs.php index 1080b8e5758d..673092316b57 100644 --- a/includes/api/ApiQueryUserContribs.php +++ b/includes/api/ApiQueryUserContribs.php @@ -486,6 +486,10 @@ class ApiQueryUserContribs extends ApiQueryBase { $this->addWhere( '1=0' ); } } + $this->addOption( + 'MAX_EXECUTION_TIME', + $this->getConfig()->get( 'MaxExecutionTimeForExpensiveQueries' ) + ); } /** diff --git a/includes/libs/rdbms/querybuilder/SelectQueryBuilder.php b/includes/libs/rdbms/querybuilder/SelectQueryBuilder.php index d1b5095c6543..10cbd7706136 100644 --- a/includes/libs/rdbms/querybuilder/SelectQueryBuilder.php +++ b/includes/libs/rdbms/querybuilder/SelectQueryBuilder.php @@ -389,6 +389,17 @@ class SelectQueryBuilder extends JoinGroupBase { } /** + * 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. * diff --git a/includes/logging/LogPager.php b/includes/logging/LogPager.php index ed6f524ba120..e9a9a5c56f1b 100644 --- a/includes/logging/LogPager.php +++ b/includes/logging/LogPager.php @@ -380,6 +380,8 @@ class LogPager extends ReverseChronologicalPager { $options[] = 'STRAIGHT_JOIN'; } + $options['MAX_EXECUTION_TIME'] = $this->getConfig()->get( 'MaxExecutionTimeForExpensiveQueries' ); + $info = [ 'tables' => $tables, 'fields' => $fields, diff --git a/includes/specials/SpecialRecentChanges.php b/includes/specials/SpecialRecentChanges.php index ea81503c8d43..4cc25ee9191d 100644 --- a/includes/specials/SpecialRecentChanges.php +++ b/includes/specials/SpecialRecentChanges.php @@ -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, diff --git a/includes/specials/SpecialRecentChangesLinked.php b/includes/specials/SpecialRecentChangesLinked.php index 5911fa05b216..94ce9e0a4eba 100644 --- a/includes/specials/SpecialRecentChangesLinked.php +++ b/includes/specials/SpecialRecentChangesLinked.php @@ -249,7 +249,6 @@ class SpecialRecentChangesLinked extends SpecialRecentChanges { ' ORDER BY rc_timestamp DESC'; $sql = $dbr->limitResult( $sql, $limit, false ); } - return $dbr->query( $sql, __METHOD__ ); } diff --git a/includes/specials/SpecialWatchlist.php b/includes/specials/SpecialWatchlist.php index 7485a6e127d8..2e48b94a6f52 100644 --- a/includes/specials/SpecialWatchlist.php +++ b/includes/specials/SpecialWatchlist.php @@ -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, diff --git a/includes/specials/pagers/ContribsPager.php b/includes/specials/pagers/ContribsPager.php index 0a07dd47b68b..70c04168f7d1 100644 --- a/includes/specials/pagers/ContribsPager.php +++ b/includes/specials/pagers/ContribsPager.php @@ -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. diff --git a/includes/watcheditem/WatchedItemQueryService.php b/includes/watcheditem/WatchedItemQueryService.php index d7979c81546a..d7442e1a6eba 100644 --- a/includes/watcheditem/WatchedItemQueryService.php +++ b/includes/watcheditem/WatchedItemQueryService.php @@ -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; } |