MediaWiki  master
DeferredUpdates Class Reference

Class for managing the deferred updates. More...

Collaboration diagram for DeferredUpdates:

Static Public Member Functions

static addCallableUpdate ( $callable, $stage=self::POSTSEND, $dbw=null)
 Add a callable update. More...
 
static addUpdate (DeferrableUpdate $update, $stage=self::POSTSEND)
 Add an update to the deferred update queue for execution at the appropriate time. More...
 
static attemptUpdate (DeferrableUpdate $update, ILBFactory $lbFactory)
 Attempt to run an update with the appropriate transaction round state it expects. More...
 
static clearPendingUpdates ()
 Clear all pending updates without performing them. More...
 
static doUpdates ( $mode='run', $stage=self::ALL)
 Consume the list of deferred updates and execute them. More...
 
static getPendingUpdates ( $stage=self::ALL)
 Get the list of pending updates in the top-queues. More...
 
static pendingUpdatesCount ()
 Get the number of currently enqueued updates in the top-queues. More...
 
static tryOpportunisticExecute ( $mode='run')
 Run all deferred updates immediately if there are no DB writes active. More...
 

Public Attributes

const ALL = 0
 
const POSTSEND = 2
 
const PRESEND = 1
 

Static Protected Member Functions

static handleUpdateQueue (array &$queue, $mode, $stage)
 Immediately run or enqueue a list of updates. More...
 

Static Private Member Functions

static areDatabaseTransactionsActive ()
 
static enqueueUpdates (array $updates)
 Enqueue a job for each EnqueueableDataUpdate item and return the other items. More...
 
static jobify (EnqueueableDataUpdate $update, LBFactory $lbFactory, LoggerInterface $logger, StatsdDataFactoryInterface $stats, $httpMethod)
 Push a update into the job queue system and catch/log any exceptions. More...
 
static push (array &$queue, DeferrableUpdate $update)
 
static run (DeferrableUpdate $update, LBFactory $lbFactory, LoggerInterface $logger, StatsdDataFactoryInterface $stats, $httpMethod)
 Run an update, and, if an error was thrown, catch/log it and fallback to the job queue. More...
 

Private Attributes

const BIG_QUEUE_SIZE = 100
 

Static Private Attributes

static array[] $executionStack = []
 Execution stack of currently running updates -var array<array{stage:int,update:DeferrableUpdate,subqueue:DeferrableUpdate[]}> More...
 
static DeferrableUpdate[] $postSendUpdates = []
 Updates to be deferred until just after HTTP response emission. More...
 
static DeferrableUpdate[] $preSendUpdates = []
 Updates to be deferred until just before HTTP response emission. More...
 

Detailed Description

Class for managing the deferred updates.

In web request mode, deferred updates can be run at the end of the request, either before or after the HTTP response has been sent. In either case, they run after the DB commit step. If an update runs after the response is sent, it will not block clients. If sent before, it will run synchronously. These two modes are defined via PRESEND and POSTSEND constants, the latter being the default for addUpdate() and addCallableUpdate().

Updates that work through this system will be more likely to complete by the time the client makes their next request after this one than with the JobQueue system.

In CLI mode, deferred updates will run:

  • a) During DeferredUpdates::addUpdate if no LBFactory DB handles have writes pending
  • b) On commit of an LBFactory DB handle if no other such handles have writes pending
  • c) During an LBFactory::waitForReplication call if no LBFactory DBs have writes pending
  • d) When the queue is large and an LBFactory DB handle commits (EnqueueableDataUpdate only)
  • e) At the completion of Maintenance::execute()
See also
Maintenance::setLBFactoryTriggers

When updates are deferred, they go into one two FIFO "top-queues" (one for pre-send and one for post-send). Updates enqueued during doUpdate() of a "top" update go into the "sub-queue" for that update. After that method finishes, the sub-queue is run until drained. This continues for each top-queue job until the entire top queue is drained. This happens for the pre-send top-queue, and later on, the post-send top-queue, in doUpdates().

Since
1.19

Definition at line 62 of file DeferredUpdates.php.

Member Function Documentation

◆ addCallableUpdate()

static DeferredUpdates::addCallableUpdate (   $callable,
  $stage = self::POSTSEND,
  $dbw = null 
)
static

Add a callable update.

In a lot of cases, we just need a callback/closure, defining a new DeferrableUpdate object is not necessary

See also
MWCallableUpdate::__construct()
Parameters
callable$callable
int$stageDeferredUpdates constant (PRESEND or POSTSEND) (since 1.27)
IDatabase | IDatabase[] | null$dbwAbort if this DB is rolled back optional

Definition at line 145 of file DeferredUpdates.php.

References addUpdate(), and wfGetCaller().

Referenced by MediaWiki\User\UserGroupManager\addUserToGroup(), MediaWiki\Auth\AuthManager\autoCreateUser(), MediaWiki\Auth\LocalPasswordPrimaryAuthenticationProvider\beginPrimaryAuthentication(), SpecialEditWatchlist\cleanupWatchlist(), MediaWiki\User\WatchlistNotificationManager\clearTitleUserNotifications(), FileBackendMultiWrite\doDirectoryOp(), LinksDeletionUpdate\doIncrementalUpdate(), FileBackendMultiWrite\doOperationsInternal(), FileBackendMultiWrite\doQuickOperationsInternal(), MediaWiki\Storage\DerivedPageDataUpdater\doUpdates(), WikiPage\doViewUpdates(), EditPage\edit(), RollbackAction\enableTransactionalTimelimit(), ApiRollback\execute(), MovePageForm\execute(), MediaWiki\Logger\Monolog\BufferHandler\handle(), Category\initialize(), WikiPage\insertRedirect(), LocalFile\maybeUpgradeRow(), ResourceLoader\measureResponseTime(), RecentChange\notifyEdit(), RecentChange\notifyNew(), WikiPage\onArticleEdit(), ManualLogEntry\publish(), WikiPage\purgeInterwikiCheckKey(), MediaWiki\Session\SessionBackend\save(), ResourceLoader\saveModuleDependenciesInternal(), SpecialSearch\saveNamespaces(), MediaWiki\Storage\PageUpdater\saveRevision(), Pingback\schedulePingback(), RevDelList\setVisibility(), WikiPage\updateCategoryCounts(), WatchedItemStore\updateNotificationTimestamp(), and EditPage\updateWatchlist().

◆ addUpdate()

static DeferredUpdates::addUpdate ( DeferrableUpdate  $update,
  $stage = self::POSTSEND 
)
static

Add an update to the deferred update queue for execution at the appropriate time.

In CLI mode, callback magic will also be used to run updates when safe

If an update is already in progress, then what happens to this update is as follows:

  • MergeableUpdate instances always go on the top-queue for the specified stage, with existing updates melding into the newly added instance at the end of the queue.
  • Non-MergeableUpdate instances with a "defer until" stage at/before the actual run stage of the innermost in-progress update go into the sub-queue of that in-progress update. They are executed right after the update finishes to maximize isolation.
  • Non-MergeableUpdate instances with a "defer until" stage after the actual run stage of the innermost in-progress update go into the normal top-queue for that stage.
Parameters
DeferrableUpdate$updateSome object that implements doUpdate()
int$stageDeferredUpdates constant (PRESEND or POSTSEND) (since 1.27)

Definition at line 106 of file DeferredUpdates.php.

References $wgCommandLineMode, push(), and tryOpportunisticExecute().

Referenced by addCallableUpdate(), MediaWiki\Auth\AuthManager\autoCreateUser(), MediaWiki\Auth\AuthManager\continueAccountCreation(), LocalFile\deleteFile(), MediaWiki\Storage\PageUpdater\doCreate(), WikiPage\doDeleteUpdates(), MediaWiki\Storage\PageUpdater\doModify(), MediaWiki\Storage\DerivedPageDataUpdater\doSecondaryDataUpdates(), LinksUpdate\doUpdate(), MediaWiki\Storage\DerivedPageDataUpdater\doUpdates(), SpecialRunJobs\execute(), LocalFileRestoreBatch\execute(), PasswordReset\execute(), ChangesListSpecialPage\execute(), WikiImporter\finishImportPage(), User\incEditCount(), Title\invalidateCache(), PurgeJobUtils\invalidatePages(), JobQueueGroup\lazyPush(), NamespaceDupes\mergePage(), LocalFile\move(), MovePage\moveUnsafe(), MediaWiki\Block\DatabaseBlock\purgeExpired(), Title\purgeExpiredRestrictions(), HtmlCacheUpdater\purgeTitleUrls(), HtmlCacheUpdater\purgeUrls(), LocalFile\recordUpload3(), MessageCache\replace(), and MediaWiki\schedulePostSendJobs().

◆ areDatabaseTransactionsActive()

static DeferredUpdates::areDatabaseTransactionsActive ( )
staticprivate
Returns
bool If a transaction round is active or connection is not ready for commit()

Definition at line 581 of file DeferredUpdates.php.

References Wikimedia\Rdbms\IDatabase\explicitTrxActive(), Wikimedia\Rdbms\LoadBalancer\forEachOpenMasterConnection(), and Wikimedia\Rdbms\IDatabase\writesOrCallbacksPending().

◆ attemptUpdate()

static DeferredUpdates::attemptUpdate ( DeferrableUpdate  $update,
ILBFactory  $lbFactory 
)
static

Attempt to run an update with the appropriate transaction round state it expects.

DeferredUpdate classes that wrap the execution of bundles of other DeferredUpdate instances can use this method to run the updates. Any such wrapper class should always use TRX_ROUND_ABSENT itself.

Parameters
DeferrableUpdate$update
ILBFactory$lbFactory
Since
1.34

Definition at line 440 of file DeferredUpdates.php.

References Wikimedia\Rdbms\ILBFactory\beginMasterChanges(), Wikimedia\Rdbms\ILBFactory\commitMasterChanges(), DeferrableUpdate\doUpdate(), Wikimedia\Rdbms\ILBFactory\getEmptyTransactionTicket(), and Wikimedia\Rdbms\ILBFactory\hasTransactionRound().

Referenced by MediaWiki\Storage\DerivedPageDataUpdater\doSecondaryDataUpdates(), RefreshSecondaryDataUpdate\doUpdate(), and run().

◆ clearPendingUpdates()

static DeferredUpdates::clearPendingUpdates ( )
static

Clear all pending updates without performing them.

Calling this while an update is in-progress produces undefined results

This method should only be used for unit tests

Definition at line 573 of file DeferredUpdates.php.

◆ doUpdates()

static DeferredUpdates::doUpdates (   $mode = 'run',
  $stage = self::ALL 
)
static

Consume the list of deferred updates and execute them.

Note that it is rarely the case that this method should be called outside of a few select entry points. For simplicity, that kind of recursion is discouraged. Recursion cannot happen if an explicit transaction round is active, which limits usage to updates with TRX_ROUND_ABSENT that do not leave open an transactions round of their own during the call to this method.

In the less-common case of this being called within an in-progress DeferrableUpdate, this will not see any top-queue updates (since they were consumed and are being run inside an outer execution loop). In that case, it will instead operate on the sub-queue of the innermost in-progress update on the stack.

If $stage is self::ALL then the queue of PRESEND updates will be resolved, followed by the queue of POSTSEND updates.

Parameters
string$modeUse "enqueue" to use the job queue when possible [Default: "run"]
int$stageDeferredUpdates constant (PRESEND, POSTSEND, or ALL) (since 1.27)

Definition at line 171 of file DeferredUpdates.php.

References ALL, and handleUpdateQueue().

Referenced by JobRunner\doExecuteJob(), RefreshLinks\fixLinksFromArticle(), NamespaceDupes\mergePage(), MediaWiki\preOutputCommit(), MediaWiki\restInPeace(), and tryOpportunisticExecute().

◆ enqueueUpdates()

static DeferredUpdates::enqueueUpdates ( array  $updates)
staticprivate

Enqueue a job for each EnqueueableDataUpdate item and return the other items.

Parameters
DeferrableUpdate[]$updatesA list of deferred update instances
Returns
DeferrableUpdate[] Remaining updates that do not support being queued

Definition at line 511 of file DeferredUpdates.php.

References JobQueueGroup\singleton().

Referenced by tryOpportunisticExecute().

◆ getPendingUpdates()

static DeferredUpdates::getPendingUpdates (   $stage = self::ALL)
static

Get the list of pending updates in the top-queues.

Calling this while an update is in-progress produces undefined results

This method should only be used for unit tests

Parameters
int$stageDeferredUpdates constant (PRESEND, POSTSEND, or ALL)
Returns
DeferrableUpdate[]
Since
1.29

Definition at line 554 of file DeferredUpdates.php.

◆ handleUpdateQueue()

static DeferredUpdates::handleUpdateQueue ( array &  $queue,
  $mode,
  $stage 
)
staticprotected

Immediately run or enqueue a list of updates.

Updates that implement EnqueueableDataUpdate and fail to run will be enqueued

Parameters
DeferrableUpdate[]&$queueList of DeferrableUpdate objects
string$modeEither "run" or "enqueue" (to use the job queue when possible)
int$stageClass constant (PRESEND, POSTSEND) (since 1.28)
Exceptions
ErrorPageErrorHappens on top-level calls
ExceptionHappens on second-level calls

Definition at line 234 of file DeferredUpdates.php.

References $queue, RequestContext\getMain(), jobify(), and run().

Referenced by doUpdates().

◆ jobify()

static DeferredUpdates::jobify ( EnqueueableDataUpdate  $update,
LBFactory  $lbFactory,
LoggerInterface  $logger,
StatsdDataFactoryInterface  $stats,
  $httpMethod 
)
staticprivate

Push a update into the job queue system and catch/log any exceptions.

Parameters
EnqueueableDataUpdate$update
LBFactory$lbFactory
LoggerInterface$logger
StatsdDataFactoryInterface$stats
string$httpMethod

Definition at line 398 of file DeferredUpdates.php.

References $type, EnqueueableDataUpdate\getAsJobSpecification(), MWExceptionHandler\logException(), Wikimedia\Rdbms\LBFactory\rollbackMasterChanges(), and JobQueueGroup\singleton().

Referenced by handleUpdateQueue().

◆ pendingUpdatesCount()

static DeferredUpdates::pendingUpdatesCount ( )
static

Get the number of currently enqueued updates in the top-queues.

Calling this while an update is in-progress produces undefined results

Returns
int
Since
1.28

Definition at line 535 of file DeferredUpdates.php.

Referenced by MediaWiki\outputResponsePayload(), and tryOpportunisticExecute().

◆ push()

static DeferredUpdates::push ( array &  $queue,
DeferrableUpdate  $update 
)
staticprivate
Parameters
DeferrableUpdate[]&$queueCombined FIFO update list and MergeableUpdate map
DeferrableUpdate$update

Definition at line 203 of file DeferredUpdates.php.

References $queue.

Referenced by addUpdate().

◆ run()

static DeferredUpdates::run ( DeferrableUpdate  $update,
LBFactory  $lbFactory,
LoggerInterface  $logger,
StatsdDataFactoryInterface  $stats,
  $httpMethod 
)
staticprivate

Run an update, and, if an error was thrown, catch/log it and fallback to the job queue.

Parameters
DeferrableUpdate$update
LBFactory$lbFactory
LoggerInterface$logger
StatsdDataFactoryInterface$stats
string$httpMethod
Returns
Throwable|null

Definition at line 329 of file DeferredUpdates.php.

References $type, attemptUpdate(), MWExceptionHandler\logException(), Wikimedia\Rdbms\LBFactory\rollbackMasterChanges(), and JobQueueGroup\singleton().

Referenced by handleUpdateQueue().

◆ tryOpportunisticExecute()

static DeferredUpdates::tryOpportunisticExecute (   $mode = 'run')
static

Run all deferred updates immediately if there are no DB writes active.

If there are many deferred updates pending, $mode is 'run', and there are still busy LBFactory database handles, then any EnqueueableDataUpdate updates might be enqueued as jobs to be executed later.

Parameters
string$modeUse "enqueue" to use the job queue when possible
Returns
bool Whether updates were allowed to run
Since
1.28

Definition at line 483 of file DeferredUpdates.php.

References doUpdates(), enqueueUpdates(), and pendingUpdatesCount().

Referenced by addUpdate().

Member Data Documentation

◆ $executionStack

array [] DeferredUpdates::$executionStack = []
staticprivate

Execution stack of currently running updates -var array<array{stage:int,update:DeferrableUpdate,subqueue:DeferrableUpdate[]}>

Definition at line 81 of file DeferredUpdates.php.

◆ $postSendUpdates

DeferrableUpdate [] DeferredUpdates::$postSendUpdates = []
staticprivate

Updates to be deferred until just after HTTP response emission.

Integer-keyed entries form a list of FIFO updates and a string-keyed entries form a map of (class => MergeableUpdate) for updates that absorb the work of any already pending updates of the same class.

Definition at line 76 of file DeferredUpdates.php.

◆ $preSendUpdates

DeferrableUpdate [] DeferredUpdates::$preSendUpdates = []
staticprivate

Updates to be deferred until just before HTTP response emission.

Integer-keyed entries form a list of FIFO updates and a string-keyed entries form a map of (class => MergeableUpdate) for updates that absorb the work of any already pending updates of the same class.

Definition at line 69 of file DeferredUpdates.php.

◆ ALL

const DeferredUpdates::ALL = 0

Definition at line 83 of file DeferredUpdates.php.

Referenced by doUpdates().

◆ BIG_QUEUE_SIZE

const DeferredUpdates::BIG_QUEUE_SIZE = 100
private

Definition at line 87 of file DeferredUpdates.php.

◆ POSTSEND

◆ PRESEND


The documentation for this class was generated from the following file: