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

Change subject: (Bug 47482) Update redis in bulk onTransactionIdle
......................................................................


(Bug 47482) Update redis in bulk onTransactionIdle

Change I00107ffc9 in mediawiki/core makes WikiPage::updateCategoryCounts defer
work to a callback function which executes at the end of the current
transaction, if one is open. This means that LinksUpdateComplete is no longer
guaranteed to run after CategoryAfterPageAdded / CategoryAfterPageRemoved.
Consequently we can no longer rely on it for batch-processing all pending
updates.

This change uses a different mechanism to defer batch processing of redis
updates to a Database->onTransactionIdle callback.

Change-Id: Ib073661c267cbabbe2ab2245224afd12b8784fca
---
M GettingStarted.php
M RedisCategorySync.php
2 files changed, 37 insertions(+), 23 deletions(-)

Approvals:
  Aaron Schulz: Looks good to me, but someone else must approve
  Mattflaschen: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/GettingStarted.php b/GettingStarted.php
index d8a5308..45f9bf1 100644
--- a/GettingStarted.php
+++ b/GettingStarted.php
@@ -164,7 +164,6 @@
 $wgHooks[ 'RecentChange_save' ][] = 'GettingStartedHooks::onRecentChange_save';
 $wgHooks[ 'CategoryAfterPageAdded' ][] = 
'RedisCategorySync::onCategoryAfterPageAdded';
 $wgHooks[ 'CategoryAfterPageRemoved' ][] = 
'RedisCategorySync::onCategoryAfterPageRemoved';
-$wgHooks[ 'LinksUpdateComplete' ][] = 
'RedisCategorySync::onLinksUpdateComplete';
 $wgHooks[ 'ListDefinedTags' ][] = 'GettingStartedHooks::onListDefinedTags';
 $wgHooks[ 'MakeGlobalVariablesScript' ][] = 
'GettingStartedHooks::onMakeGlobalVariablesScript';
 $wgHooks[ 'BeforeCreateEchoEvent' ][] = 
'GettingStartedHooks::onBeforeCreateEchoEvent';
diff --git a/RedisCategorySync.php b/RedisCategorySync.php
index 18e2bc2..041a84f 100644
--- a/RedisCategorySync.php
+++ b/RedisCategorySync.php
@@ -22,6 +22,10 @@
        /** @var array: arrays of [Category, WikiPage] removals to process. **/
        public static $removals = array();
 
+       /** @var bool: whether or not an update callback has been registered. 
**/
+       public static $callbackSet = false;
+
+
        /**
         * Acquire a Redis connection.
         * @return Redis|bool Redis client or false.
@@ -87,6 +91,7 @@
        public static function onCategoryAfterPageAdded( Category $category, 
WikiPage $page ) {
                if ( self::isUpdateRelevant( $category, $page ) ) {
                        self::$additions[] = array( $category, $page );
+                       self::setCallback();
                }
                return true;
        }
@@ -98,39 +103,49 @@
        public static function onCategoryAfterPageRemoved( Category $category, 
WikiPage $page ) {
                if ( self::isUpdateRelevant( $category, $page ) ) {
                        self::$removals[] = array( $category, $page );
+                       self::setCallback();
                }
                return true;
        }
 
        /**
-        * @param LinksUpdate &$linksUpdate
+        * Register a callback function that will perform all redis updates once
+        * the current transaction completes.
+        * @return bool True if callback was set, false if it was set already.
         */
-       public static function onLinksUpdateComplete( $linksUpdate ) {
-               if ( !count( self::$additions ) && !count( self::$removals ) ) {
-                       return true;
+       public static function setCallback() {
+               if ( self::$callbackSet ) {
+                       return false;
                }
+               self::$callbackSet = true;
 
-               $conn = self::getClient();
-               if ( !$conn ) {
-                       wfDebugLog( 'GettingStarted', "Unable to acquire redis 
connection.\n" );
-                       return true;
-               }
+               $dbw = wfGetDB( DB_MASTER );
+               $dbw->onTransactionIdle( function () {
+                       // Any category updates that happen after this will 
require an
+                       // additional run of the callback.
+                       RedisCategorySync::$callbackSet = false;
 
-               try {
-                       $redis = $conn->multi( Redis::PIPELINE );
-                       foreach( self::$additions as $addition ) {
-                               list( $category, $page ) = $addition;
-                               $redis->sAdd( self::makeCategoryKey( $category 
), $page->getId() );
+                       $conn = RedisCategorySync::getClient();
+                       if ( !$conn ) {
+                               wfDebugLog( 'GettingStarted', "Unable to 
acquire redis connection.\n" );
+                               return;
                        }
-                       foreach( self::$removals as $removal ) {
-                               list( $category, $page ) = $removal;
-                               $redis->sRem( self::makeCategoryKey( $category 
), $page->getId() );
-                       }
-                       $redis->exec();
-               } catch ( RedisException $e ) {
-                       wfDebugLog( 'GettingStarted', 'Redis exception: ' . 
$e->getMessage() . "\n" );
-               }
 
+                       try {
+                               $redis = $conn->multi( Redis::PIPELINE );
+                               while ( RedisCategorySync::$additions ) {
+                                       list( $category, $page ) = array_pop( 
RedisCategorySync::$additions );
+                                       $redis->sAdd( 
RedisCategorySync::makeCategoryKey( $category ), $page->getId() );
+                               }
+                               while ( RedisCategorySync::$removals ) {
+                                       list( $category, $page ) = array_pop( 
RedisCategorySync::$removals );
+                                       $redis->sRem( 
RedisCategorySync::makeCategoryKey( $category ), $page->getId() );
+                               }
+                               $redis->exec();
+                       } catch ( RedisException $e ) {
+                               wfDebugLog( 'GettingStarted', 'Redis exception: 
' . $e->getMessage() . "\n" );
+                       }
+               } );
                return true;
        }
 }

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

Gerrit-MessageType: merged
Gerrit-Change-Id: Ib073661c267cbabbe2ab2245224afd12b8784fca
Gerrit-PatchSet: 7
Gerrit-Project: mediawiki/extensions/GettingStarted
Gerrit-Branch: master
Gerrit-Owner: Ori.livneh <[email protected]>
Gerrit-Reviewer: Aaron Schulz <[email protected]>
Gerrit-Reviewer: Mattflaschen <[email protected]>
Gerrit-Reviewer: Ori.livneh <[email protected]>
Gerrit-Reviewer: Spage <[email protected]>
Gerrit-Reviewer: Swalling <[email protected]>
Gerrit-Reviewer: jenkins-bot

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

Reply via email to