26 use Liuggio\StatsdClient\Factory\StatsdDataFactoryInterface;
43 const NORMAL_MAX_LAG = 10;
45 const LAG_WAIT_TIMEOUT = 15;
50 $this->removeDuplicates = (
56 $this->params += [
'causeAction' =>
'unknown',
'causeAgent' =>
'unknown' ];
60 $this->executionFlags |= self::JOB_NO_EXPLICIT_TRX_ROUND;
70 $job->command =
'refreshLinksPrioritized';
82 $job->command =
'refreshLinksDynamic';
91 if ( !empty( $this->params[
'recursive'] ) ) {
92 $services = MediaWikiServices::getInstance();
96 if ( !isset( $this->params[
'range'] ) ) {
97 $lbFactory = $services->getDBLoadBalancerFactory();
98 if ( !$lbFactory->waitForReplication( [
99 'domain' => $lbFactory->getLocalDomainID(),
100 'timeout' => self::LAG_WAIT_TIMEOUT
102 $stats = $services->getStatsdDataFactory();
103 $stats->increment(
'refreshlinks.lag_wait_failed' );
108 $extraParams[
'triggeredRecursive'] =
true;
110 $extraParams[
'causeAction'] = $this->params[
'causeAction'];
111 $extraParams[
'causeAgent'] = $this->params[
'causeAgent'];
116 $services->getMainConfig()->get(
'UpdateRowsPerJob' ),
118 [
'params' => $extraParams ]
122 } elseif ( isset( $this->params[
'pages'] ) ) {
123 foreach ( $this->params[
'pages'] as list( $ns, $dbKey ) ) {
145 $services = MediaWikiServices::getInstance();
146 $stats = $services->getStatsdDataFactory();
147 $renderer = $services->getRevisionRenderer();
148 $parserCache = $services->getParserCache();
149 $lbFactory = $services->getDBLoadBalancerFactory();
150 $ticket = $lbFactory->getEmptyTransactionTicket( __METHOD__ );
154 $page->loadPageData( WikiPage::READ_LATEST );
160 $dbw = $lbFactory->getMainLB()->getConnectionRef(
DB_MASTER );
163 if ( $scopedLock ===
null ) {
165 $this->
setLastError(
'LinksUpdate already running for this page, try again later.' );
166 $stats->increment(
'refreshlinks.lock_failure' );
172 $stats->increment(
'refreshlinks.update_skipped' );
178 $lbFactory->beginMasterChanges( __METHOD__ );
181 $lbFactory->commitMasterChanges( __METHOD__ );
188 $options[
'known-revision-output'] =
$output;
190 $page->doSecondaryDataUpdates( $options );
195 $lbFactory->commitAndWaitForReplication( __METHOD__, $ticket );
206 $rootTimestamp = $this->params[
'rootJobTimestamp'] ??
null;
207 if ( $rootTimestamp ===
null ) {
211 if ( !empty( $this->params[
'isOpportunistic'] ) ) {
214 $lagAwareTimestamp = $rootTimestamp;
219 wfTimestamp( TS_UNIX, $rootTimestamp ) + self::NORMAL_MAX_LAG
239 StatsdDataFactoryInterface $stats
247 if ( $cachedOutput ) {
248 return $cachedOutput;
255 [
'audience' => $revision::RAW ]
259 $output = $renderedRevision->getRevisionParserOutput( [
'generate-html' =>
false ] );
260 $output->setCacheTime( $parseTimestamp );
274 StatsdDataFactoryInterface $stats
282 $triggeringRevisionId = $this->params[
'triggeringRevisionId'] ??
null;
283 if ( $triggeringRevisionId && $triggeringRevisionId !== $latest ) {
285 $stats->increment(
'refreshlinks.rev_not_current' );
286 $this->
setLastError(
"Revision $triggeringRevisionId is not current" );
295 $stats->increment(
'refreshlinks.rev_not_found' );
296 $this->
setLastError(
"Revision not found for {$title->getPrefixedDBkey()}" );
299 } elseif ( $revision->getId() !== $latest || $revision->getPageId() !== $page->
getId() ) {
304 $stats->increment(
'refreshlinks.rev_not_current' );
305 $this->
setLastError(
"Revision {$revision->getId()} is not current" );
326 StatsdDataFactoryInterface $stats
328 $cachedOutput =
null;
332 $rootTimestamp = $this->params[
'rootJobTimestamp'] ??
null;
333 if ( $rootTimestamp !==
null ) {
334 $opportunistic = !empty( $this->params[
'isOpportunistic'] );
335 if ( $opportunistic ) {
338 $lagAwareTimestamp = $rootTimestamp;
343 wfTimestamp( TS_UNIX, $rootTimestamp ) + self::NORMAL_MAX_LAG
347 if ( $page->
getTouched() >= $rootTimestamp || $opportunistic ) {
355 $output->getCacheRevisionId() == $currentRevision->
getId() &&
356 $output->getCacheTime() >= $lagAwareTimestamp
363 if ( $cachedOutput ) {
364 $stats->increment(
'refreshlinks.parser_cached' );
366 $stats->increment(
'refreshlinks.parser_uncached' );
369 return $cachedOutput;
377 'recursive' => !empty( $this->params[
'useRecursiveLinksUpdate'] ),
379 'causeAction' => $this->params[
'causeAction'],
380 'causeAgent' => $this->params[
'causeAgent']
382 if ( !empty( $this->params[
'triggeringUser'] ) ) {
383 $userInfo = $this->params[
'triggeringUser'];
384 if ( $userInfo[
'userId'] ) {
396 $info = parent::getDeduplicationInfo();
397 unset( $info[
'causeAction'] );
398 unset( $info[
'causeAgent'] );
399 if ( is_array( $info[
'params'] ) ) {
402 if ( isset( $info[
'params'][
'pages'] ) ) {
403 unset( $info[
'namespace'] );
404 unset( $info[
'title'] );
412 if ( !empty( $this->params[
'recursive'] ) ) {
414 } elseif ( isset( $this->params[
'pages'] ) ) {
415 return count( $this->params[
'pages'] );