jenkins-bot has submitted this change and it was merged.

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, 186 insertions(+), 160 deletions(-)

Approvals:
  Aaron Schulz: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/ApiFileAnnotations.php b/ApiFileAnnotations.php
index 5ac4e4f..70445cd 100644
--- a/ApiFileAnnotations.php
+++ b/ApiFileAnnotations.php
@@ -25,13 +25,17 @@
  */
 
 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' );
        }
 
        public function execute() {
-               wfProfileIn( __METHOD__ );
-
                $params = $this->extractRequestParams();
                $shouldParse = $params['parse'];
 
@@ -78,172 +82,197 @@
                }
        }
 
-       protected function renderCommonsAnnotation( $commonsMatches, 
$commonsCategoryMatch ) {
+       protected function renderCommonsAnnotation( $commonsMatches ) {
                $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'
+               $cache = ObjectCache::getMainWANInstance();
+
+               return $cache->getWithSetCallback(
+                       $cache->makeKey( 'fileannotations', 'commonscategory', 
$categoryName ),
+                       self::CACHE_TTL,
+                       function ( $oldValue, &$ttl, array &$setOpts ) use ( 
$categoryName ) {
+                               $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'
+                               );
+
+                               $imagesApiData = json_decode( 
$imagesApiDataStr, true );
+
+                               $pages = $imagesApiData['query']['pages'];
+
+                               $imagesHtml = '<div class="category-members">';
+
+                               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>';
+
+                               return
+                                       '<div 
class="commons-category-annotation">' .
+                                               $imagesHtml .
+                                               '<a href="' . $href . '">' .
+                                                       'See more images' .
+                                               '</a>' .
+                                       '</div>';
+                       }
                );
-
-               $imagesApiData = json_decode( $imagesApiDataStr, true );
-
-               $pages = $imagesApiData['query']['pages'];
-
-               $imagesHtml = '<div class="category-members">';
-
-               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>';
-
-               return
-                       '<div class="commons-category-annotation">' .
-                               $imagesHtml .
-                               '<a href="' . $href . '">' .
-                                       'See more images' .
-                               '</a>' .
-                       '</div>';
        }
 
-       protected function renderWikipediaAnnotation( $wpMatches, 
$wpArticleMatch ) {
+       protected function renderWikipediaAnnotation( $wpMatches ) {
                $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'
+               $cache = ObjectCache::getMainWANInstance();
+
+               return $cache->getWithSetCallback(
+                       $cache->makeKey( 'fileannotations', 'wikipediapage', 
$language, $articleName ),
+                       self::CACHE_TTL,
+                       function ( $oldValue, &$ttl, array &$setOpts ) use ( 
$articleName, $language ) {
+                               $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'
+                               );
+
+                               $articleApiData = json_decode( 
$articleApiDataStr, true );
+
+                               $pages = $articleApiData['query']['pages'];
+
+                               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>';
+                               }
+                       }
                );
-
-               $articleApiData = json_decode( $articleApiDataStr, true );
-
-               $pages = $articleApiData['query']['pages'];
-
-               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>';
-               }
        }
 
-       protected function renderWikidataAnnotation( $wdMatches, $wdEntityMatch 
) {
+       protected function renderWikidataAnnotation( $wdMatches ) {
                $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'
+               $cache = ObjectCache::getMainWANInstance();
+
+               return $cache->getWithSetCallback(
+                       $cache->makeKey( 'fileannotations', 'wikidataentity', 
$currentLang, $entityId ),
+                       self::CACHE_TTL,
+                       function ( $oldValue, &$ttl, array &$setOpts ) use ( 
$entityId, $currentLang ) {
+                               $entityApiDataStr = file_get_contents(
+                                       'https://www.wikidata.org/w/api.php' .
+                                       '?action=wbgetentities' .
+                                       '&ids=' . $entityId .
+                                       '&languages=en|' . $currentLang .
+                                       '&props=labels|descriptions|claims' .
+                                       '&format=json'
+                               );
+
+                               $entityApiData = json_decode( 
$entityApiDataStr, true );
+
+                               $entity = $entityApiData['entities'][$entityId];
+
+                               $labels = $entity['labels'];
+                               $descriptions = $entity['descriptions'];
+                               $claims = $entity['claims'];
+
+                               $imageHtml = null;
+
+                               foreach ( $claims as $claimid => $claim ) {
+                                       switch ( $claimid ) {
+                                               case 'P18':
+                                                       // Main image. Fetch 
imageinfo and render.
+                                                       $imageHtml = 
$this->renderWdImage(
+                                                               
$claim[0]['mainsnak']['datavalue']['value']
+                                                       );
+                                                       break;
+
+                                               default:
+                                                       continue;
+                                       }
+                               }
+
+                               $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;
+                                       }
+                               }
+
+                               return $parsed;
+                       }
                );
-
-               $entityApiData = json_decode( $entityApiDataStr, true );
-
-               $entity = $entityApiData['entities'][$entityId];
-
-               $labels = $entity['labels'];
-               $descriptions = $entity['descriptions'];
-               $claims = $entity['claims'];
-
-               $imageHtml = null;
-
-               foreach ( $claims as $claimid => $claim ) {
-                       switch ( $claimid ) {
-                               case 'P18':
-                                       // Main image. Fetch imageinfo and 
render.
-                                       $imageHtml = $this->renderWdImage(
-                                               
$claim[0]['mainsnak']['datavalue']['value']
-                                       );
-                                       break;
-
-                               default:
-                                       continue;
-                       }
-               }
-
-               $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;
-                       }
-
-                       if ( !is_null( $description ) ) {
-                               $html .= $description;
-                       }
-               }
-
-               return $html;
        }
 
        protected function renderWdImage( $imageTitle ) {
@@ -315,22 +344,19 @@
 
                        if ( $commonsCategoryMatch === 1 ) {
                                $parsed = $this->renderCommonsAnnotation(
-                                       $commonsMatches,
-                                       $commonsCategoryMatch
+                                       $commonsMatches
                                );
                        }
 
                        if ( $wpArticleMatch === 1 ) {
                                $parsed = $this->renderWikipediaAnnotation(
-                                       $wpMatches,
-                                       $wpArticleMatch
+                                       $wpMatches
                                );
                        }
 
                        if ( $wdEntityMatch === 1 ) {
                                $parsed = $this->renderWikidataAnnotation(
-                                       $wdMatches,
-                                       $wdEntityMatch
+                                       $wdMatches
                                );
                        }
                }

-- 
To view, visit https://gerrit.wikimedia.org/r/308775
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Ic319afc11e5befdab26542616cda85b52ff61512
Gerrit-PatchSet: 4
Gerrit-Project: mediawiki/extensions/FileAnnotations
Gerrit-Branch: master
Gerrit-Owner: MarkTraceur <[email protected]>
Gerrit-Reviewer: Aaron Schulz <[email protected]>
Gerrit-Reviewer: MarkTraceur <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to