MediaWiki master
DeferredUpdatesScopeMediaWikiStack.php
Go to the documentation of this file.
1<?php
21namespace MediaWiki\Deferred;
22
25
37
38 private function areDatabaseTransactionsActive(): bool {
39 $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
40 if ( $lbFactory->hasTransactionRound()
41 || !$lbFactory->isReadyForRoundOperations()
42 ) {
43 return true;
44 }
45
46 foreach ( $lbFactory->getAllLBs() as $lb ) {
47 if ( $lb->hasPrimaryChanges() || $lb->explicitTrxActive() ) {
48 return true;
49 }
50 }
51
52 return false;
53 }
54
55 public function allowOpportunisticUpdates(): bool {
56 if ( MW_ENTRY_POINT !== 'cli' ) {
57 // In web req
58 return false;
59 }
60
61 // Run the updates only if they will have outer transaction scope
62 if ( $this->areDatabaseTransactionsActive() ) {
63 // transaction round is active or connection is not ready for commit()
64 return false;
65 }
66
67 return true;
68 }
69
70 public function queueDataUpdate( EnqueueableDataUpdate $update ): void {
71 $spec = $update->getAsJobSpecification();
72 $jobQueueGroupFactory = MediaWikiServices::getInstance()->getJobQueueGroupFactory();
73 $jobQueueGroupFactory->makeJobQueueGroup( $spec['domain'] )->push( $spec['job'] );
74 }
75
76 public function onRunUpdateStart( DeferrableUpdate $update ): void {
77 // Increment a counter metric
78 $type = get_class( $update )
79 . ( $update instanceof DeferrableCallback ? '_' . $update->getOrigin() : '' );
80 $httpMethod = MW_ENTRY_POINT === 'cli' ? 'cli' : strtolower( $_SERVER['REQUEST_METHOD'] ?? 'GET' );
81 $stats = MediaWikiServices::getInstance()->getStatsFactory();
82 $stats->getCounter( 'deferred_updates_total' )
83 ->setLabel( 'http_method', $httpMethod )
84 ->setLabel( 'type', $type )
85 ->copyToStatsdAt( "deferred_updates.$httpMethod.$type" )
86 ->increment();
87
88 $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
89 $ticket = $lbFactory->getEmptyTransactionTicket( __METHOD__ );
90 if ( !$ticket || $lbFactory->hasTransactionRound() ) {
91 throw new DBTransactionError( null, "A database transaction round is pending." );
92 }
93
94 if ( $update instanceof DataUpdate ) {
95 $update->setTransactionTicket( $ticket );
96 }
97
98 // Designate $update::doUpdate() as the transaction round owner
99 $fnameTrxOwner = ( $update instanceof DeferrableCallback )
100 ? $update->getOrigin()
101 : get_class( $update ) . '::doUpdate';
102
103 // Determine whether the transaction round will be explicit or implicit
104 $useExplicitTrxRound = !(
105 $update instanceof TransactionRoundAwareUpdate &&
106 $update->getTransactionRoundRequirement() == $update::TRX_ROUND_ABSENT
107 );
108 if ( $useExplicitTrxRound ) {
109 // Start a new explicit round
110 $lbFactory->beginPrimaryChanges( $fnameTrxOwner );
111 } else {
112 // Start a new implicit round
113 $lbFactory->commitPrimaryChanges( $fnameTrxOwner );
114 }
115 }
116
117 public function onRunUpdateEnd( DeferrableUpdate $update ): void {
118 $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
119
120 $fnameTrxOwner = ( $update instanceof DeferrableCallback )
121 ? $update->getOrigin()
122 : get_class( $update ) . '::doUpdate';
123
124 // Commit any pending changes from the explicit or implicit transaction round
125 $lbFactory->commitPrimaryChanges( $fnameTrxOwner );
126 }
127
128 public function onRunUpdateFailed( DeferrableUpdate $update ): void {
129 $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
130 $lbFactory->rollbackPrimaryChanges( __METHOD__ );
131 }
132}
133
135class_alias( DeferredUpdatesScopeMediaWikiStack::class, 'DeferredUpdatesScopeMediaWikiStack' );
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:81
const MW_ENTRY_POINT
Definition api.php:35
Abstract base class for update jobs that do something with some secondary data extracted from article...
This class decouples DeferredUpdates's awareness of MediaWikiServices to ease unit testing.
allowOpportunisticUpdates()
Whether DeferredUpdates::addUpdate() may run the update right away.
queueDataUpdate(EnqueueableDataUpdate $update)
Queue an EnqueueableDataUpdate as a job instead.
DeferredUpdates helper class for tracking DeferrableUpdate::doUpdate() nesting levels caused by neste...
Service locator for MediaWiki core services.
static getInstance()
Returns the global default instance of the top level service locator.
Callback wrapper that has an originating method.
Interface that deferrable updates should implement.
Interface that marks a DataUpdate as enqueuable via the JobQueue.