API: (bug 20554) Expose average slave lag (avglag) as well as maxlag. Patch by Sam Reed.

This commit is contained in:
Roan Kattouw 2009-11-06 14:38:55 +00:00
parent 1b389a2afc
commit 1b89cd274a
10 changed files with 95 additions and 0 deletions

View file

@ -684,6 +684,7 @@ Hopefully we will remove this configuration var soon)
* (bug 19004) Added support for tags
* (bug 21083) list=allusers no longer returns current timestamp for users
without registration date
* (bug 20554) Expose average slave lag (avglag) as well as maxlag
=== Languages updated in 1.16 ===

View file

@ -3113,6 +3113,21 @@ function wfMaxlagError( $host, $lag, $maxLag ) {
}
}
/**
* Displays a avglag error
*
* @param $lag Integer: avglag (actual)
* @param $avgLag Integer: avglag (requested)
*/
function wfAvglagError( $lag, $avgLag ) {
header( 'HTTP/1.1 503 Service Unavailable' );
header( 'Retry-After: ' . max( intval( $avgLag ), 5 ) );
header( 'X-Database-Lag: ' . intval( $lag ) );
header( 'Content-Type: text/plain' );
echo "Lagged: $lag seconds average\n";
}
/**
* Throws a warning that $function is deprecated
* @param $function String

View file

@ -95,6 +95,24 @@ class MediaWiki {
return true;
}
}
/**
* Check if the average lag of database slaves is higher that $avgLag, and
* if it's the case, output an error message
*
* @param $avgLag int: maximum lag allowed for the request, as supplied by
* the client
* @return bool true if the request can continue
*/
function checkAvgLag( $avgLag ) {
list( $host, $lag ) = wfGetLB()->getAvgLag();
if( $lag > $avgLag ) {
wfAvglagError( $lag, $avgLag );
return false;
} else {
return true;
}
}
/**
* Checks some initial queries

View file

@ -935,6 +935,14 @@ abstract class ApiBase {
public function shouldCheckMaxlag() {
return true;
}
/**
* Indicates if this module needs avglag to be checked
* @return bool
*/
public function shouldCheckAvglag() {
return true;
}
/**
* Indicates whether this module requires read rights

View file

@ -49,6 +49,10 @@ class ApiHelp extends ApiBase {
public function shouldCheckMaxlag() {
return false;
}
public function shouldCheckAvglag() {
return false;
}
public function isReadMode() {
return false;

View file

@ -394,6 +394,20 @@ class ApiMain extends ApiBase {
return;
}
}
if( $module->shouldCheckAvglag() && isset( $params['avglag'] ) ) {
// Check for avglag
global $wgShowHostnames;
$avgLag = $params['avglag'];
$lag = wfGetLB()->getAvgLag();
if ( $lag > $avgLag ) {
header( 'Retry-After: ' . max( intval( $avgLag ), 5 ) );
header( 'X-Database-Lag: ' . intval( $lag ) );
$this->dieUsage( "Lag: $lag seconds average", 'avglag' );
return;
}
}
global $wgUser;
if ($module->isReadMode() && !$wgUser->isAllowed('read'))
@ -477,6 +491,9 @@ class ApiMain extends ApiBase {
'maxlag' => array (
ApiBase :: PARAM_TYPE => 'integer'
),
'avglag' => array (
ApiBase :: PARAM_TYPE => 'integer'
),
'smaxage' => array (
ApiBase :: PARAM_TYPE => 'integer',
ApiBase :: PARAM_DFLT => 0
@ -498,6 +515,7 @@ class ApiMain extends ApiBase {
'action' => 'What action you would like to perform',
'version' => 'When showing help, include version for each module',
'maxlag' => 'Maximum lag',
'avglag' => 'Average lag',
'smaxage' => 'Set the s-maxage header to this many seconds. Errors are never cached',
'maxage' => 'Set the max-age header to this many seconds. Errors are never cached',
'requestid' => 'Request ID to distinguish requests. This will just be output back to you',

View file

@ -548,6 +548,10 @@ class ApiQuery extends ApiBase {
public function shouldCheckMaxlag() {
return true;
}
public function shouldCheckAvglag() {
return true;
}
public function getParamDescription() {
return array (

View file

@ -295,6 +295,7 @@ class ApiQuerySiteinfo extends ApiQueryBase {
);
}
$data['avglag'] = wfGetLB()->getAvgLag();
$result = $this->getResult();
$result->setIndexedTagName( $data, 'db' );
return $this->getResult()->addValue( 'query', $property, $data );

View file

@ -898,6 +898,27 @@ class LoadBalancer {
}
return array( $host, $maxLag );
}
/**
* Gets the average lag of slaves.
* May attempt to open connections to slaves on the default DB.
*/
function getAvgLag() {
$lag = 0;
$count = 0;
foreach ( $this->mServers as $i => $conn ) {
$conn = $this->getAnyOpenConnection( $i );
if ( !$conn ) {
$conn = $this->openConnection( $i );
}
if ( !$conn ) {
continue;
}
$lag += $conn->getLag();
$count++;
}
return ($count > 1) ? $lag / $count : $lag;
}
/**
* Get lag time for each server

View file

@ -53,6 +53,11 @@ if( !is_null( $maxLag ) && !$mediaWiki->checkMaxLag( $maxLag ) ) {
exit;
}
$avgLag = $wgRequest->getVal( 'avglag' );
if( !is_null( $avgLag ) && !$mediaWiki->checkAvgLag( $avgLag ) ) {
exit;
}
# Query string fields
$action = $wgRequest->getVal( 'action', 'view' );
$title = $wgRequest->getVal( 'title' );