private $db;
/**
- * Constructor
- *
* @param Title $title Title of the page we're updating
* @param ParserOutput $parserOutput Output from a full parse of this page
* @param bool $recursive Queue jobs for recursive updates?
* Acquire a lock for performing link table updates for a page on a DB
*
* @param IDatabase $dbw
- * @param integer $pageId
+ * @param int $pageId
* @param string $why One of (job, atomicity)
* @return ScopedCallback
* @throws RuntimeException
* using the job queue.
*/
protected function queueRecursiveJobs() {
- self::queueRecursiveJobsForTable( $this->mTitle, 'templatelinks' );
+ $action = $this->getCauseAction();
+ $agent = $this->getCauseAgent();
+
+ self::queueRecursiveJobsForTable( $this->mTitle, 'templatelinks', $action, $agent );
if ( $this->mTitle->getNamespace() == NS_FILE ) {
// Process imagelinks in case the title is or was a redirect
- self::queueRecursiveJobsForTable( $this->mTitle, 'imagelinks' );
+ self::queueRecursiveJobsForTable( $this->mTitle, 'imagelinks', $action, $agent );
}
$bc = $this->mTitle->getBacklinkCache();
// Which ever runs first generally no-ops the other one.
$jobs = [];
foreach ( $bc->getCascadeProtectedLinks() as $title ) {
- $jobs[] = RefreshLinksJob::newPrioritized( $title, [] );
+ $jobs[] = RefreshLinksJob::newPrioritized(
+ $title,
+ [
+ 'causeAction' => $action,
+ 'causeAgent' => $agent
+ ]
+ );
}
JobQueueGroup::singleton()->push( $jobs );
}
*
* @param Title $title Title to do job for
* @param string $table Table to use (e.g. 'templatelinks')
+ * @param string $action Triggering action
+ * @param string $userName Triggering user name
*/
- public static function queueRecursiveJobsForTable( Title $title, $table ) {
+ public static function queueRecursiveJobsForTable(
+ Title $title, $table, $action = 'unknown', $userName = 'unknown'
+ ) {
if ( $title->getBacklinkCache()->hasLinks( $table ) ) {
$job = new RefreshLinksJob(
$title,
'recursive' => true,
] + Job::newRootJobParams( // "overall" refresh links job info
"refreshlinks:{$table}:{$title->getPrefixedText()}"
- )
+ ) + [ 'causeAction' => $action, 'causeAgent' => $userName ]
);
JobQueueGroup::singleton()->push( $job );
private function updateCategoryCounts( array $added, array $deleted ) {
global $wgUpdateRowsPerQuery;
+ if ( !$added && !$deleted ) {
+ return;
+ }
+
+ $domainId = $this->getDB()->getDomainID();
$wp = WikiPage::factory( $this->mTitle );
- $factory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
+ $lbf = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
+ // T163801: try to release any row locks to reduce contention
+ $lbf->commitAndWaitForReplication( __METHOD__, $this->ticket, [ 'domain' => $domainId ] );
foreach ( array_chunk( array_keys( $added ), $wgUpdateRowsPerQuery ) as $addBatch ) {
$wp->updateCategoryCounts( $addBatch, [], $this->mId );
- $factory->commitAndWaitForReplication(
- __METHOD__, $this->ticket, [ 'wiki' => $this->getDB()->getWikiID() ]
- );
+ $lbf->commitAndWaitForReplication(
+ __METHOD__, $this->ticket, [ 'domain' => $domainId ] );
}
foreach ( array_chunk( array_keys( $deleted ), $wgUpdateRowsPerQuery ) as $deleteBatch ) {
$wp->updateCategoryCounts( [], $deleteBatch, $this->mId );
- $factory->commitAndWaitForReplication(
- __METHOD__, $this->ticket, [ 'wiki' => $this->getDB()->getWikiID() ]
- );
+ $lbf->commitAndWaitForReplication(
+ __METHOD__, $this->ticket, [ 'domain' => $domainId ] );
}
}
private function incrTableUpdate( $table, $prefix, $deletions, $insertions ) {
$services = MediaWikiServices::getInstance();
$bSize = $services->getMainConfig()->get( 'UpdateRowsPerQuery' );
- $factory = $services->getDBLoadBalancerFactory();
+ $lbf = $services->getDBLoadBalancerFactory();
if ( $table === 'page_props' ) {
$fromField = 'pp_page';
$deleteWheres = []; // list of WHERE clause arrays for each DB delete() call
if ( $table === 'pagelinks' || $table === 'templatelinks' || $table === 'iwlinks' ) {
- $baseKey = ( $table === 'iwlinks' ) ? 'iwl_prefix' : "{$prefix}_namespace";
+ $baseKey = ( $table === 'iwlinks' ) ? 'iwl_prefix' : "{$prefix}_namespace";
$curBatchSize = 0;
$curDeletionBatch = [];
}
}
+ $domainId = $this->getDB()->getDomainID();
+
foreach ( $deleteWheres as $deleteWhere ) {
$this->getDB()->delete( $table, $deleteWhere, __METHOD__ );
- $factory->commitAndWaitForReplication(
- __METHOD__, $this->ticket, [ 'wiki' => $this->getDB()->getWikiID() ]
+ $lbf->commitAndWaitForReplication(
+ __METHOD__, $this->ticket, [ 'domain' => $domainId ]
);
}
$insertBatches = array_chunk( $insertions, $bSize );
foreach ( $insertBatches as $insertBatch ) {
$this->getDB()->insert( $table, $insertBatch, __METHOD__, 'IGNORE' );
- $factory->commitAndWaitForReplication(
- __METHOD__, $this->ticket, [ 'wiki' => $this->getDB()->getWikiID() ]
+ $lbf->commitAndWaitForReplication(
+ __METHOD__, $this->ticket, [ 'domain' => $domainId ]
);
}
foreach ( $diffs as $url => $dummy ) {
foreach ( wfMakeUrlIndexes( $url ) as $index ) {
$arr[] = [
- 'el_id' => $this->getDB()->nextSequenceValue( 'externallinks_el_id_seq' ),
'el_from' => $this->mId,
'el_to' => $url,
'el_index' => $index,
$inv = [ $inv ];
}
foreach ( $inv as $table ) {
- DeferredUpdates::addUpdate( new HTMLCacheUpdate( $this->mTitle, $table ) );
+ DeferredUpdates::addUpdate(
+ new HTMLCacheUpdate( $this->mTitle, $table, 'page-props' )
+ );
}
}
}
}
return [
- 'wiki' => $this->getDB()->getWikiID(),
+ 'wiki' => WikiMap::getWikiIdFromDomain( $this->getDB()->getDomainID() ),
'job' => new JobSpecification(
'refreshLinksPrioritized',
[
'useRecursiveLinksUpdate' => $this->mRecursive,
'triggeringUser' => $userInfo,
'triggeringRevisionId' => $triggeringRevisionId,
+ 'causeAction' => $this->getCauseAction(),
+ 'causeAgent' => $this->getCauseAgent()
],
[ 'removeDuplicates' => true ],
$this->getTitle()