MarkTraceur has uploaded a new change for review.
https://gerrit.wikimedia.org/r/308775
Change subject: Cache, cache, everywhere a cache
......................................................................
Cache, cache, everywhere a cache
Cache API requests and rendering for WD, WP, and Commons annotations,
because fetching data from those sites is not super efficient.
Only caching for five minutes currently, to avoid making it totally
impossible to get updated data in a timely manner. Thoughts?
Change-Id: Ic319afc11e5befdab26542616cda85b52ff61512
---
M ApiFileAnnotations.php
1 file changed, 177 insertions(+), 129 deletions(-)
git pull
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/FileAnnotations
refs/changes/75/308775/1
diff --git a/ApiFileAnnotations.php b/ApiFileAnnotations.php
index 5ac4e4f..2af9c53 100644
--- a/ApiFileAnnotations.php
+++ b/ApiFileAnnotations.php
@@ -25,6 +25,12 @@
*/
class ApiFileAnnotations extends ApiQueryBase {
+ // 5 minutes - long enough to avoid crashing the servers with a lot
+ // of repeated requests for the same data, but not long enough so it's
+ // hard to update information quickly. Cache not invalidated by changes
+ // to Wikidata, Wikipedia, or Commons.
+ const CACHE_TTL = 300;
+
public function __construct( $query, $moduleName ) {
parent::__construct( $query, $moduleName, 'fa' );
}
@@ -81,169 +87,211 @@
protected function renderCommonsAnnotation( $commonsMatches,
$commonsCategoryMatch ) {
$categoryName = $commonsMatches[1];
- $imagesApiDataStr = file_get_contents(
- 'https://commons.wikimedia.org/w/api.php' .
- '?action=query' .
- '&prop=imageinfo' .
- '&generator=categorymembers' .
- '&gcmtype=file' .
- '&gcmtitle=' . urlencode( $categoryName ) .
- '&gcmlimit=5' .
- '&iiprop=url' .
- '&iiurlwidth=100' .
- '&iiurlheight=100' .
- '&format=json'
- );
+ $key = wfMemcKey( 'fileannotations', 'commonscategory',
$categoryName );
+ $cache = wfGetCache( CACHE_ANYTHING );
+ $parsed = $cache->get( $key );
- $imagesApiData = json_decode( $imagesApiDataStr, true );
+ if ( $parsed === false ) {
+ $imagesApiDataStr = file_get_contents(
+ 'https://commons.wikimedia.org/w/api.php' .
+ '?action=query' .
+ '&prop=imageinfo' .
+ '&generator=categorymembers' .
+ '&gcmtype=file' .
+ '&gcmtitle=' . urlencode( $categoryName ) .
+ '&gcmlimit=5' .
+ '&iiprop=url' .
+ '&iiurlwidth=100' .
+ '&iiurlheight=100' .
+ '&format=json'
+ );
- $pages = $imagesApiData['query']['pages'];
+ $imagesApiData = json_decode( $imagesApiDataStr, true );
- $imagesHtml = '<div class="category-members">';
+ $pages = $imagesApiData['query']['pages'];
- foreach ( $pages as $id => $page ) {
- $info = $page['imageinfo'][0];
- $href = $info['descriptionurl'];
- $src = $info['thumburl'];
+ $imagesHtml = '<div class="category-members">';
- $imagesHtml .=
- '<a class="category-member" href="' . $href .
'">' .
- '<img src="' . $src . '" />' .
- '</a>';
+ foreach ( $pages as $id => $page ) {
+ $info = $page['imageinfo'][0];
+ $href = $info['descriptionurl'];
+ $src = $info['thumburl'];
+
+ $imagesHtml .=
+ '<a class="category-member" href="' .
$href . '">' .
+ '<img src="' . $src . '" />' .
+ '</a>';
+ }
+
+ $imagesHtml .= '</div>';
+
+ $parsed =
+ '<div class="commons-category-annotation">' .
+ $imagesHtml .
+ '<a href="' . $href . '">' .
+ 'See more images' .
+ '</a>' .
+ '</div>';
+
+ $cache->set(
+ $key,
+ $parsed,
+ self::CACHE_TTL
+ );
}
- $imagesHtml .= '</div>';
-
- return
- '<div class="commons-category-annotation">' .
- $imagesHtml .
- '<a href="' . $href . '">' .
- 'See more images' .
- '</a>' .
- '</div>';
+ return $parsed;
}
protected function renderWikipediaAnnotation( $wpMatches,
$wpArticleMatch ) {
$articleName = $wpMatches[2];
+ $language = $wpMatches[1];
- $articleApiDataStr = file_get_contents(
- $wpMatches[1] .
- '/w/api.php?action=query' .
- '&titles=' . urlencode( $articleName ) .
- '&prop=pageimages|extracts' .
- '&piprop=thumbnail|name' .
- '&pithumbsize=250' .
- '&exsentences=4' .
- '&format=json'
- );
+ $key = wfMemcKey( 'fileannotations', 'wikipediapage',
$language, $articleName );
+ $cache = wfGetCache( CACHE_ANYTHING );
+ $parsed = $cache->get( $key );
- $articleApiData = json_decode( $articleApiDataStr, true );
+ if ( $parsed === false ) {
+ $articleApiDataStr = file_get_contents(
+ $language .
+ '/w/api.php?action=query' .
+ '&titles=' . urlencode( $articleName ) .
+ '&prop=pageimages|extracts' .
+ '&piprop=thumbnail|name' .
+ '&pithumbsize=250' .
+ '&exsentences=4' .
+ '&format=json'
+ );
- $pages = $articleApiData['query']['pages'];
+ $articleApiData = json_decode( $articleApiDataStr, true
);
- foreach ( $pages as $id => $page ) {
- // There's only one page, so just do it here
- return
- '<div class="wikipedia-article-annotation">' .
- $page['extract'] .
- '<p class="pageimage">' .
- '<img src="' .
-
$page['thumbnail']['source'] .
- '" width="' .
-
$page['thumbnail']['width'] .
- '" height="' .
-
$page['thumbnail']['height'] .
- '" />' .
- '</p>' .
- '</div>';
+ $pages = $articleApiData['query']['pages'];
+
+ foreach ( $pages as $id => $page ) {
+ // There's only one page, so just do it here
+ $parsed =
+ '<div
class="wikipedia-article-annotation">' .
+ $page['extract'] .
+ '<p class="pageimage">' .
+ '<img src="' .
+
$page['thumbnail']['source'] .
+ '" width="' .
+
$page['thumbnail']['width'] .
+ '" height="' .
+
$page['thumbnail']['height'] .
+ '" />' .
+ '</p>' .
+ '</div>';
+ break;
+ }
+
+ $cache->set(
+ $key,
+ $parsed,
+ self::CACHE_TTL
+ );
}
+
+ return $parsed;
}
protected function renderWikidataAnnotation( $wdMatches, $wdEntityMatch
) {
$entityId = $wdMatches[2];
$currentLang = $this->getLanguage()->getCode();
- $entityApiDataStr = file_get_contents(
- 'https://www.wikidata.org/w/api.php' .
- '?action=wbgetentities' .
- '&ids=' . $entityId .
- '&languages=en|' . $currentLang .
- '&props=labels|descriptions|claims' .
- '&format=json'
- );
+ $key = wfMemcKey( 'fileannotations', 'wikidataentity',
$currentLang, $entityId );
+ $cache = wfGetCache( CACHE_ANYTHING );
+ $parsed = $cache->get( $key );
- $entityApiData = json_decode( $entityApiDataStr, true );
+ if ( $parsed === false ) {
+ $entityApiDataStr = file_get_contents(
+ 'https://www.wikidata.org/w/api.php' .
+ '?action=wbgetentities' .
+ '&ids=' . $entityId .
+ '&languages=en|' . $currentLang .
+ '&props=labels|descriptions|claims' .
+ '&format=json'
+ );
- $entity = $entityApiData['entities'][$entityId];
+ $entityApiData = json_decode( $entityApiDataStr, true );
- $labels = $entity['labels'];
- $descriptions = $entity['descriptions'];
- $claims = $entity['claims'];
+ $entity = $entityApiData['entities'][$entityId];
- $imageHtml = null;
+ $labels = $entity['labels'];
+ $descriptions = $entity['descriptions'];
+ $claims = $entity['claims'];
- foreach ( $claims as $claimid => $claim ) {
- switch ( $claimid ) {
- case 'P18':
- // Main image. Fetch imageinfo and
render.
- $imageHtml = $this->renderWdImage(
-
$claim[0]['mainsnak']['datavalue']['value']
- );
- break;
+ $imageHtml = null;
- default:
- continue;
- }
- }
+ foreach ( $claims as $claimid => $claim ) {
+ switch ( $claimid ) {
+ case 'P18':
+ // Main image. Fetch imageinfo
and render.
+ $imageHtml =
$this->renderWdImage(
+
$claim[0]['mainsnak']['datavalue']['value']
+ );
+ break;
- $label = null;
- $description = null;
-
- if ( isset( $labels[$currentLang] ) ) {
- $label =
- '<h2 class="wikidata-label">' .
- $labels[$currentLang]['value'] .
- '</h2>';
- } elseif ( isset( $labels['en'] ) ) {
- // Blatantly strange fallback, but we don't want to have
- // no label...hopefully this works for 99% of things.
- $label =
- '<h2 class="wikidata-label">' .
- $labels['en']['value'] .
- '</h2>';
- }
-
- if ( isset( $descriptions[$currentLang] ) ) {
- $description =
- '<p class="wikidata-description">' .
- $descriptions[$currentLang]['value'] .
- '</p>';
- } elseif ( isset( $descriptions['en'] ) ) {
- $description =
- '<p class="wikidata-description">' .
- $descriptions['en']['value'] .
- '</p>';
- }
-
- $html = '<div class="wikidata-entity-annotation">';
-
- if ( !is_null( $imageHtml ) ) {
- $html .= $imageHtml;
- }
-
- if ( !is_null( $label ) || !is_null( $description ) ) {
- $html .= '<div class="text-content">';
-
- if ( !is_null( $label ) ) {
- $html .= $label;
+ default:
+ continue;
+ }
}
- if ( !is_null( $description ) ) {
- $html .= $description;
+ $label = null;
+ $description = null;
+
+ if ( isset( $labels[$currentLang] ) ) {
+ $label =
+ '<h2 class="wikidata-label">' .
+ $labels[$currentLang]['value'] .
+ '</h2>';
+ } elseif ( isset( $labels['en'] ) ) {
+ // Blatantly strange fallback, but we don't
want to have
+ // no label...hopefully this works for 99% of
things.
+ $label =
+ '<h2 class="wikidata-label">' .
+ $labels['en']['value'] .
+ '</h2>';
}
+
+ if ( isset( $descriptions[$currentLang] ) ) {
+ $description =
+ '<p class="wikidata-description">' .
+
$descriptions[$currentLang]['value'] .
+ '</p>';
+ } elseif ( isset( $descriptions['en'] ) ) {
+ $description =
+ '<p class="wikidata-description">' .
+ $descriptions['en']['value'] .
+ '</p>';
+ }
+
+ $parsed = '<div class="wikidata-entity-annotation">';
+
+ if ( !is_null( $imageHtml ) ) {
+ $parsed .= $imageHtml;
+ }
+
+ if ( !is_null( $label ) || !is_null( $description ) ) {
+ $parsed .= '<div class="text-content">';
+
+ if ( !is_null( $label ) ) {
+ $parsed .= $label;
+ }
+
+ if ( !is_null( $description ) ) {
+ $parsed .= $description;
+ }
+ }
+
+ $cache->set(
+ $key,
+ $parsed,
+ self::CACHE_TTL
+ );
}
- return $html;
+ return $parsed;
}
protected function renderWdImage( $imageTitle ) {
--
To view, visit https://gerrit.wikimedia.org/r/308775
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ic319afc11e5befdab26542616cda85b52ff61512
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/FileAnnotations
Gerrit-Branch: master
Gerrit-Owner: MarkTraceur <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits