jenkins-bot has submitted this change and it was merged.
Change subject: Updates after performance review
......................................................................
Updates after performance review
* Use MapCacheLRU in displayGlobalPage()
* Optimize brokenLink to avoid DB queries if already known
* Don't check prefs if GlobalPreferences is disabled
* Use MapCacheLRU in getCentralTouched() and call
reuseConnection()
* getRemoteParsedText() has a fixed length memcached key
* Optionally use $wgConf in getRemoteURL()
* Use a custom timeout for internal API requests
* Gracefully fail if an internal API request fails
Bug: 70585
Change-Id: I7440151f29bf38b6c135d8508ac1a0cf24a5677e
---
M GlobalUserPage.body.php
M GlobalUserPage.hooks.php
M GlobalUserPage.php
3 files changed, 117 insertions(+), 55 deletions(-)
Approvals:
Aaron Schulz: Looks good to me, approved
jenkins-bot: Verified
diff --git a/GlobalUserPage.body.php b/GlobalUserPage.body.php
index 421aeb6..df8f89c 100644
--- a/GlobalUserPage.body.php
+++ b/GlobalUserPage.body.php
@@ -12,6 +12,16 @@
*/
private $cache;
+ /**
+ * @var MapCacheLRU
+ */
+ private static $displayCache;
+
+ /**
+ * @var MapCacheLRU
+ */
+ private static $touchedCache;
+
public function __construct( Title $title, Config $config ) {
global $wgMemc;
parent::__construct( $title );
@@ -32,8 +42,9 @@
$out = $this->getContext()->getOutput();
$parsedOutput = $this->getRemoteParsedText(
self::getCentralTouched( $user ) );
- // If the user page is empty, don't use it
- if ( !trim( $parsedOutput['text']['*'] ) ) {
+ // If the user page is empty or the API request failed, show
the normal
+ // missing article page
+ if ( !$parsedOutput || !trim( $parsedOutput['text']['*'] ) ) {
parent::showMissingArticle();
return;
}
@@ -79,15 +90,6 @@
}
/**
- * @param int $type DB_SLAVE or DB_MASTER
- * @return DatabaseBase
- */
- protected static function getRemoteDB( $type ) {
- global $wgGlobalUserPageDBname;
- return wfGetDB( $type, array(), $wgGlobalUserPageDBname );
- }
-
- /**
* Given a Title, assuming it doesn't exist, should
* we display a global user page on it
*
@@ -96,28 +98,33 @@
*/
public static function displayGlobalPage( Title $title ) {
global $wgGlobalUserPageDBname;
- static $cache = array();
+ if ( !self::$displayCache ) {
+ self::$displayCache = new MapCacheLRU( 100 );
+ }
$text = $title->getPrefixedText();
// Do some instance caching since this can be
// called frequently due do the Linker hook
- if ( isset( $cache[$text] ) ) {
- return $cache[$text];
+ if ( self::$displayCache->has( $text ) ) {
+ return self::$displayCache->get( $text );
}
if ( !self::canBeGlobal( $title ) ) {
- $cache[$text] = false;
+ self::$displayCache->set( $text, false );
return false;
}
$user = User::newFromName( $title->getText() );
if ( !$user || $user->getId() === 0 ) {
- $cache[$text] = false;
+ self::$displayCache->set( $text, false );
return false;
}
- if ( !$user->getOption( 'globaluserpage' ) ) {
- $cache[$text] = false;
- return false;
+ // Only check preferences if E:GlobalPreferences is installed
+ if ( class_exists( 'GlobalPreferences' ) ) {
+ if ( !$user->getOption( 'globaluserpage' ) ) {
+ self::$displayCache->set( $text, false );
+ return false;
+ }
}
// Allow for authorization extensions to determine
@@ -125,12 +132,13 @@
// This hook intentionally functions the same
// as the one in Extension:GlobalCssJs.
if ( !wfRunHooks( 'LoadGlobalUserPage', array( $user,
$wgGlobalUserPageDBname, wfWikiID() ) ) ) {
- $cache[$text] = false;
+ self::$displayCache->set( $text, false );
return false;
}
- $cache[$text] = (bool)self::getCentralTouched( $user );
- return $cache[$text];
+ $touched = (bool)self::getCentralTouched( $user );
+ self::$displayCache->set( $text, $touched );
+ return $touched;
}
/**
@@ -141,20 +149,27 @@
* @return string|bool
*/
protected static function getCentralTouched( User $user ) {
- static $cache = array();
- if ( !isset( $cache[$user->getName()] ) ) {
- $cache[$user->getName()] = self::getRemoteDB( DB_SLAVE
)->selectField(
- 'page',
- 'page_touched',
- array(
- 'page_namespace' => NS_USER,
- 'page_title' =>
$user->getUserPage()->getDBkey()
- ),
- __METHOD__
- );
+ if ( self::$touchedCache->has( $user->getName() ) ) {
+ return self::$touchedCache->get( $user->getName() );
}
- return $cache[$user->getName()];
+ global $wgGlobalUserPageDBname;
+ $lb = wfGetLB( $wgGlobalUserPageDBname );
+ $dbr = $lb->getConnection( DB_SLAVE, array(),
$wgGlobalUserPageDBname );
+ $touched = $dbr->selectField(
+ 'page',
+ 'page_touched',
+ array(
+ 'page_namespace' => NS_USER,
+ 'page_title' => $user->getUserPage()->getDBkey()
+ ),
+ __METHOD__
+ );
+ $lb->reuseConnection( $dbr );
+
+ self::$touchedCache->set( $user->getName(), $touched );
+
+ return $touched;
}
/**
@@ -194,11 +209,16 @@
$langCode = $this->getContext()->getLanguage()->getCode();
// Need language code in the key since we pass &uselang= to the
API.
- $key =
"globaluserpage:parsed:$touched:$langCode:{$this->getUsername()}";
+ $key = "globaluserpage:parsed:$touched:$langCode:" . md5(
$this->getUsername() );
$data = $this->cache->get( $key );
if ( $data === false ){
$data = $this->parseWikiText( $this->getTitle(),
$langCode );
- $this->cache->set( $key, $data, $this->config->get(
'GlobalUserPageCacheExpiry' ) );
+ if ( $data ) {
+ $this->cache->set( $key, $data,
$this->config->get( 'GlobalUserPageCacheExpiry' ) );
+ } else {
+ // Cache failure for 10 seconds
+ $this->cache->set( $key, null, 10 );
+ }
}
return $data;
@@ -239,16 +259,43 @@
* Makes an API request to the central wiki
*
* @param $params array
- * @return array
+ * @return array|bool false if the request failed
*/
protected function makeAPIRequest( $params ) {
$params['format'] = 'json';
$url = wfAppendQuery( $this->config->get(
'GlobalUserPageAPIUrl' ), $params );
- $req = MWHttpRequest::factory( $url );
- $req->execute();
+ $req = MWHttpRequest::factory(
+ $url,
+ array( 'timeout' => $this->config->get(
'GlobalUserPageTimeout' ) )
+ );
+ $status = $req->execute();
+ if ( !$status->isOK() ) {
+ return false;
+ }
$json = $req->getContent();
$decoded = FormatJson::decode( $json, true );
return $decoded;
+ }
+
+ /**
+ * Returns a URL to the user page on the central wiki,
+ * attempts to use SiteConfiguration if possible, else
+ * falls back to using an API request
+ *
+ * @return string
+ */
+ protected function getRemoteURL() {
+ $url = WikiMap::getForeignURL(
+ $this->config->get( 'GlobalUserPageDBname' ),
+ 'User:' . $this->getUsername()
+ );
+
+ if ( $url !== false ) {
+ return $url;
+ } else {
+ // Fallback to the API
+ return $this->getRemoteURLFromAPI();
+ }
}
/**
@@ -259,7 +306,7 @@
*
* @return string
*/
- protected function getRemoteURL() {
+ protected function getRemoteURLFromAPI() {
$key = 'globaluserpage:url:' . md5( $this->getUsername() );
$data = $this->cache->get( $key );
if ( $data === false ) {
@@ -271,6 +318,10 @@
'indexpageids' => '1',
);
$resp = $this->makeAPIRequest( $params );
+ if ( $resp === false ) {
+ // Don't cache upon failure
+ return '';
+ }
$pageInfo =
$resp['query']['pages'][$resp['query']['pageids'][0]];
if ( isset( $pageInfo['canonicalurl'] ) ) {
// New in 1.24
@@ -308,6 +359,6 @@
'prop' => 'text|modules'
);
$data = $this->makeAPIRequest( $params );
- return $data['parse'];
+ return $data !== false ? $data['parse'] : false;
}
}
diff --git a/GlobalUserPage.hooks.php b/GlobalUserPage.hooks.php
index 5ea610d..6b09ea5 100644
--- a/GlobalUserPage.hooks.php
+++ b/GlobalUserPage.hooks.php
@@ -102,22 +102,25 @@
/**
* Turn red User: links into blue ones
*
- * @param $linker Linker
- * @param $target Title
- * @param $text String
- * @param $customAtrribs Array: array of custom attributes [unused]
- * @param $query [unused]
- * @param $ret String: return value (link HTML)
- * @return Boolean
+ * @param DummyLinker $linker for b/c
+ * @param Title $target
+ * @param string $text
+ * @param array $customAttribs custom attributes
+ * @param array $query
+ * @param array $options
+ * @param string $ret return value (link HTML)
+ * @return bool
*/
public static function brokenLink( $linker, $target, &$text,
&$customAttribs, &$query, &$options, &$ret ) {
+ if ( in_array( 'known', $options ) || $target->isKnown() ) {
+ return true;
+ }
+
if ( GlobalUserPage::displayGlobalPage( $target ) ) {
- if ( in_array( 'known', $options ) ||
$target->isKnown() ) {
- return true;
- } else {
- $ret = Linker::linkKnown( $target, $text );
- return false;
- }
+ $options = array_merge(
+ $options,
+ array( 'known', 'noclasses' )
+ );
}
return true;
diff --git a/GlobalUserPage.php b/GlobalUserPage.php
index 5e4f534..bafa0a5 100644
--- a/GlobalUserPage.php
+++ b/GlobalUserPage.php
@@ -68,11 +68,19 @@
*/
$wgGlobalUserPageCSSRLSourceName = false;
+/**
+ * Timeout for internal API requests. To use $wgHTTPTimeout,
+ * set this to 'default'
+ *
+ * @var string|int
+ */
+$wgGlobalUserPageTimeout = 10;
+
// Extension credits that will show up on Special:Version
$wgExtensionCredits['other'][] = array(
'path' => __FILE__,
'name' => 'GlobalUserPage',
- 'version' => '0.9',
+ 'version' => '0.9.1',
'author' => array( 'Kunal Mehta', 'Jack Phoenix' ),
'url' => 'https://www.mediawiki.org/wiki/Extension:GlobalUserPage',
'descriptionmsg' => 'globaluserpage-desc',
--
To view, visit https://gerrit.wikimedia.org/r/169653
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I7440151f29bf38b6c135d8508ac1a0cf24a5677e
Gerrit-PatchSet: 5
Gerrit-Project: mediawiki/extensions/GlobalUserPage
Gerrit-Branch: master
Gerrit-Owner: Legoktm <[email protected]>
Gerrit-Reviewer: Aaron Schulz <[email protected]>
Gerrit-Reviewer: Jack Phoenix <[email protected]>
Gerrit-Reviewer: Legoktm <[email protected]>
Gerrit-Reviewer: MZMcBride <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits