From 6b2f8639b681bdaec318d5423a202e46ea796846 Mon Sep 17 00:00:00 2001 From: Timo Tijhof Date: Thu, 12 Oct 2017 21:19:56 +0100 Subject: [PATCH] deferred: Introduce TransactionRoundDefiningUpdate This allows scheduling of updates that need to start their own transaction round. Specifically for cases where the ability to commit early is not enough (which is already possible via LBFactory getEmptyTransactionTicket and commitAndWaitForReplication). Change-Id: I0910587b61c8ddf825f91e92c2f93582cc7ebd80 --- autoload.php | 1 + includes/deferred/DeferredUpdates.php | 2 + .../TransactionRoundDefiningUpdate.php | 31 +++++++++++++ .../includes/deferred/DeferredUpdatesTest.php | 44 +++++++++++++++++++ .../TransactionRoundDefiningUpdateTest.php | 17 +++++++ 5 files changed, 95 insertions(+) create mode 100644 includes/deferred/TransactionRoundDefiningUpdate.php create mode 100644 tests/phpunit/includes/deferred/TransactionRoundDefiningUpdateTest.php diff --git a/autoload.php b/autoload.php index 0a2ecf01c5..ede520f9dc 100644 --- a/autoload.php +++ b/autoload.php @@ -1498,6 +1498,7 @@ $wgAutoloadLocalClasses = [ 'TrackBlobs' => __DIR__ . '/maintenance/storage/trackBlobs.php', 'TrackingCategories' => __DIR__ . '/includes/TrackingCategories.php', 'TraditionalImageGallery' => __DIR__ . '/includes/gallery/TraditionalImageGallery.php', + 'TransactionRoundDefiningUpdate' => __DIR__ . '/includes/deferred/TransactionRoundDefiningUpdate.php', 'TransformParameterError' => __DIR__ . '/includes/media/MediaTransformOutput.php', 'TransformTooBigImageAreaError' => __DIR__ . '/includes/media/MediaTransformOutput.php', 'TransformationalImageHandler' => __DIR__ . '/includes/media/TransformationalImageHandler.php', diff --git a/includes/deferred/DeferredUpdates.php b/includes/deferred/DeferredUpdates.php index e8e250b551..3c4833c7f0 100644 --- a/includes/deferred/DeferredUpdates.php +++ b/includes/deferred/DeferredUpdates.php @@ -250,6 +250,8 @@ class DeferredUpdates { // Run only the job enqueue logic to complete the update later $spec = $update->getAsJobSpecification(); JobQueueGroup::singleton( $spec['wiki'] )->push( $spec['job'] ); + } elseif ( $update instanceof TransactionRoundDefiningUpdate ) { + $update->doUpdate(); } else { // Run the bulk of the update now $fnameTrxOwner = get_class( $update ) . '::doUpdate'; diff --git a/includes/deferred/TransactionRoundDefiningUpdate.php b/includes/deferred/TransactionRoundDefiningUpdate.php new file mode 100644 index 0000000000..65baec5d51 --- /dev/null +++ b/includes/deferred/TransactionRoundDefiningUpdate.php @@ -0,0 +1,31 @@ +callback = $callback; + $this->fname = $fname; + } + + public function doUpdate() { + call_user_func( $this->callback ); + } + + public function getOrigin() { + return $this->fname; + } +} diff --git a/tests/phpunit/includes/deferred/DeferredUpdatesTest.php b/tests/phpunit/includes/deferred/DeferredUpdatesTest.php index 999ad03935..8332d2ccc2 100644 --- a/tests/phpunit/includes/deferred/DeferredUpdatesTest.php +++ b/tests/phpunit/includes/deferred/DeferredUpdatesTest.php @@ -1,5 +1,7 @@ assertTrue( $x, "Outer POSTSEND update ran" ); $this->assertTrue( $y, "Nested PRESEND update ran" ); } + + /** + * @covers DeferredUpdates::runUpdate + */ + public function testRunUpdateTransactionScope() { + $this->setMwGlobals( 'wgCommandLineMode', false ); + + $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory(); + $this->assertFalse( $lbFactory->hasTransactionRound(), 'Initial state' ); + + $ran = 0; + DeferredUpdates::addCallableUpdate( function () use ( &$ran, $lbFactory ) { + $ran++; + $this->assertTrue( $lbFactory->hasTransactionRound(), 'Has transaction' ); + } ); + DeferredUpdates::doUpdates(); + + $this->assertSame( 1, $ran, 'Update ran' ); + $this->assertFalse( $lbFactory->hasTransactionRound(), 'Final state' ); + } + + /** + * @covers DeferredUpdates::runUpdate + * @covers TransactionRoundDefiningUpdate::getOrigin + */ + public function testRunOuterScopeUpdate() { + $this->setMwGlobals( 'wgCommandLineMode', false ); + + $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory(); + $this->assertFalse( $lbFactory->hasTransactionRound(), 'Initial state' ); + + $ran = 0; + DeferredUpdates::addUpdate( new TransactionRoundDefiningUpdate( + function () use ( &$ran, $lbFactory ) { + $ran++; + $this->assertFalse( $lbFactory->hasTransactionRound(), 'No transaction' ); + } ) + ); + DeferredUpdates::doUpdates(); + + $this->assertSame( 1, $ran, 'Update ran' ); + } } diff --git a/tests/phpunit/includes/deferred/TransactionRoundDefiningUpdateTest.php b/tests/phpunit/includes/deferred/TransactionRoundDefiningUpdateTest.php new file mode 100644 index 0000000000..e6ad072516 --- /dev/null +++ b/tests/phpunit/includes/deferred/TransactionRoundDefiningUpdateTest.php @@ -0,0 +1,17 @@ +assertSame( 0, $ran ); + $update->doUpdate(); + $this->assertSame( 1, $ran ); + } +} -- 2.20.1