jenkins-bot has submitted this change and it was merged.
Change subject: Per user request limits
......................................................................
Per user request limits
Needs poolcounter's Ie282b8486c7bad451fbc5fb9a8274c6e01a728a7 before we can
set $wgPoolCounterConf['CirrusSearch-PerUser'] otherwise we just abuse the
poor poolcounter. If we don't set $wgPoolCounterConf['CirrusSearch-PerUser']
then this is just a noop.
Adds some testing code that detects if the poolcounter is setup and configures
cirrus to use it if it is.
Change-Id: Iedda2d1f39bc70bb8103d0fdfb1297708c960766
---
M README
M i18n/en.json
M includes/Searcher.php
M includes/Util.php
M tests/jenkins/Jenkins.php
5 files changed, 110 insertions(+), 29 deletions(-)
Approvals:
Chad: Looks good to me, approved
jenkins-bot: Verified
diff --git a/README b/README
index 4986715..68fcbf8 100644
--- a/README
+++ b/README
@@ -108,26 +108,32 @@
elasticsearch. You can do this by installing the PoolCounter extension and
then configuring it in
LocalSettings.php like so:
require_once( "$IP/extensions/PoolCounter/PoolCounterClient.php");
- $wgPoolCounterConf = array(
- 'CirrusSearch-Search' => array( // Configuration for non-prefix
non-regex searches
- 'class' => 'PoolCounter_Client',
- 'timeout' => 30,
- 'workers' => 25,
- 'maxqueue' => 10,
- ),
- 'CirrusSearch-Prefix' => array( // Configuration for prefix searches
- 'class' => 'PoolCounter_Client',
- 'timeout' => 10,
- 'workers' => 50,
- 'maxqueue' => 10,
- ),
- 'CirrusSearch-Regex' => array( // Configuration for regex searches
- 'class' => 'PoolCounter_Client',
- 'timeout' => 30,
- 'workers' => 10,
- 'maxqueue' => 0,
- ),
- 'CirrusSearch-NamespaceLookup' => array( // Configuration for funky
namespace lookups
+ // Configuration for standard searches.
+ $wgPoolCounterConf[ 'CirrusSearch-Search' ] = array(
+ 'class' => 'PoolCounter_Client',
+ 'timeout' => 30,
+ 'workers' => 25,
+ 'maxqueue' => 50,
+ );
+ // Configuration for prefix searches. These are usually quite quick and
+ // plentiful.
+ $wgPoolCounterConf[ 'CirrusSearch-Prefix' ] = array(
+ 'class' => 'PoolCounter_Client',
+ 'timeout' => 10,
+ 'workers' => 50,
+ 'maxqueue' => 100,
+ );
+ // Configuration for regex searches. These are slow and use lots of resources
+ // so we only allow a few at a time.
+ $wgPoolCounterConf[ 'CirrusSearch-Regex' ] = array(
+ 'class' => 'PoolCounter_Client',
+ 'timeout' => 30,
+ 'workers' => 10,
+ 'maxqueue' => 10,
+ );
+ // Configuration for funky namespace lookups. These should be reasonably fast
+ // and reasonably rare.
+ $wgPoolCounterConf[ 'CirrusSearch-NamespaceLookup' ] = array(
'class' => 'PoolCounter_Client',
'timeout' => 10,
'workers' => 20,
@@ -135,6 +141,15 @@
),
);
+If you have a version of the pool counter with
Ie282b8486c7bad451fbc5fb9a8274c6e01a728a7
+you can also enable per user request limits:
+ // Each user (or remote IP) can only do 5 concurrent queries.
+ $wgPoolCounterConf[ 'CirrusSearch-PerUser' ] = array(
+ 'class' => 'PoolCounter_Client',
+ 'timeout' => 0,
+ 'workers' => 5,
+ 'maxqueue' => 5,
+ );
Upgrading
---------
@@ -257,6 +272,7 @@
This can take some time but it produces a clean development environment in a
virtual machine
that has everything required to run Cirrus.
+
Hooks
-----
CirrusSearch provides hooks that other extensions can make use of to extend
the core schema and
@@ -284,5 +300,6 @@
Licensing information
---------------------
-CirrusSearch makes use of the Elastica library to connect to elasticsearch
<http://elastica.io/>.
-It is Apache licensed and you can read the license Elastica/LICENSE.txt.
+CirrusSearch makes use of the Elastica extension containing the Elastica
library to connect
+to Elasticsearch <http://elastica.io/>. It is Apache licensed and you can read
the license
+Elastica/LICENSE.txt.
diff --git a/i18n/en.json b/i18n/en.json
index 87de93a..3ed8ecb 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -6,6 +6,8 @@
"cirrussearch-backend-error": "We could not complete your search due to
a temporary problem. Please try again later.",
"cirrussearch-parse-error": "Query was not understood. Please make it
simpler. The query was logged to improve the search system.",
"cirrussearch-too-busy-error": "Search is currently too busy. Please
try again later.",
+ "cirrussearch-too-busy-for-you-anonymous-error": "You have too many
concurrent searches running. If you are sharing an IP address with other users
you can log in to get your own limits.",
+ "cirrussearch-too-busy-for-you-logged-in-error": "You have too many
concurrent searches running.",
"cirrussearch-regex-syntax-error": "Regular expression syntax error at
$2: $1",
"cirrussearch-regex-too-busy-error": "Too many regular expression
searches currently running. Please try again later.",
"cirrussearch-regex-too-complex-error": "Regular expression is too
complex. Learn more about simplifying it
[[mw:Special:MyLanguage/Help:CirrusSearch/RegexTooComplex|here]].",
diff --git a/includes/Searcher.php b/includes/Searcher.php
index f9c0b0d..35c20d0 100644
--- a/includes/Searcher.php
+++ b/includes/Searcher.php
@@ -830,6 +830,7 @@
$indexBaseName = $this->indexBaseName;
return Util::doPoolCounterWork(
'CirrusSearch-Search',
+ $this->user,
function() use ( $searcher, $pageIds, $sourceFiltering,
$indexType, $indexBaseName ) {
try {
global
$wgCirrusSearchClientSideSearchTimeout;
@@ -857,6 +858,7 @@
$indexBaseName = $this->indexBaseName;
return Util::doPoolCounterWork(
'CirrusSearch-NamespaceLookup',
+ $this->user,
function() use ( $searcher, $name, $indexBaseName ) {
try {
$searcher->start( "lookup namespace for
$name" );
@@ -1083,8 +1085,10 @@
// Perform the search
$searcher = $this;
wfProfileIn( __METHOD__ . '-execute' );
+ $user = $this->user;
$result = Util::doPoolCounterWork(
$poolCounterType,
+ $this->user,
function() use ( $searcher, $search, $description ) {
try {
$searcher->start( $description );
@@ -1093,9 +1097,13 @@
return $searcher->failure( $e );
}
},
- function( $error, $key ) use ( $type, $description ) {
+ function( $error, $key ) use ( $type, $description,
$user ) {
wfLogWarning( "Pool error on key $key during
$description: $error" );
if ( $error === 'pool-queuefull' ) {
+ if ( strpos( $key,
'CirrusSearch:_per_user' ) === 0 ) {
+ $loggedIn = $user->isLoggedIn()
? 'logged-in' : 'anonymous';
+ return Status::newFatal(
"cirrussearch-too-busy-for-you-{$loggedIn}-error" );
+ }
if ( $type === 'regex' ) {
return Status::newFatal(
'cirrussearch-regex-too-busy-error' );
}
diff --git a/includes/Util.php b/includes/Util.php
index 0b7bf47..d4f9c46 100644
--- a/includes/Util.php
+++ b/includes/Util.php
@@ -90,31 +90,45 @@
* Wraps the complex pool counter interface to force the single call
pattern
* that Cirrus always uses.
* @param $type same as type parameter on PoolCounter::factory
+ * @param $user the user
* @param $workCallback callback when pool counter is aquired. Called
with
* no parameters.
* @param $errorCallback optional callback called on errors. Called
with
* the error string and the key as parameters. If left undefined
defaults
* to a function that returns a fatal status and logs an warning.
*/
- public static function doPoolCounterWork( $type, $workCallback,
$errorCallback = null ) {
+ public static function doPoolCounterWork( $type, $user, $workCallback,
$errorCallback = null ) {
global $wgCirrusSearchPoolCounterKey;
// By default the pool counter allows you to lock the same key
with
// multiple types. That might be useful but it isn't how
Cirrus thinks.
// Instead, all keys are scoped to their type.
- $key = "$type:$wgCirrusSearchPoolCounterKey";
+ $perUserKey = md5( $user->getName() );
+ $perUserKey = "nowait:CirrusSearch:_per_user:$perUserKey";
+ $globalKey = "$type:$wgCirrusSearchPoolCounterKey";
if ( $errorCallback === null ) {
$errorCallback = function( $error, $key ) {
wfLogWarning( "Pool error on $key: $error" );
return Status::newFatal(
'cirrussearch-backend-error' );
};
}
- $work = new PoolCounterWorkViaCallback( $type, $key, array(
- 'doWork' => $workCallback,
- 'error' => function( $status ) use ( $errorCallback,
$key ) {
+ $errorHandler = function( $key ) use ( $errorCallback ) {
+ return function( $status ) use ( $errorCallback, $key )
{
$status = $status->getErrorsArray();
return $errorCallback( $status[ 0 ][ 0 ], $key
);
- }
+ };
+ };
+ $work = new PoolCounterWorkViaCallback( 'CirrusSearch-PerUser',
$perUserKey, array(
+ 'doWork' => function() use ( $type, $globalKey,
$workCallback, $errorHandler ) {
+ // Now that we have the per user lock lets get
the operation lock.
+ // Note that this could block, causing the user
to wait in line with their lock held.
+ $work = new PoolCounterWorkViaCallback( $type,
$globalKey, array(
+ 'doWork' => $workCallback,
+ 'error' => $errorHandler( $globalKey ),
+ ) );
+ return $work->execute();
+ },
+ 'error' => $errorHandler( $perUserKey ),
) );
return $work->execute();
}
diff --git a/tests/jenkins/Jenkins.php b/tests/jenkins/Jenkins.php
index 9c94ba2..6091fcf 100644
--- a/tests/jenkins/Jenkins.php
+++ b/tests/jenkins/Jenkins.php
@@ -87,6 +87,46 @@
$wgCirrusSearchLanguageWeight[ 'user' ] = 10.0;
$wgCirrusSearchLanguageWeight[ 'wiki' ] = 5.0;
+if ( class_exists( 'PoolCounter_Client' ) ) {
+ // If the pool counter is around set up prod like pool counter settings
+ $wgPoolCounterConf[ 'CirrusSearch-Search' ] = array(
+ 'class' => 'PoolCounter_Client',
+ 'timeout' => 15,
+ 'workers' => 432,
+ 'maxqueue' => 600,
+ );
+ // Super common and mostly fast
+ $wgPoolCounterConf[ 'CirrusSearch-Prefix' ] = array(
+ 'class' => 'PoolCounter_Client',
+ 'timeout' => 15,
+ 'workers' => 432,
+ 'maxqueue' => 600,
+ );
+ // Regex searches are much heavier then regular searches so we limit the
+ // concurrent number.
+ $wgPoolCounterConf[ 'CirrusSearch-Regex' ] = array(
+ 'class' => 'PoolCounter_Client',
+ 'timeout' => 60,
+ 'workers' => 10,
+ 'maxqueue' => 20,
+ );
+ // These should be very very fast and reasonably rare
+ $wgPoolCounterConf[ 'CirrusSearch-NamespaceLookup' ] = array(
+ 'class' => 'PoolCounter_Client',
+ 'timeout' => 5,
+ 'workers' => 50,
+ 'maxqueue' => 200,
+ );
+ // Can't be enabled until poolcounter gets
Ie282b8486c7bad451fbc5fb9a8274c6e01a728a7.
+ // TODO enable this.
+ // $wgPoolCounterConf[ 'CirrusSearch-PerUser' ] = array(
+ // 'class' => 'PoolCounter_Client',
+ // 'timeout' => 0,
+ // 'workers' => 1,
+ // 'maxqueue' => 1,
+ // );
+}
+
class Jenkins {
/**
* Installs maintenance scripts that provide a clean Elasticsearch
index for testing.
--
To view, visit https://gerrit.wikimedia.org/r/177552
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Iedda2d1f39bc70bb8103d0fdfb1297708c960766
Gerrit-PatchSet: 6
Gerrit-Project: mediawiki/extensions/CirrusSearch
Gerrit-Branch: master
Gerrit-Owner: Manybubbles <[email protected]>
Gerrit-Reviewer: Chad <[email protected]>
Gerrit-Reviewer: Manybubbles <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits