objectcache: make BagOStuff::mergeViaLock() timeout more sensible
authorAaron Schulz <aschulz@wikimedia.org>
Wed, 11 Jul 2018 22:54:24 +0000 (23:54 +0100)
committerAaron Schulz <aschulz@wikimedia.org>
Thu, 12 Jul 2018 15:02:38 +0000 (16:02 +0100)
Interpret "1 attempt" as non-blocking and use 3 seconds otherwise
(instead of 6 seconds). This means that the WAN cache merge call
does not block.

Bug: T198239
Change-Id: Ieb194a949f18785c2cc9dd20fdc4d2e3fed51abf

includes/libs/objectcache/BagOStuff.php
tests/phpunit/includes/libs/objectcache/BagOStuffTest.php

index 0100fb2..782f4c6 100644 (file)
@@ -371,7 +371,13 @@ abstract class BagOStuff implements IExpiringStore, LoggerAwareInterface {
         * @return bool Success
         */
        protected function mergeViaLock( $key, $callback, $exptime = 0, $attempts = 10, $flags = 0 ) {
-               if ( !$this->lock( $key, 6 ) ) {
+               if ( $attempts <= 1 ) {
+                       $timeout = 0; // clearly intended to be "non-blocking"
+               } else {
+                       $timeout = 3;
+               }
+
+               if ( !$this->lock( $key, $timeout ) ) {
                        return false;
                }
 
index b6709a0..f0f55fb 100644 (file)
@@ -68,8 +68,11 @@ class BagOStuffTest extends MediaWikiTestCase {
         * @covers BagOStuff::mergeViaCas
         */
        public function testMerge() {
+               $calls = 0;
                $key = $this->cache->makeKey( self::TEST_KEY );
-               $callback = function ( BagOStuff $cache, $key, $oldVal ) {
+               $callback = function ( BagOStuff $cache, $key, $oldVal ) use ( &$calls ) {
+                       ++$calls;
+
                        return ( $oldVal === false ) ? 'merged' : $oldVal . 'merged';
                };
 
@@ -82,6 +85,12 @@ class BagOStuffTest extends MediaWikiTestCase {
                $merged = $this->cache->merge( $key, $callback, 5 );
                $this->assertTrue( $merged );
                $this->assertEquals( 'mergedmerged', $this->cache->get( $key ) );
+
+               $calls = 0;
+               $this->cache->lock( $key );
+               $this->assertFalse( $this->cache->merge( $key, $callback, 1 ), 'Non-blocking merge' );
+               $this->cache->unlock( $key );
+               $this->assertEquals( 0, $calls );
        }
 
        /**
@@ -305,4 +314,21 @@ class BagOStuffTest extends MediaWikiTestCase {
 
                DeferredUpdates::doUpdates();
        }
+
+       /**
+        * @covers BagOStuff::lock()
+        * @covers BagOStuff::unlock()
+        */
+       public function testLocking() {
+               $key = 'test';
+               $this->assertTrue( $this->cache->lock( $key ) );
+               $this->assertFalse( $this->cache->lock( $key ) );
+               $this->assertTrue( $this->cache->unlock( $key ) );
+
+               $key2 = 'test2';
+               $this->assertTrue( $this->cache->lock( $key2, 5, 5, 'rclass' ) );
+               $this->assertTrue( $this->cache->lock( $key2, 5, 5, 'rclass' ) );
+               $this->assertTrue( $this->cache->unlock( $key2 ) );
+               $this->assertTrue( $this->cache->unlock( $key2 ) );
+       }
 }