Merge "Unbreak the DB updater by removing transaction from doUpdates()"
[lhc/web/wiklou.git] / includes / deferred / LinksDeletionUpdate.php
index c227ecd..0009781 100644 (file)
@@ -27,13 +27,16 @@ class LinksDeletionUpdate extends SqlDataUpdate implements EnqueueableDataUpdate
        protected $page;
        /** @var integer */
        protected $pageId;
+       /** @var string */
+       protected $timestamp;
 
        /**
         * @param WikiPage $page Page we are updating
         * @param integer|null $pageId ID of the page we are updating [optional]
+        * @param string|null $timestamp TS_MW timestamp of deletion
         * @throws MWException
         */
-       function __construct( WikiPage $page, $pageId = null ) {
+       function __construct( WikiPage $page, $pageId = null, $timestamp = null ) {
                parent::__construct( false ); // no implicit transaction
 
                $this->page = $page;
@@ -44,6 +47,8 @@ class LinksDeletionUpdate extends SqlDataUpdate implements EnqueueableDataUpdate
                } else {
                        throw new InvalidArgumentException( "Page ID not known. Page doesn't exist?" );
                }
+
+               $this->timestamp = $timestamp ?: wfTimestampNow();
        }
 
        public function doUpdate() {
@@ -56,6 +61,8 @@ class LinksDeletionUpdate extends SqlDataUpdate implements EnqueueableDataUpdate
                // This handles the case when updates have to batched into several COMMITs.
                $scopedLock = LinksUpdate::acquirePageLock( $this->mDb, $id );
 
+               $title = $this->page->getTitle();
+
                // Delete restrictions for it
                $this->mDb->delete( 'page_restrictions', [ 'pr_page' => $id ], __METHOD__ );
 
@@ -68,13 +75,27 @@ class LinksDeletionUpdate extends SqlDataUpdate implements EnqueueableDataUpdate
                );
                $catBatches = array_chunk( $cats, $batchSize );
                foreach ( $catBatches as $catBatch ) {
-                       $this->page->updateCategoryCounts( [], $catBatch );
+                       $this->page->updateCategoryCounts( [], $catBatch, $id );
                        if ( count( $catBatches ) > 1 ) {
                                $this->mDb->commit( __METHOD__, 'flush' );
                                wfGetLBFactory()->waitForReplication( [ 'wiki' => $this->mDb->getWikiID() ] );
                        }
                }
 
+               // Refresh the category table entry if it seems to have no pages. Check
+               // master for the most up-to-date cat_pages count.
+               if ( $title->getNamespace() === NS_CATEGORY ) {
+                       $row = $this->mDb->selectRow(
+                               'category',
+                               [ 'cat_id', 'cat_title', 'cat_pages', 'cat_subcats', 'cat_files' ],
+                               [ 'cat_title' => $title->getDBkey(), 'cat_pages <= 0' ],
+                               __METHOD__
+                       );
+                       if ( $row ) {
+                               $cat = Category::newFromRow( $row, $title )->refreshCounts();
+                       }
+               }
+
                // If using cascading deletes, we can skip some explicit deletes
                if ( !$this->mDb->cascadingDeletes() ) {
                        // Delete outgoing links
@@ -127,7 +148,6 @@ class LinksDeletionUpdate extends SqlDataUpdate implements EnqueueableDataUpdate
 
                // If using cleanup triggers, we can skip some manual deletes
                if ( !$this->mDb->cleanupTriggers() ) {
-                       $title = $this->page->getTitle();
                        // Find recentchanges entries to clean up...
                        $rcIdsForTitle = $this->mDb->selectFieldValues(
                                'recentchanges',
@@ -135,7 +155,9 @@ class LinksDeletionUpdate extends SqlDataUpdate implements EnqueueableDataUpdate
                                [
                                        'rc_type != ' . RC_LOG,
                                        'rc_namespace' => $title->getNamespace(),
-                                       'rc_title' => $title->getDBkey()
+                                       'rc_title' => $title->getDBkey(),
+                                       'rc_timestamp < ' .
+                                               $this->mDb->addQuotes( $this->mDb->timestamp( $this->timestamp ) )
                                ],
                                __METHOD__
                        );
@@ -157,10 +179,8 @@ class LinksDeletionUpdate extends SqlDataUpdate implements EnqueueableDataUpdate
                        }
                }
 
-               $this->mDb->onTransactionIdle( function() use ( &$scopedLock ) {
-                       // Release the lock *after* the final COMMIT for correctness
-                       ScopedCallback::consume( $scopedLock );
-               } );
+               // Commit and release the lock
+               ScopedCallback::consume( $scopedLock );
        }
 
        private function batchDeleteByPK( $table, array $conds, array $pk, $bSize ) {
@@ -188,7 +208,7 @@ class LinksDeletionUpdate extends SqlDataUpdate implements EnqueueableDataUpdate
                        'wiki' => $this->mDb->getWikiID(),
                        'job'  => new JobSpecification(
                                'deleteLinks',
-                               [ 'pageId' => $this->pageId ],
+                               [ 'pageId' => $this->pageId, 'timestamp' => $this->timestamp ],
                                [ 'removeDuplicates' => true ],
                                $this->page->getTitle()
                        )