// Make sure all links update threads see the changes of each other.
// This handles the case when updates have to batched into several COMMITs.
$scopedLock = LinksUpdate::acquirePageLock( $this->getDB(), $id );
+ if ( !$scopedLock ) {
+ throw new RuntimeException( "Could not acquire lock for page ID '{$id}'." );
+ }
}
$title = $this->page->getTitle();
*/
use Wikimedia\Rdbms\IDatabase;
+use MediaWiki\Logger\LoggerFactory;
use MediaWiki\MediaWikiServices;
use Wikimedia\ScopedCallback;
// Make sure all links update threads see the changes of each other.
// This handles the case when updates have to batched into several COMMITs.
$scopedLock = self::acquirePageLock( $this->getDB(), $this->mId );
+ if ( !$scopedLock ) {
+ throw new RuntimeException( "Could not acquire lock for page ID '{$this->mId}'." );
+ }
}
// Avoid PHP 7.1 warning from passing $this by reference
* @param IDatabase $dbw
* @param int $pageId
* @param string $why One of (job, atomicity)
- * @return ScopedCallback
- * @throws RuntimeException
+ * @return ScopedCallback|null
* @since 1.27
*/
public static function acquirePageLock( IDatabase $dbw, $pageId, $why = 'atomicity' ) {
$key = "LinksUpdate:$why:pageid:$pageId";
$scopedLock = $dbw->getScopedLockAndFlush( $key, __METHOD__, 15 );
if ( !$scopedLock ) {
- throw new RuntimeException( "Could not acquire lock '$key'." );
+ $logger = LoggerFactory::getInstance( 'SecondaryDataUpdate' );
+ $logger->info( "Could not acquire lock '{key}' for page ID '{page_id}'.", [
+ 'key' => $key,
+ 'page_id' => $pageId,
+ ] );
+ return null;
}
return $scopedLock;
// Serialize links updates by page ID so they see each others' changes
$scopedLock = LinksUpdate::acquirePageLock( wfGetDB( DB_MASTER ), $pageId, 'job' );
+ if ( $scopedLock === null ) {
+ $this->setLastError( 'LinksUpdate already running for this page, try again later.' );
+ return false;
+ }
if ( WikiPage::newFromID( $pageId, WikiPage::READ_LATEST ) ) {
// The page was restored somehow or something went wrong
$dbw = $lbFactory->getMainLB()->getConnection( DB_MASTER );
/** @noinspection PhpUnusedLocalVariableInspection */
$scopedLock = LinksUpdate::acquirePageLock( $dbw, $page->getId(), 'job' );
+ if ( $scopedLock === null ) {
+ // Another job is already updating the page, likely for an older revision (T170596).
+ $this->setLastError( 'LinksUpdate already running for this page, try again later.' );
+ return false;
+ }
// Get the latest ID *after* acquirePageLock() flushed the transaction.
// This is used to detect edits/moves after loadPageData() but before the scope lock.
// The works around the chicken/egg problem of determining the scope lock key.