MediaWiki master
ClearUserWatchlistJob.php
Go to the documentation of this file.
1<?php
2
3namespace MediaWiki\Watchlist;
4
10
24 public function __construct( array $params ) {
25 parent::__construct( 'clearUserWatchlist', $params );
26
27 $this->removeDuplicates = true;
28 }
29
36 public static function newForUser( UserIdentity $user, $maxWatchlistId ) {
37 return new self( [ 'userId' => $user->getId(), 'maxWatchlistId' => $maxWatchlistId ] );
38 }
39
41 public function run() {
42 $updateRowsPerQuery = MediaWikiServices::getInstance()->getMainConfig()->get(
44 $userId = $this->params['userId'];
45 $maxWatchlistId = $this->params['maxWatchlistId'];
46 $batchSize = $updateRowsPerQuery;
47
48 $loadBalancer = MediaWikiServices::getInstance()->getDBLoadBalancer();
49 $dbw = $loadBalancer->getConnection( DB_PRIMARY );
50 $dbr = $loadBalancer->getConnection( DB_REPLICA );
51
52 // Wait before lock to try to reduce time waiting in the lock.
53 if ( !$loadBalancer->waitForPrimaryPos( $dbr ) ) {
54 $this->setLastError( 'Timed out waiting for replica to catch up before lock' );
55 return false;
56 }
57
58 // Use a named lock so that jobs for this user see each others' changes
59 $lockKey = "{{$dbw->getDomainID()}}:ClearUserWatchlist:$userId"; // per-wiki
60 $scopedLock = $dbw->getScopedLockAndFlush( $lockKey, __METHOD__, 10 );
61 if ( !$scopedLock ) {
62 $this->setLastError( "Could not acquire lock '$lockKey'" );
63 return false;
64 }
65
66 if ( !$loadBalancer->waitForPrimaryPos( $dbr ) ) {
67 $this->setLastError( 'Timed out waiting for replica to catch up within lock' );
68 return false;
69 }
70
71 // Clear any stale REPEATABLE-READ snapshot
72 $dbr->flushSnapshot( __METHOD__ );
73
74 $watchlistIds = $dbr->newSelectQueryBuilder()
75 ->select( 'wl_id' )
76 ->from( 'watchlist' )
77 ->where( [ 'wl_user' => $userId ] )
78 ->andWhere( $dbr->expr( 'wl_id', '<=', $maxWatchlistId ) )
79 ->limit( $batchSize )
80 ->caller( __METHOD__ )->fetchFieldValues();
81 if ( count( $watchlistIds ) == 0 ) {
82 return true;
83 }
84
85 $dbw->newDeleteQueryBuilder()
86 ->deleteFrom( 'watchlist' )
87 ->where( [ 'wl_id' => $watchlistIds ] )
88 ->caller( __METHOD__ )->execute();
90 $dbw->newDeleteQueryBuilder()
91 ->deleteFrom( 'watchlist_expiry' )
92 ->where( [ 'we_item' => $watchlistIds ] )
93 ->caller( __METHOD__ )->execute();
94 }
95
96 // Commit changes and remove lock before inserting next job.
97 $lbf = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
98 $lbf->commitPrimaryChanges( __METHOD__ );
99 unset( $scopedLock );
100
101 if ( count( $watchlistIds ) === (int)$batchSize ) {
102 // Until we get less results than the limit, recursively push
103 // the same job again.
104 MediaWikiServices::getInstance()->getJobQueueGroup()->push( new self( $this->getParams() ) );
105 }
106
107 return true;
108 }
109
111 public function getDeduplicationInfo() {
112 $info = parent::getDeduplicationInfo();
113 // This job never has a namespace or title so we can't use it for deduplication
114 unset( $info['namespace'] );
115 unset( $info['title'] );
116 return $info;
117 }
118
119}
121class_alias( ClearUserWatchlistJob::class, 'ClearUserWatchlistJob' );
const DB_REPLICA
Definition defines.php:26
const DB_PRIMARY
Definition defines.php:28
Describe and execute a background job.
Definition Job.php:28
array $params
Array of job parameters.
Definition Job.php:33
setLastError( $error)
Definition Job.php:425
getParams()
array Parameters that specify sources, targets, and options for execution
Definition Job.php:144
A class containing constants representing the names of configuration variables.
const UpdateRowsPerQuery
Name constant for the UpdateRowsPerQuery setting, for use with Config::get()
const WatchlistExpiry
Name constant for the WatchlistExpiry setting, for use with Config::get()
Service locator for MediaWiki core services.
static getInstance()
Returns the global default instance of the top level service locator.
Job to clear a users watchlist in batches.
getDeduplicationInfo()
Subclasses may need to override this to make duplication detection work.The resulting map conveys eve...
run()
Run the job.If this method returns false or completes exceptionally, the job runner will retry execut...
static newForUser(UserIdentity $user, $maxWatchlistId)
Interface for generic jobs only uses the parameters field and are JSON serializable.
Interface for objects representing user identity.
getId( $wikiId=self::LOCAL)