CentralIdLookup: Add @since to factoryNonLocal()
[mediawiki.git] / includes / deferred / WANCacheReapUpdate.php
blob4acab9548446e56e153279e5934438cb7ea918f5
1 <?php
3 use MediaWiki\Linker\LinkTarget;
4 use MediaWiki\MediaWikiServices;
5 use Psr\Log\LoggerInterface;
6 use Wikimedia\Rdbms\IDatabase;
8 /**
9 * Class for fixing stale WANObjectCache keys using a purge event source
11 * This is useful for expiring keys that missed fire-and-forget purges. This uses the
12 * recentchanges table as a reliable stream to make certain keys reach consistency
13 * as soon as the underlying replica database catches up. These means that critical
14 * keys will not escape getting purged simply due to brief hiccups in the network,
15 * which are more prone to happen across datacenters.
17 * ----
18 * "I was trying to cheat death. I was only trying to surmount for a little while the
19 * darkness that all my life I surely knew was going to come rolling in on me some day
20 * and obliterate me. I was only to stay alive a little brief while longer, after I was
21 * already gone. To stay in the light, to be with the living, a little while past my time."
22 * -- Notes for "Blues of a Lifetime", by [[Cornell Woolrich]]
24 * @since 1.28
26 class WANCacheReapUpdate implements DeferrableUpdate {
27 /** @var IDatabase */
28 private $db;
29 /** @var LoggerInterface */
30 private $logger;
32 /**
33 * @param IDatabase $db
34 * @param LoggerInterface $logger
36 public function __construct( IDatabase $db, LoggerInterface $logger ) {
37 $this->db = $db;
38 $this->logger = $logger;
41 public function doUpdate() {
42 $reaper = new WANObjectCacheReaper(
43 MediaWikiServices::getInstance()->getMainWANObjectCache(),
44 ObjectCache::getLocalClusterInstance(),
45 [ $this, 'getTitleChangeEvents' ],
46 [ $this, 'getEventAffectedKeys' ],
48 'channel' => 'table:recentchanges:' . $this->db->getDomainID(),
49 'logger' => $this->logger
53 $reaper->invoke( 100 );
56 /**
57 * @see WANObjectCacheRepear
59 * @param int $start
60 * @param int $id
61 * @param int $end
62 * @param int $limit
63 * @return TitleValue[]
65 public function getTitleChangeEvents( $start, $id, $end, $limit ) {
66 $db = $this->db;
67 $encStart = $db->addQuotes( $db->timestamp( $start ) );
68 $encEnd = $db->addQuotes( $db->timestamp( $end ) );
69 $id = (int)$id; // cast NULL => 0 since rc_id is an integer
71 $res = $db->select(
72 'recentchanges',
73 [ 'rc_namespace', 'rc_title', 'rc_timestamp', 'rc_id' ],
75 $db->makeList( [
76 "rc_timestamp > $encStart",
77 "rc_timestamp = $encStart AND rc_id > " . $db->addQuotes( $id )
78 ], LIST_OR ),
79 "rc_timestamp < $encEnd"
81 __METHOD__,
82 [ 'ORDER BY' => [ 'rc_timestamp ASC', 'rc_id ASC' ], 'LIMIT' => $limit ]
85 $events = [];
86 foreach ( $res as $row ) {
87 $events[] = [
88 'id' => (int)$row->rc_id,
89 'pos' => (int)wfTimestamp( TS_UNIX, $row->rc_timestamp ),
90 'item' => new TitleValue( (int)$row->rc_namespace, $row->rc_title )
94 return $events;
97 /**
98 * Gets a list of important cache keys associated with a title
100 * @see WANObjectCacheRepear
101 * @param WANObjectCache $cache
102 * @param LinkTarget $t
103 * @return string[]
105 public function getEventAffectedKeys( WANObjectCache $cache, LinkTarget $t ) {
106 /** @var WikiPage[]|LocalFile[]|User[] $entities */
107 $entities = [];
109 // You can't create a WikiPage for special pages (-1) or other virtual
110 // namespaces, but special pages do appear in RC sometimes, e.g. for logs
111 // of AbuseFilter filter changes.
112 if ( $t->getNamespace() >= 0 ) {
113 $entities[] = WikiPage::factory( Title::newFromLinkTarget( $t ) );
116 if ( $t->inNamespace( NS_FILE ) ) {
117 $entities[] = MediaWikiServices::getInstance()->getRepoGroup()->getLocalRepo()
118 ->newFile( $t->getText() );
120 if ( $t->inNamespace( NS_USER ) ) {
121 $entities[] = User::newFromName( $t->getText(), false );
124 $keys = [];
125 foreach ( $entities as $entity ) {
126 if ( $entity ) {
127 $keys = array_merge( $keys, $entity->getMutableCacheKeys( $cache ) );
130 if ( $keys ) {
131 $this->logger->debug( __CLASS__ . ': got key(s) ' . implode( ', ', $keys ) );
134 return $keys;