Aaron Schulz has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/264579

Change subject: Add IDatabase::getScopedLockAndFlush() method
......................................................................

Add IDatabase::getScopedLockAndFlush() method

This method is less manual and avoids the usual pitfalls of
not unlocking for a return statement or not flushing out any
prior transaction.

Change-Id: Ib1681244767de860105a68210e181e2f024ee525
---
M includes/db/DBConnRef.php
M includes/db/Database.php
M includes/db/IDatabase.php
M includes/jobqueue/jobs/CategoryMembershipChangeJob.php
4 files changed, 43 insertions(+), 14 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core 
refs/changes/79/264579/1

diff --git a/includes/db/DBConnRef.php b/includes/db/DBConnRef.php
index f09de4f..264ee11 100644
--- a/includes/db/DBConnRef.php
+++ b/includes/db/DBConnRef.php
@@ -505,6 +505,10 @@
                return $this->__call( __FUNCTION__, func_get_args() );
        }
 
+       public function getScopedLockAndFlush( $lockKey, $fname, $timeout ) {
+               return $this->__call( __FUNCTION__, func_get_args() );
+       }
+
        public function namedLocksEnqueue() {
                return $this->__call( __FUNCTION__, func_get_args() );
        }
diff --git a/includes/db/Database.php b/includes/db/Database.php
index 1835958..dc1570e 100644
--- a/includes/db/Database.php
+++ b/includes/db/Database.php
@@ -3167,6 +3167,21 @@
                return true;
        }
 
+       public function getScopedLockAndFlush( $lockKey, $fname, $timeout ) {
+               if ( !$this->lock( $lockKey, $fname, $timeout ) ) {
+                       return null;
+               }
+
+               $that = $this;
+               $unlocker = new ScopedCallback( function () use ( $that, 
$lockKey, $fname ) {
+                       $that->unlock( $lockKey, $fname );
+               } );
+
+               $this->commit( __METHOD__, 'flush' );
+
+               return $unlocker;
+       }
+
        public function namedLocksEnqueue() {
                return false;
        }
diff --git a/includes/db/IDatabase.php b/includes/db/IDatabase.php
index c72218a..e708d93 100644
--- a/includes/db/IDatabase.php
+++ b/includes/db/IDatabase.php
@@ -1489,8 +1489,8 @@
         * Named locks are not related to transactions
         *
         * @param string $lockName Name of lock to aquire
-        * @param string $method Name of method calling us
-        * @param int $timeout
+        * @param string $method Name of the calling method
+        * @param int $timeout Acquisition timeout in seconds
         * @return bool
         */
        public function lock( $lockName, $method, $timeout = 5 );
@@ -1501,7 +1501,7 @@
         * Named locks are not related to transactions
         *
         * @param string $lockName Name of lock to release
-        * @param string $method Name of method calling us
+        * @param string $method Name of the calling method
         *
         * @return int Returns 1 if the lock was released, 0 if the lock was 
not established
         * by this thread (in which case the lock is not released), and NULL if 
the named
@@ -1510,6 +1510,25 @@
        public function unlock( $lockName, $method );
 
        /**
+        * Acquire a named lock, flush any transaction, and return an RAII 
style unlocker object
+        *
+        * This is suitiable for transactions that need to be serialized using 
cooperative locks,
+        * where each transaction can see each others' changes. Any transaction 
is flushed to clear
+        * out stale REPEATABLE-READ snapshot data. Once the returned object 
falls out of PHP scope,
+        * the lock will be released.
+        *
+        * If the lock acquisition failed, then no transaction flush happens, 
and null is returned.
+        *
+        * @param string $lockKey Name of lock to release
+        * @param string $fname Name of the calling method
+        * @param int $timeout Acquisition timeout in seconds
+        * @return ScopedCallback|null
+        * @throws DBUnexpectedError
+        * @since 1.27
+        */
+       public function getScopedLockAndFlush( $lockKey, $fname, $timeout );
+
+       /**
         * Check to see if a named lock used by lock() use blocking queues
         *
         * @return bool
diff --git a/includes/jobqueue/jobs/CategoryMembershipChangeJob.php 
b/includes/jobqueue/jobs/CategoryMembershipChangeJob.php
index c9e20a9..3323850 100644
--- a/includes/jobqueue/jobs/CategoryMembershipChangeJob.php
+++ b/includes/jobqueue/jobs/CategoryMembershipChangeJob.php
@@ -51,19 +51,12 @@
                $dbw = wfGetDB( DB_MASTER );
 
                // Use a named lock so that jobs for this page see each others' 
changes
-               $fname = __METHOD__;
                $lockKey = "CategoryMembershipUpdates:{$page->getId()}";
-               if ( !$dbw->lock( $lockKey, $fname, 10 ) ) {
+               $scopedLock = $dbw->getScopedLockAndFlush( $lockKey, 
__METHOD__, 10 );
+               if ( !$scopedLock ) {
                        $this->setLastError( "Could not acquire lock 
'$lockKey'" );
                        return false;
                }
-
-               $unlocker = new ScopedCallback( function () use ( $dbw, 
$lockKey, $fname ) {
-                       $dbw->unlock( $lockKey, $fname );
-               } );
-
-               // Sanity: clear any DB transaction snapshot
-               $dbw->commit( __METHOD__, 'flush' );
 
                $cutoffUnix = wfTimestamp( TS_UNIX, 
$this->params['revTimestamp'] );
                // Using ENQUEUE_FUDGE_SEC handles jobs inserted out of 
revision order due to the delay
@@ -120,8 +113,6 @@
                foreach ( $res as $row ) {
                        $this->notifyUpdatesForRevision( $page, 
Revision::newFromRow( $row ) );
                }
-
-               ScopedCallback::consume( $unlocker );
 
                return true;
        }

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ib1681244767de860105a68210e181e2f024ee525
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Aaron Schulz <[email protected]>

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

Reply via email to