Merge "Rewrite pref cleanup script"
[lhc/web/wiklou.git] / includes / jobqueue / jobs / CategoryMembershipChangeJob.php
index 3907fc6..16640be 100644 (file)
@@ -25,6 +25,8 @@ use Wikimedia\Rdbms\LBFactory;
 /**
  * Job to add recent change entries mentioning category membership changes
  *
+ * This allows users to easily scan categories for recent page membership changes
+ *
  * Parameters include:
  *   - pageId : page ID
  *   - revTimestamp : timestamp of the triggering revision
@@ -59,6 +61,13 @@ class CategoryMembershipChangeJob extends Job {
                        return false; // deleted?
                }
 
+               // Cut down on the time spent in safeWaitForMasterPos() in the critical section
+               $dbr = $lb->getConnection( DB_REPLICA, [ 'recentchanges' ] );
+               if ( !$lb->safeWaitForMasterPos( $dbr ) ) {
+                       $this->setLastError( "Timed out while pre-waiting for replica DB to catch up" );
+                       return false;
+               }
+
                // Use a named lock so that jobs for this page see each others' changes
                $lockKey = "CategoryMembershipUpdates:{$page->getId()}";
                $scopedLock = $dbw->getScopedLockAndFlush( $lockKey, __METHOD__, 3 );
@@ -67,8 +76,7 @@ class CategoryMembershipChangeJob extends Job {
                        return false;
                }
 
-               $dbr = $lb->getConnection( DB_REPLICA, [ 'recentchanges' ] );
-               // Wait till the replica DB is caught up so that jobs for this page see each others' changes
+               // Wait till replica DB is caught up so that jobs for this page see each others' changes
                if ( !$lb->safeWaitForMasterPos( $dbr ) ) {
                        $this->setLastError( "Timed out while waiting for replica DB to catch up" );
                        return false;
@@ -81,28 +89,28 @@ class CategoryMembershipChangeJob extends Job {
                // between COMMIT and actual enqueueing of the CategoryMembershipChangeJob job.
                $cutoffUnix -= self::ENQUEUE_FUDGE_SEC;
 
-               // Get the newest revision that has a SRC_CATEGORIZE row...
+               // Get the newest page revision that has a SRC_CATEGORIZE row.
+               // Assume that category changes before it were already handled.
                $row = $dbr->selectRow(
-                       [ 'revision', 'recentchanges' ],
+                       'revision',
                        [ 'rev_timestamp', 'rev_id' ],
                        [
                                'rev_page' => $page->getId(),
-                               'rev_timestamp >= ' . $dbr->addQuotes( $dbr->timestamp( $cutoffUnix ) )
-                       ],
-                       __METHOD__,
-                       [ 'ORDER BY' => 'rev_timestamp DESC, rev_id DESC' ],
-                       [
-                               'recentchanges' => [
-                                       'INNER JOIN',
+                               'rev_timestamp >= ' . $dbr->addQuotes( $dbr->timestamp( $cutoffUnix ) ),
+                               'EXISTS (' . $dbr->selectSQLText(
+                                       'recentchanges',
+                                       '1',
                                        [
                                                'rc_this_oldid = rev_id',
                                                'rc_source' => RecentChange::SRC_CATEGORIZE,
                                                // Allow rc_cur_id or rc_timestamp index usage
                                                'rc_cur_id = rev_page',
-                                               'rc_timestamp >= rev_timestamp'
+                                               'rc_timestamp = rev_timestamp'
                                        ]
-                               ]
-                       ]
+                               ) . ')'
+                       ],
+                       __METHOD__,
+                       [ 'ORDER BY' => 'rev_timestamp DESC, rev_id DESC' ]
                );
                // Only consider revisions newer than any such revision
                if ( $row ) {
@@ -115,16 +123,18 @@ class CategoryMembershipChangeJob extends Job {
                // Find revisions to this page made around and after this revision which lack category
                // notifications in recent changes. This lets jobs pick up were the last one left off.
                $encCutoff = $dbr->addQuotes( $dbr->timestamp( $cutoffUnix ) );
+               $revQuery = Revision::getQueryInfo();
                $res = $dbr->select(
-                       'revision',
-                       Revision::selectFields(),
+                       $revQuery['tables'],
+                       $revQuery['fields'],
                        [
                                'rev_page' => $page->getId(),
                                "rev_timestamp > $encCutoff" .
                                        " OR (rev_timestamp = $encCutoff AND rev_id > $lastRevId)"
                        ],
                        __METHOD__,
-                       [ 'ORDER BY' => 'rev_timestamp ASC, rev_id ASC' ]
+                       [ 'ORDER BY' => 'rev_timestamp ASC, rev_id ASC' ],
+                       $revQuery['joins']
                );
 
                // Apply all category updates in revision timestamp order