Make UserEditCountUpdate::doUpdate avoid comparing IDatabase instances
authorAaron Schulz <aschulz@wikimedia.org>
Sat, 29 Jun 2019 02:11:43 +0000 (19:11 -0700)
committerKrinkle <krinklemail@gmail.com>
Tue, 2 Jul 2019 21:43:00 +0000 (21:43 +0000)
Also make User::initEditCountInternal take the specific DB handle that
was waited on for replication. This shouldn't make a difference but makes
things more explicit.

Change-Id: Ibb8e083406eb4f4453afce94a2b33450239fce94

includes/deferred/UserEditCountUpdate.php
includes/user/User.php

index e9ebabb..157c20b 100644 (file)
@@ -82,16 +82,15 @@ class UserEditCountUpdate implements DeferrableUpdate, MergeableUpdate {
                                $affectedInstances = $info['instances'];
                                // Lazy initialization check...
                                if ( $dbw->affectedRows() == 0 ) {
-                                       // No rows will be "affected" if user_editcount is NULL.
-                                       // Check if the generic "replica" connection is not the master.
+                                       // The user_editcount is probably NULL (e.g. not initialized).
+                                       // Since this update runs after the new revisions were committed,
+                                       // wait for the replica DB to catch up so they will be counted.
                                        $dbr = $lb->getConnection( DB_REPLICA );
-                                       if ( $dbr !== $dbw ) {
-                                               // This method runs after the new revisions were committed.
-                                               // Wait for the replica to catch up so they will all be counted.
-                                               $dbr->flushSnapshot( $fname );
-                                               $lb->waitForMasterPos( $dbr );
-                                       }
-                                       $affectedInstances[0]->initEditCountInternal();
+                                       // If $dbr is actually the master DB, then clearing the snapshot is
+                                       // is harmless and waitForMasterPos() will just no-op.
+                                       $dbr->flushSnapshot( $fname );
+                                       $lb->waitForMasterPos( $dbr );
+                                       $affectedInstances[0]->initEditCountInternal( $dbr );
                                }
                                $newCount = (int)$dbw->selectField(
                                        'user',
index 97d4702..965cd84 100644 (file)
@@ -3464,7 +3464,7 @@ class User implements IDBAccessObject, UserIdentity {
 
                        if ( $count === null ) {
                                // it has not been initialized. do so.
-                               $count = $this->initEditCountInternal();
+                               $count = $this->initEditCountInternal( $dbr );
                        }
                        $this->mEditCount = $count;
                }
@@ -5024,14 +5024,13 @@ class User implements IDBAccessObject, UserIdentity {
        /**
         * Initialize user_editcount from data out of the revision table
         *
-        * This method should not be called outside User/UserEditCountUpdate
-        *
+        * @internal This method should not be called outside User/UserEditCountUpdate
+        * @param IDatabase $dbr Replica database
         * @return int Number of edits
         */
-       public function initEditCountInternal() {
+       public function initEditCountInternal( IDatabase $dbr ) {
                // Pull from a replica DB to be less cruel to servers
                // Accuracy isn't the point anyway here
-               $dbr = wfGetDB( DB_REPLICA );
                $actorWhere = ActorMigration::newMigration()->getWhere( $dbr, 'rev_user', $this );
                $count = (int)$dbr->selectField(
                        [ 'revision' ] + $actorWhere['tables'],