Ladsgroup has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/353478 )

Change subject: Do not update chd_seen twice and use replica for reading
......................................................................

Do not update chd_seen twice and use replica for reading

Bug: T162556
Bug: T162557
Change-Id: Ic679fae1467675a325c41ecc98ecb42263b7dfeb
---
M repo/includes/Store/Sql/SqlChangeDispatchCoordinator.php
1 file changed, 41 insertions(+), 39 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikibase 
refs/changes/78/353478/1

diff --git a/repo/includes/Store/Sql/SqlChangeDispatchCoordinator.php 
b/repo/includes/Store/Sql/SqlChangeDispatchCoordinator.php
index ce93c44..4fc5438 100644
--- a/repo/includes/Store/Sql/SqlChangeDispatchCoordinator.php
+++ b/repo/includes/Store/Sql/SqlChangeDispatchCoordinator.php
@@ -236,6 +236,13 @@
        }
 
        /**
+        * @return Database A connection to the repo's replica database
+        */
+       private function getRepoReplica() {
+               return $this->getRepoLB()->getConnection( DB_REPLICA, [], 
$this->repoDB );
+       }
+
+       /**
         * @param Database $db The repo database connection to release for 
re-use.
         */
        private function releaseRepoMaster( Database $db ) {
@@ -304,14 +311,14 @@
         * @see selectClient()
         */
        private function getCandidateClients() {
-               $db = $this->getRepoMaster();
+               $dbr = $this->getRepoReplica();
 
                // XXX: subject to clock skew. Use DB based "now" time?
                $freshDispatchTime = wfTimestamp( TS_MW, $this->now() - 
$this->dispatchInterval );
                $staleLockTime = wfTimestamp( TS_MW, $this->now() - 
$this->lockGraceInterval );
 
                // TODO: pass the max change ID as a parameter!
-               $row = $db->selectRow(
+               $row = $dbr->selectRow(
                        $this->changesTable,
                        'max( change_id ) as maxid',
                        array(),
@@ -329,16 +336,19 @@
                // Limit the list to $randomness items. Candidates will be 
picked
                // from the resulting list at random.
 
-               $candidates = $db->selectFieldValues(
+               $where = [
+                       '( chd_lock is NULL ' . // not locked
+                       ' OR chd_touched < ' . $dbr->addQuotes( $staleLockTime 
) . ' ) ', // or the lock is old
+                       '( chd_touched < ' . $dbr->addQuotes( 
$freshDispatchTime ) . // and wasn't touched too recently or
+                       ' OR ( ' . (int)$maxId. ' - chd_seen ) > ' . 
(int)$this->batchSize . ') ' , // or it's lagging by more changes than batchSite
+                       'chd_seen < ' . (int)$maxId, // and not fully up to 
date.
+                       'chd_disabled = 0' // and not disabled
+               ];
+
+               $candidates = $dbr->selectFieldValues(
                        $this->stateTable,
                        'chd_site',
-                       array( '( chd_lock is NULL ' . // not locked or...
-                                       ' OR chd_touched < ' . $db->addQuotes( 
$staleLockTime ) . ' ) ', // ...the lock is old
-                               '( chd_touched < ' . $db->addQuotes( 
$freshDispatchTime ) . // and wasn't touched too recently or...
-                                       ' OR ( ' . (int)$maxId. ' - chd_seen ) 
> ' . (int)$this->batchSize . ') ' , // or it's lagging by more changes than 
batchSite
-                               'chd_seen < ' . (int)$maxId, // and not fully 
up to date.
-                               'chd_disabled = 0' // and not disabled
-                       ),
+                       $where,
                        __METHOD__,
                        array(
                                'ORDER BY' => 'chd_seen ASC',
@@ -359,9 +369,10 @@
         * @throws DBUnexpectedError
         */
        public function initState( array $clientWikiDBs ) {
-               $db = $this->getRepoMaster();
+               $dbr = $this->getRepoReplica();
+               $dbw = $this->getRepoMaster();
 
-               $trackedSiteIds = $db->selectFieldValues(
+               $trackedSiteIds = $dbr->selectFieldValues(
                        $this->stateTable,
                        'chd_site',
                        array(),
@@ -380,7 +391,7 @@
                                'chd_disabled' => 0,
                        );
 
-                       $db->insert(
+                       $dbw->insert(
                                $this->stateTable,
                                $state,
                                __METHOD__,
@@ -390,7 +401,7 @@
                        $this->log( "Initialized dispatch state for $siteID" );
                }
 
-               $this->releaseRepoMaster( $db );
+               $this->releaseRepoMaster( $dbr );
        }
 
        /**
@@ -401,7 +412,7 @@
         *
         * @throws MWException if there are no client wikis to chose from.
         * @throws Exception
-        * @return array An associative array containing the state of the 
selected client wiki
+        * @return bool|array An associative array containing the state of the 
selected client wiki
         *               (see selectClient()) or false if the client wiki could 
not be locked.
         *
         * @see selectClient()
@@ -410,14 +421,16 @@
                $this->trace( "Trying $siteID" );
 
                // start transaction
-               $db = $this->getRepoMaster();
-               $db->startAtomic( __METHOD__ );
+               $dbw = $this->getRepoMaster();
+               $dbr = $this->getRepoReplica();
+
+               $dbw->startAtomic( __METHOD__ );
 
                try {
                        $this->trace( 'Loaded repo db master' );
 
                        // get client state
-                       $state = $db->selectRow(
+                       $state = $dbr->selectRow(
                                $this->stateTable,
                                array( 'chd_site', 'chd_db', 'chd_seen', 
'chd_touched', 'chd_lock', 'chd_disabled' ),
                                array( 'chd_site' => $siteID ),
@@ -440,17 +453,17 @@
 
                        if ( $state['chd_lock'] !== null ) {
                                // bail out if another dispatcher instance is 
holding a lock for that wiki
-                               if ( $this->isClientLockUsed( $db, $lock ) ) {
+                               if ( $this->isClientLockUsed( $dbw, $lock ) ) {
                                        $this->trace( "$siteID is already being 
handled by another process."
                                                                . " (lock: " . 
$state['chd_lock'] . ")" );
 
-                                       $db->rollback( __METHOD__ );
-                                       $this->releaseRepoMaster( $db );
+                                       $dbw->rollback( __METHOD__ );
+                                       $this->releaseRepoMaster( $dbw );
                                        return false;
                                }
                        }
 
-                       $ok = $this->engageClientLock( $db, $lock );
+                       $ok = $this->engageClientLock( $dbw, $lock );
 
                        if ( !$ok ) {
                                // This really shouldn't happen, since we 
already checked if another process has a lock.
@@ -461,31 +474,20 @@
 
                                $this->trace( "Warning: Failed to acquire lock 
$lock for site $siteID!" );
 
-                               $db->rollback( __METHOD__ );
-                               $this->releaseRepoMaster( $db );
+                               $dbw->rollback( __METHOD__ );
+                               $this->releaseRepoMaster( $dbw );
                                return false;
                        }
 
                        $this->trace( "Locked client $siteID with $lock" );
-
-                       $state['chd_lock'] = $lock;
-                       $state['chd_touched'] = wfTimestamp( TS_MW, 
$this->now() ); // XXX: use DB time
-
-                       // update state record for already known client wiki
-                       $db->update(
-                               $this->stateTable,
-                               $state,
-                               array( 'chd_site' => $state['chd_site'] ),
-                               __METHOD__
-                       );
                } catch ( Exception $ex ) {
-                       $db->rollback( __METHOD__ );
-                       $this->releaseRepoMaster( $db );
+                       $dbw->rollback( __METHOD__ );
+                       $this->releaseRepoMaster( $dbw );
                        throw $ex;
                }
 
-               $db->endAtomic( __METHOD__ );
-               $this->releaseRepoMaster( $db );
+               $dbw->endAtomic( __METHOD__ );
+               $this->releaseRepoMaster( $dbw );
 
                $this->trace( "Locked site $siteID at {$state['chd_seen']}." );
 

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ic679fae1467675a325c41ecc98ecb42263b7dfeb
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Ladsgroup <[email protected]>

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

Reply via email to