From 99610822d875a7b596cda0c0e7fd9033d044df0a Mon Sep 17 00:00:00 2001 From: Aaron Schulz Date: Mon, 30 Nov 2015 15:26:45 -0800 Subject: [PATCH] Add mergeable update support DeferredUpdates * DeferrableUpdate classes can implement MergeableUpdate. Duplicate updates will be merged via the merge() method. * Make SquidUpdate support merge() so that duplicate URL purges are now caught accross the entire pre-send request execution. Change-Id: Idffdd3e71d89e4a0f28281e65a881113caae497c --- autoload.php | 1 + includes/deferred/DeferredUpdates.php | 14 +++++++++- includes/deferred/MergeableUpdate.php | 16 +++++++++++ includes/deferred/SquidUpdate.php | 27 +++++++++++-------- .../includes/deferred/DeferredUpdatesTest.php | 3 --- .../includes/deferred/SquidUpdateTest.php | 25 +++++++++++++++++ 6 files changed, 71 insertions(+), 15 deletions(-) create mode 100644 includes/deferred/MergeableUpdate.php create mode 100644 tests/phpunit/includes/deferred/SquidUpdateTest.php diff --git a/autoload.php b/autoload.php index f79e58b4c2..685849b368 100644 --- a/autoload.php +++ b/autoload.php @@ -793,6 +793,7 @@ $wgAutoloadLocalClasses = array( 'MergeHistoryPager' => __DIR__ . '/includes/specials/SpecialMergeHistory.php', 'MergeLogFormatter' => __DIR__ . '/includes/logging/MergeLogFormatter.php', 'MergeMessageFileList' => __DIR__ . '/maintenance/mergeMessageFileList.php', + 'MergeableUpdate' => __DIR__ . '/includes/deferred/MergeableUpdate.php', 'Message' => __DIR__ . '/includes/Message.php', 'MessageBlobStore' => __DIR__ . '/includes/cache/MessageBlobStore.php', 'MessageCache' => __DIR__ . '/includes/cache/MessageCache.php', diff --git a/includes/deferred/DeferredUpdates.php b/includes/deferred/DeferredUpdates.php index 3323c04d4f..adad908e36 100644 --- a/includes/deferred/DeferredUpdates.php +++ b/includes/deferred/DeferredUpdates.php @@ -95,7 +95,19 @@ class DeferredUpdates { private static function push( array &$queue, DeferrableUpdate $update ) { global $wgCommandLineMode; - array_push( $queue, $update ); + if ( $update instanceof MergeableUpdate ) { + $class = get_class( $update ); // fully-qualified class + if ( isset( $queue[$class] ) ) { + /** @var $existingUpdate MergeableUpdate */ + $existingUpdate = $queue[$class]; + $existingUpdate->merge( $update ); + } else { + $queue[$class] = $update; + } + } else { + $queue[] = $update; + } + if ( self::$forceDeferral ) { return; // do not run } diff --git a/includes/deferred/MergeableUpdate.php b/includes/deferred/MergeableUpdate.php new file mode 100644 index 0000000000..70760ce49c --- /dev/null +++ b/includes/deferred/MergeableUpdate.php @@ -0,0 +1,16 @@ +urls = array_unique( $urlArr ); + $this->urls = $urlArr; } /** @@ -59,9 +60,7 @@ class SquidUpdate implements DeferrableUpdate { * @deprecated 1.27 */ public static function newSimplePurge( Title $title ) { - $urlArr = $title->getSquidURLs(); - - return new SquidUpdate( $urlArr ); + return new SquidUpdate( $title->getSquidURLs() ); } /** @@ -71,6 +70,13 @@ class SquidUpdate implements DeferrableUpdate { self::purge( $this->urls ); } + public function merge( MergeableUpdate $update ) { + /** @var SquidUpdate $update */ + Assert::parameterType( __CLASS__, $update, '$update' ); + + $this->urls = array_merge( $this->urls, $update->urls ); + } + /** * Purges a list of Squids defined in $wgSquidServers. * $urlArr should contain the full URLs to purge as values @@ -86,6 +92,9 @@ class SquidUpdate implements DeferrableUpdate { return; } + // Remove duplicate URLs from list + $urlArr = array_unique( $urlArr ); + wfDebugLog( 'squid', __METHOD__ . ': ' . implode( ' ', $urlArr ) ); if ( $wgHTCPRouting ) { @@ -93,8 +102,6 @@ class SquidUpdate implements DeferrableUpdate { } if ( $wgSquidServers ) { - // Remove duplicate URLs - $urlArr = array_unique( $urlArr ); // Maximum number of parallel connections per squid $maxSocketsPerSquid = 8; // Number of requests to send per socket @@ -127,7 +134,7 @@ class SquidUpdate implements DeferrableUpdate { * @throws MWException * @param string[] $urlArr Collection of URLs to purge */ - protected static function HTCPPurge( array $urlArr ) { + private static function HTCPPurge( array $urlArr ) { global $wgHTCPRouting, $wgHTCPMulticastTTL; // HTCP CLR operation @@ -158,8 +165,6 @@ class SquidUpdate implements DeferrableUpdate { $wgHTCPMulticastTTL ); } - // Remove duplicate URLs from collection - $urlArr = array_unique( $urlArr ); // Get sequential trx IDs for packet loss counting $ids = UIDGenerator::newSequentialPerNodeIDs( 'squidhtcppurge', 32, count( $urlArr ), UIDGenerator::QUICK_VOLATILE diff --git a/tests/phpunit/includes/deferred/DeferredUpdatesTest.php b/tests/phpunit/includes/deferred/DeferredUpdatesTest.php index 42e48ff933..736f6e8909 100644 --- a/tests/phpunit/includes/deferred/DeferredUpdatesTest.php +++ b/tests/phpunit/includes/deferred/DeferredUpdatesTest.php @@ -1,8 +1,5 @@ setMwGlobals( 'wgCommandLineMode', false ); diff --git a/tests/phpunit/includes/deferred/SquidUpdateTest.php b/tests/phpunit/includes/deferred/SquidUpdateTest.php new file mode 100644 index 0000000000..6ceb42c116 --- /dev/null +++ b/tests/phpunit/includes/deferred/SquidUpdateTest.php @@ -0,0 +1,25 @@ +setMwGlobals( 'wgCommandLineMode', false ); + + $urls1 = array(); + $title = Title::newMainPage(); + $urls1[] = $title->getCanonicalURL( '?x=1' ); + $urls1[] = $title->getCanonicalURL( '?x=2' ); + $urls1[] = $title->getCanonicalURL( '?x=3' ); + $update1 = new SquidUpdate( $urls1 ); + DeferredUpdates::addUpdate( $update1 ); + + $urls2 = array(); + $urls2[] = $title->getCanonicalURL( '?x=2' ); + $urls2[] = $title->getCanonicalURL( '?x=3' ); + $urls2[] = $title->getCanonicalURL( '?x=4' ); + $update2 = new SquidUpdate( $urls2 ); + DeferredUpdates::addUpdate( $update2 ); + + $wrapper = TestingAccessWrapper::newFromObject( $update1 ); + $this->assertEquals( array_merge( $urls1, $urls2 ), $wrapper->urls ); + } +} -- 2.20.1