/**
* 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
* @since 1.27
*/
class CategoryMembershipChangeJob extends Job {
- /** @var integer|null */
+ /** @var int|null */
private $ticket;
const ENQUEUE_FUDGE_SEC = 60;
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 );
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;
// 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 ) {
// 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