Made ReplicatedBagOStuff wrapping the SQL class the default stash
authorAaron Schulz <aschulz@wikimedia.org>
Thu, 21 May 2015 19:05:39 +0000 (12:05 -0700)
committerKrinkle <krinklemail@gmail.com>
Wed, 24 Jun 2015 19:37:03 +0000 (19:37 +0000)
* To make this work, a slaveOnly flag was added to SqlBagOStuff
  and it no longer prunes expired items on get(), it just treats
  them as missing. The use of garbageCollect() for the writeFactory
  cache and the use of replace() on updates already makes this
  a non-issue.
* This also makes the default $wgMainStash non-bogus.

Bug: T88493
Change-Id: I9d1f31305e08430de29a3cd521cdb10a82dffd10

includes/DefaultSettings.php
includes/objectcache/SqlBagOStuff.php

index 2ea8b29..052555c 100644 (file)
@@ -2151,6 +2151,19 @@ $wgObjectCaches = array(
        CACHE_ACCEL => array( 'factory' => 'ObjectCache::newAccelerator' ),
        CACHE_MEMCACHED => array( 'factory' => 'ObjectCache::newMemcached', 'loggroup' => 'memcached' ),
 
+       'db-replicated' => array(
+               'class'       => 'ReplicatedBagOStuff',
+               'readFactory' => array(
+                       'class' => 'SqlBagOStuff',
+                       'args'  => array( array( 'slaveOnly' => true ) )
+               ),
+               'writeFactory' => array(
+                       'class' => 'SqlBagOStuff',
+                       'args'  => array( array( 'slaveOnly' => false ) )
+               ),
+               'loggroup'  => 'SQLBagOStuff'
+       ),
+
        'apc' => array( 'class' => 'APCBagOStuff' ),
        'xcache' => array( 'class' => 'XCacheBagOStuff' ),
        'wincache' => array( 'class' => 'WinCacheBagOStuff' ),
@@ -2213,6 +2226,7 @@ $wgWANObjectCaches = array(
  * lightweight data like hit counters and user activity. Sites with multiple
  * data-centers should have this use a store that replicates all writes. The
  * store should have enough consistency for CAS operations to be usable.
+ * Reads outside of those needed for merge() may be eventually consistent.
  *
  * The options are:
  *   - db:      Store cache objects in the DB
@@ -2221,7 +2235,7 @@ $wgWANObjectCaches = array(
  *
  * @since 1.26
  */
-$wgMainStash = 'db';
+$wgMainStash = 'db-replicated';
 
 /**
  * The expiry time for the parser cache, in seconds.
index 82eeb84..05115c9 100644 (file)
@@ -30,6 +30,7 @@ class SqlBagOStuff extends BagOStuff {
        /** @var LoadBalancer */
        protected $lb;
 
+       /** @var array */
        protected $serverInfos;
 
        /** @var array */
@@ -53,6 +54,9 @@ class SqlBagOStuff extends BagOStuff {
        /** @var string */
        protected $tableName = 'objectcache';
 
+       /** @var bool */
+       protected $slaveOnly = false;
+
        /** @var array UNIX timestamps */
        protected $connFailureTimes = array();
 
@@ -84,6 +88,10 @@ class SqlBagOStuff extends BagOStuff {
         *                  required to hold the largest shard index. Data will be
         *                  distributed across all tables by key hash. This is for
         *                  MySQL bugs 61735 and 61736.
+        *   - slaveOnly:   Whether to only use slave DBs and avoid triggering
+        *                  garbage collection logic of expired items. This only
+        *                  makes sense if the primary DB is used and only if get()
+        *                  calls will be used. This is used by ReplicatedBagOStuff.
         *
         * @param array $params
         */
@@ -112,6 +120,7 @@ class SqlBagOStuff extends BagOStuff {
                if ( isset( $params['shards'] ) ) {
                        $this->shards = intval( $params['shards'] );
                }
+               $this->slaveOnly = !empty( $params['slaveOnly'] );
        }
 
        /**
@@ -155,12 +164,13 @@ class SqlBagOStuff extends BagOStuff {
                                 * However, SQLite has an opposite behavior. And PostgreSQL needs to know
                                 * if we are in transaction or no
                                 */
-                               if ( wfGetDB( DB_MASTER )->getType() == 'mysql' ) {
+                               $index = $this->slaveOnly ? DB_SLAVE : DB_MASTER;
+                               if ( wfGetDB( $index )->getType() == 'mysql' ) {
                                        $this->lb = wfGetLBFactory()->newMainLB();
-                                       $db = $this->lb->getConnection( DB_MASTER );
+                                       $db = $this->lb->getConnection( $index );
                                        $db->clearFlag( DBO_TRX ); // auto-commit mode
                                } else {
-                                       $db = wfGetDB( DB_MASTER );
+                                       $db = wfGetDB( $index );
                                }
                        }
                        if ( $wgDebugDBTransactions ) {
@@ -274,12 +284,7 @@ class SqlBagOStuff extends BagOStuff {
                                try {
                                        $db = $this->getDB( $row->serverIndex );
                                        if ( $this->isExpired( $db, $row->exptime ) ) { // MISS
-                                               $this->debug( "get: key has expired, deleting" );
-                                               # Put the expiry time in the WHERE condition to avoid deleting a
-                                               # newly-inserted value
-                                               $db->delete( $row->tableName,
-                                                       array( 'keyname' => $key, 'exptime' => $row->exptime ),
-                                                       __METHOD__ );
+                                               $this->debug( "get: key has expired" );
                                        } else { // HIT
                                                $values[$key] = $this->unserialize( $db->decodeBlob( $row->value ) );
                                        }
@@ -546,7 +551,7 @@ class SqlBagOStuff extends BagOStuff {
        }
 
        protected function garbageCollect() {
-               if ( !$this->purgePeriod ) {
+               if ( !$this->purgePeriod || $this->slaveOnly ) {
                        // Disabled
                        return;
                }