Daniel Kinzler has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/55887


Change subject: Fix misleading output of Special:DispatchStats.
......................................................................

Fix misleading output of Special:DispatchStats.

Previously, the notions of "touched time" (time since last dispatch)
was confused with the "lag time" (time between last dispatched change
and most recent change).

Change-Id: I914bbf5aa7965a6d98d2033e5b1ef83da340cb15
---
M repo/Wikibase.i18n.php
M repo/includes/specials/SpecialDispatchStats.php
M repo/includes/store/sql/DispatchStats.php
M repo/tests/phpunit/includes/store/sql/DispatchStatsTest.php
4 files changed, 142 insertions(+), 79 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikibase 
refs/changes/87/55887/1

diff --git a/repo/Wikibase.i18n.php b/repo/Wikibase.i18n.php
index 176aaa0..096a4ed 100644
--- a/repo/Wikibase.i18n.php
+++ b/repo/Wikibase.i18n.php
@@ -179,8 +179,11 @@
        'wikibase-dispatchstats-oldest-change' => 'Oldest',
        'wikibase-dispatchstats-newest-change' => 'Newest',
        'wikibase-dispatchstats-site-id' => 'Site',
+       'wikibase-dispatchstats-pos' => 'Position',
        'wikibase-dispatchstats-lag-num' => 'Pending',
        'wikibase-dispatchstats-lag-time' => 'Lag',
+       'wikibase-dispatchstats-touched' => 'Touched',
+       'wikibase-dispatchstats-large-lag' => '(very large)',
        'wikibase-dispatchstats-freshest' => 'Freshest',
        'wikibase-dispatchstats-stalest' => 'Stalest',
        'wikibase-dispatchstats-median'  => 'Median',
@@ -717,9 +720,12 @@
 {{Identical|Newest}}',
        'wikibase-dispatchstats-site-id' => 'Column header for site IDs.
 {{Identical|Site}}',
+       'wikibase-dispatchstats-pos' => 'Column header for dispatch position 
(given as change ID).',
        'wikibase-dispatchstats-lag-num' => 'Column header for the number of 
changes not yet dispatched to this client wiki.
 {{Identical|Pending}}',
-       'wikibase-dispatchstats-lag-time' => 'Column header for the time since 
a dispatcher visited this client wiki',
+       'wikibase-dispatchstats-lag-time' => 'Column header for the time since 
between the change last dispatched to the client and the latest known change on 
the repo.',
+       'wikibase-dispatchstats-touched' => 'Column header for the time a 
dispatcher last visited this client wiki',
+       'wikibase-dispatchstats-large-lag' => 'Shown instead of the actual lag 
if the lag is so large that the relevant change records were already pruned',
        'wikibase-dispatchstats-freshest' => 'Row header for the freshest (most 
recently updated) client wiki.
 
 See also:
@@ -2613,11 +2619,13 @@
        'wikibase-dispatchstats-oldest-change' => 'Älteste',
        'wikibase-dispatchstats-newest-change' => 'Neueste',
        'wikibase-dispatchstats-site-id' => 'Website',
+       'wikibase-dispatchstats-pos' => 'Stand',
        'wikibase-dispatchstats-lag-num' => 'Ausstehend',
-       'wikibase-dispatchstats-lag-time' => 'Verzögerung',
+       'wikibase-dispatchstats-lag-time' => 'Rückstand',
+       'wikibase-dispatchstats-touched' => 'Letzte Verarbeitung',
        'wikibase-dispatchstats-freshest' => 'Neueste',
        'wikibase-dispatchstats-stalest' => 'Älteste',
-       'wikibase-dispatchstats-median' => 'Mittel',
+       'wikibase-dispatchstats-median' => 'Zentralwert',
        'wikibase-dispatchstats-average' => 'Durchschnitt',
        'special-listdatatypes' => 'Liste aller verfügbaren Datentypen',
        'wikibase-listdatatypes-intro' => 'Dies ist eine Liste aller 
Datentypen, die derzeit in dieser Installation verwendet werden:',
diff --git a/repo/includes/specials/SpecialDispatchStats.php 
b/repo/includes/specials/SpecialDispatchStats.php
index 2acfc3a..3273d3c 100644
--- a/repo/includes/specials/SpecialDispatchStats.php
+++ b/repo/includes/specials/SpecialDispatchStats.php
@@ -61,9 +61,15 @@
 
                $this->outputRow( array(
                        $label,
-                       isset( $state->chd_site ) ? $state->chd_site : '',
-                       $lang->formatNum( $state->chd_dist ),
-                       $lang->formatDuration( $state->chd_lag ),
+                       isset( $state->chd_site ) ? $state->chd_site : '-',
+                       isset( $state->chd_seen ) ? $state->chd_seen : '-',
+                       $lang->formatNum( $state->chd_pending ),
+                       $state->chd_lag === null
+                               ? wfMessage( 'wikibase-dispatchstats-large-lag' 
)->text()
+                               : $lang->formatDuration( $state->chd_lag, 
array( 'days', 'hours', 'minutes' ) ),
+                       isset( $state->chd_touched )
+                               ? $lang->timeanddate( $state->chd_touched )
+                               : '-',
                ) );
        }
 
@@ -118,8 +124,10 @@
                $this->outputRow( array(
                        '',
                        $this->msg( 'wikibase-dispatchstats-site-id' )->text(),
+                       $this->msg( 'wikibase-dispatchstats-pos' )->text(),
                        $this->msg( 'wikibase-dispatchstats-lag-num' )->text(),
                        $this->msg( 'wikibase-dispatchstats-lag-time' )->text(),
+                       $this->msg( 'wikibase-dispatchstats-touched' )->text(),
                ), 'th' );
 
                $this->outputStateRow(
diff --git a/repo/includes/store/sql/DispatchStats.php 
b/repo/includes/store/sql/DispatchStats.php
index f2add33..036fb1c 100644
--- a/repo/includes/store/sql/DispatchStats.php
+++ b/repo/includes/store/sql/DispatchStats.php
@@ -73,10 +73,14 @@
         * Loads the current dispatch status from the database and calculates 
statistics.
         * Before this method is called, the behavior of the getters is 
undefined.
         *
+        * @param int|string $now: Timestamp to consider the current time. 
Mostly useful for testing.
+        *
         * @return int the number of client wikis.
         */
-       public function load() {
+       public function load( $now = 0 ) {
                $db = wfGetDB( DB_SLAVE ); // XXX: use master?
+
+               $now = wfTimestamp( TS_UNIX, $now );
 
                $this->changeStats = $db->selectRow(
                        $this->changesTableName,
@@ -90,13 +94,18 @@
                        __METHOD__
                );
 
-               $res = $db->select( $this->dispatchTableName,
+               $res = $db->select(
+                       array (
+                               $this->dispatchTableName,
+                               $this->changesTableName
+                       ),
                        array( 'chd_site',
                                        'chd_db',
                                        'chd_seen',
                                        'chd_touched',
                                        'chd_lock',
                                        'chd_disabled',
+                                       'change_time',
                        ),
                        array(
                                'chd_disabled' => 0
@@ -104,29 +113,51 @@
                        __METHOD__,
                        array(
                                'ORDER BY' => 'chd_seen ASC'
+                       ),
+                       array(
+                               $this->changesTableName => array( 'LEFT JOIN', 
'chd_seen = change_id' )
                        )
                );
 
                $this->average = new \stdClass();
+               $this->average->chd_untouched = 0;
+               $this->average->chd_pending = 0;
                $this->average->chd_lag = 0;
-               $this->average->chd_dist = 0;
 
                $this->clientStates = array();
 
                while ( $row = $res->fetchObject() ) {
                        if ( $this->changeStats ) {
-                               $row->chd_lag = max( 0, (int)wfTimestamp( 
TS_UNIX, $this->changeStats->max_time )
+                               // time between last dispatch and now
+                               $row->chd_untouched = max( 0, $now
                                        - (int)wfTimestamp( TS_UNIX, 
$row->chd_touched ) );
 
-                               $row->chd_dist = 
(int)$this->changeStats->max_id - $row->chd_seen;
+                               // time between the timestamp of the last 
changed processed and the last change recorded.
+                               if ( $row->change_time === null ) {
+                                       // the change was already pruned, lag 
is "big".
+                                       $row->chd_lag = null;
+                               } else {
+                                       $row->chd_lag = max( 0, 
(int)wfTimestamp( TS_UNIX, $this->changeStats->max_time )
+                                               - (int)wfTimestamp( TS_UNIX, 
$row->change_time ) );
+                               }
+
+                               // number of changes that have not been 
processed yet
+                               $row->chd_pending = 
(int)$this->changeStats->max_id - $row->chd_seen;
                        } else {
                                // if there are no changes, there is no lag
+                               $row->chd_untouched = 0;
+                               $row->chd_pending = 0;
                                $row->chd_lag = 0;
-                               $row->chd_dist = 0;
                        }
 
-                       $this->average->chd_lag += $row->chd_lag;
-                       $this->average->chd_dist += $row->chd_dist;
+                       $this->average->chd_untouched += $row->chd_untouched;
+                       $this->average->chd_pending += $row->chd_pending;
+
+                       if ( $row->chd_lag === null || $this->average->chd_lag 
=== null ) {
+                               $this->average->chd_lag = null;
+                       } else {
+                               $this->average->chd_lag += $row->chd_lag;
+                       }
 
                        $this->clientStates[] = $row;
                }
@@ -134,8 +165,10 @@
                $n = count( $this->clientStates );
 
                if ( $n > 0 ) {
-                       $this->average->chd_lag = intval( 
$this->average->chd_lag / $n );
-                       $this->average->chd_dist = intval( 
$this->average->chd_dist / $n );
+                       $this->average->chd_untouched = intval( 
$this->average->chd_untouched / $n );
+                       $this->average->chd_pending = intval( 
$this->average->chd_pending / $n );
+                       $this->average->chd_lag = $this->average->chd_lag === 
null
+                                                                               
? null : intval( $this->average->chd_lag / $n );
                }
 
                return $n;
@@ -150,8 +183,12 @@
         * The state for each wiki is returned as an object containing the 
following fields:
         *
         * * chd_site: the client wiki's site ID
-        * * chd_lag:  seconds since that client was last touched by a 
dispatcher
-        * * chd_dist: number of changes not yet dispatched to that client
+        * * chd_untouched:  seconds since that client was last touched by a 
dispatcher
+        * * chd_pending: number of changes not yet dispatched to that client
+        * * chd_lag: seconds between the timestamp of the last change that got 
dispatched
+        *            and the latest change recorded. May be null if some of 
the pending changes
+        *            have already been pruned. This indicates that the average 
could not be
+        *            determined, but the lag is large.
         * * chd_lock: the name of the lock currently in effect for that wiki
         *
         * @return array|null A list of objects representing the dispatch state
@@ -218,8 +255,12 @@
         * Returns a pseudo-status object representing the average (mean) 
dispatch
         * lag. The status object has the following fields:
         *
-        * * chd_lag:  seconds since that client was last touched by a 
dispatcher
-        * * chd_dist: number of changes not yet dispatched to that client
+        * * chd_untouched:  seconds since that client was last touched by a 
dispatcher
+        * * chd_pending: number of changes not yet dispatched to that client
+        * * chd_lag: seconds between the timestamp of the last change that got 
dispatched
+        *            and the latest change recorded. May be null if some of 
the pending changes
+        *            have already been pruned. This indicates that the average 
could not be
+        *            determined, but the lag is large.
         *
         * @return object
         */
diff --git a/repo/tests/phpunit/includes/store/sql/DispatchStatsTest.php 
b/repo/tests/phpunit/includes/store/sql/DispatchStatsTest.php
index 179a9f2..195c65f 100644
--- a/repo/tests/phpunit/includes/store/sql/DispatchStatsTest.php
+++ b/repo/tests/phpunit/includes/store/sql/DispatchStatsTest.php
@@ -37,22 +37,27 @@
 class EntityChangeTest extends \MediaWikiTestCase {
 
        /**
-        * Injects the given $changes and $states into the database,
-        * then creates and loads a DispatchStats object.
-        *
-        * @param array $changes
-        * @param array $states
-        * @param string|int $now the value of now.
+        * Creates and loads a DispatchStats object, injecting test data into
+        * the database as needed.
         *
         * @return DispatchStats
         */
-       protected function getDispatchStats( $changes, $states ) {
+       protected function getDispatchStats() {
+               $data = self::getTestData();
+               $now = $data['now'];
+               $changes = $data['changes'];
+               $states = $data['states'];
+
                $dbw = wfGetDB( DB_MASTER ); // write to dummy tables
 
                $dbw->query( "truncate " . $dbw->tableName( 'wb_changes' ) );
                $dbw->query( "truncate " . $dbw->tableName( 
'wb_changes_dispatch' ) );
 
                foreach ( $changes as $row ) {
+                       if ( $row === null ) {
+                               continue;
+                       }
+
                        $dbw->insert( 'wb_changes',
                                $row,
                                __METHOD__
@@ -60,6 +65,10 @@
                }
 
                foreach ( $states as $row ) {
+                       if ( $row === null ) {
+                               continue;
+                       }
+
                        $dbw->insert( 'wb_changes_dispatch',
                                $row,
                                __METHOD__
@@ -67,7 +76,7 @@
                }
 
                $stats = new DispatchStats();
-               $stats->load();
+               $stats->load( $now );
                return $stats;
        }
 
@@ -108,19 +117,19 @@
                                ),
                        ),
                        'changes' => array(
-                               array(
+                               2 => array(
                                        'change_id' => 2,
                                        'change_time' => '20130303000200',
                                        'change_type' => 'test',
                                        'change_object_id' => 'test',
                                ),
-                               array(
+                               3 => array(
                                        'change_id' => 3,
                                        'change_time' => '20130303000300',
                                        'change_type' => 'test',
                                        'change_object_id' => 'test',
                                ),
-                               array(
+                               1 => array(
                                        'change_id' => 1,
                                        'change_time' => '20130303000100',
                                        'change_type' => 'test',
@@ -128,28 +137,33 @@
                                ),
                        ),
 
+                       'now' => '20130303000400',
+
                        'expected' => array(
                                'getClientStates' => array(
                                        array(
                                                'chd_site' => 'frwiki',
                                                'chd_seen' => 1,
                                                'chd_touched' => 
'20130303000110',
-                                               'chd_lag' => 110,
-                                               'chd_dist' => 2,
+                                               'chd_untouched' => 170,
+                                               'chd_pending' => 2,
+                                               'chd_lag' => 120,
                                        ),
                                        array(
                                                'chd_site' => 'dewiki',
                                                'chd_seen' => 2,
                                                'chd_touched' => 
'20130303000220',
-                                               'chd_lag' => 40,
-                                               'chd_dist' => 1,
+                                               'chd_untouched' => 100,
+                                               'chd_pending' => 1,
+                                               'chd_lag' => 60,
                                        ),
                                        array(
                                                'chd_site' => 'enwiki',
                                                'chd_seen' => 3,
                                                'chd_touched' => 
'20130303000330',
+                                               'chd_untouched' => 30,
+                                               'chd_pending' => 0,
                                                'chd_lag' => 0,
-                                               'chd_dist' => 0,
                                        ),
                                ),
 
@@ -165,26 +179,30 @@
                                        'chd_site' => 'enwiki',
                                        'chd_seen' => 3,
                                        'chd_touched' => '20130303000330',
+                                       'chd_untouched' => 30,
+                                       'chd_pending' => 0,
                                        'chd_lag' => 0,
-                                       'chd_dist' => 0,
                                ),
                                'getStalest' => array(
                                        'chd_site' => 'frwiki',
                                        'chd_seen' => 1,
                                        'chd_touched' => '20130303000110',
-                                       'chd_lag' => 110,
-                                       'chd_dist' => 2,
+                                       'chd_untouched' => 170,
+                                       'chd_pending' => 2,
+                                       'chd_lag' => 120,
                                ),
                                'getMedian' => array(
                                        'chd_site' => 'dewiki',
                                        'chd_seen' => 2,
                                        'chd_touched' => '20130303000220',
-                                       'chd_lag' => 40,
-                                       'chd_dist' => 1,
+                                       'chd_untouched' => 100,
+                                       'chd_pending' => 1,
+                                       'chd_lag' => 60,
                                ),
                                'getAverage' => array(
-                                       'chd_lag' => 30,
-                                       'chd_dist' => 1,
+                                       'chd_untouched' => 100,
+                                       'chd_pending' => 1,
+                                       'chd_lag' => 60,
                                ),
                        ),
                );
@@ -195,8 +213,6 @@
 
                return array(
                        array(
-                               $data['changes'],
-                               $data['states'],
                                $data['expected']['getClientStates'],
                        )
                );
@@ -205,8 +221,8 @@
        /**
         * @dataProvider provideGetClientStates
         */
-       public function testGetClientStates( $changes, $states, $expected ) {
-               $stats = $this->getDispatchStats( $changes, $states );
+       public function testGetClientStates( $expected ) {
+               $stats = $this->getDispatchStats();
 
                $states = $stats->getClientStates();
 
@@ -240,11 +256,11 @@
                }
 
                if ( isset( $expected['lag'] ) ) {
-                       $this->assertEquals( $expected['lag'], $actual>chd_lag, 
"lag/$suffix" );
+                       $this->assertEquals( $expected['lag'], 
$actual>chd_untouched, "lag/$suffix" );
                }
 
                if ( isset( $expected['dist'] ) ) {
-                       $this->assertEquals( $expected['dist'], 
$actual>chd_dist, "dist/$suffix" );
+                       $this->assertEquals( $expected['dist'], 
$actual>chd_pending, "dist/$suffix" );
                }
        }
 
@@ -253,7 +269,6 @@
 
                return array(
                        array(
-                               $data['states'],
                                $data['expected']['getClientCount'],
                        )
                );
@@ -262,8 +277,8 @@
        /**
         * @dataProvider provideGetClientCount
         */
-       public function testGetClientCount( $states, $expected ) {
-               $stats = $this->getDispatchStats( array(), $states );
+       public function testGetClientCount( $expected ) {
+               $stats = $this->getDispatchStats( );
 
                $this->assertEquals( $expected, $stats->getClientCount() );
        }
@@ -273,7 +288,6 @@
 
                return array(
                        array(
-                               $data['states'],
                                $data['expected']['getLockedCount'],
                        )
                );
@@ -282,8 +296,8 @@
        /**
         * @dataProvider provideGetLockedCount
         */
-       public function testGetLockedCount( $states, $expected ) {
-               $stats = $this->getDispatchStats( array(), $states );
+       public function testGetLockedCount( $expected ) {
+               $stats = $this->getDispatchStats();
 
                $this->assertEquals( $expected, $stats->getLockedCount() );
        }
@@ -293,7 +307,6 @@
 
                return array(
                        array(
-                               $data['changes'],
                                $data['expected']['getMinChangeId'],
                        )
                );
@@ -302,8 +315,8 @@
        /**
         * @dataProvider provideGetMinChangeId
         */
-       public function testGetMinChangeId( $changes, $expected ) {
-               $stats = $this->getDispatchStats( $changes, array() );
+       public function testGetMinChangeId( $expected ) {
+               $stats = $this->getDispatchStats();
 
                $this->assertEquals( $expected, $stats->getMinChangeId() );
        }
@@ -313,7 +326,6 @@
 
                return array(
                        array(
-                               $data['changes'],
                                $data['expected']['getMaxChangeId'],
                        )
                );
@@ -322,8 +334,8 @@
        /**
         * @dataProvider provideGetMaxChangeId
         */
-       public function testGetMaxChangeId( $changes, $expected ) {
-               $stats = $this->getDispatchStats( $changes, array() );
+       public function testGetMaxChangeId( $expected ) {
+               $stats = $this->getDispatchStats();
 
                $this->assertEquals( $expected, $stats->getMaxChangeId() );
        }
@@ -333,7 +345,6 @@
 
                return array(
                        array(
-                               $data['changes'],
                                $data['expected']['getMinChangeTimestamp'],
                        )
                );
@@ -342,8 +353,8 @@
        /**
         * @dataProvider provideGetMinChangeTimestamp
         */
-       public function testGetMinChangeTimestamp( $changes, $expected ) {
-               $stats = $this->getDispatchStats( $changes, array() );
+       public function testGetMinChangeTimestamp( $expected ) {
+               $stats = $this->getDispatchStats();
 
                $this->assertEquals( $expected, $stats->getMinChangeTimestamp() 
);
        }
@@ -353,7 +364,6 @@
 
                return array(
                        array(
-                               $data['changes'],
                                $data['expected']['getMaxChangeTimestamp'],
                        )
                );
@@ -362,8 +372,8 @@
        /**
         * @dataProvider provideGetMaxChangeTimestamp
         */
-       public function testGetMaxChangeTimestamp( $changes, $expected ) {
-               $stats = $this->getDispatchStats( $changes, array() );
+       public function testGetMaxChangeTimestamp( $expected ) {
+               $stats = $this->getDispatchStats();
 
                $this->assertEquals( $expected, $stats->getMaxChangeTimestamp() 
);
        }
@@ -373,7 +383,6 @@
 
                return array(
                        array(
-                               $data['states'],
                                $data['expected']['getFreshest'],
                        )
                );
@@ -382,8 +391,8 @@
        /**
         * @dataProvider provideGetFreshest
         */
-       public function testGetFreshest( $states, $expected ) {
-               $stats = $this->getDispatchStats( array(), $states );
+       public function testGetFreshest( $expected ) {
+               $stats = $this->getDispatchStats();
 
                $this->assertStateEquals( $expected, $stats->getFreshest());
        }
@@ -393,7 +402,6 @@
 
                return array(
                        array(
-                               $data['states'],
                                $data['expected']['getStalest'],
                        )
                );
@@ -402,8 +410,8 @@
        /**
         * @dataProvider provideGetStalest
         */
-       public function testGetStalest( $states, $expected ) {
-               $stats = $this->getDispatchStats( array(), $states );
+       public function testGetStalest( $expected ) {
+               $stats = $this->getDispatchStats();
 
                $this->assertStateEquals( $expected, $stats->getStalest());
        }
@@ -413,7 +421,6 @@
 
                return array(
                        array(
-                               $data['states'],
                                $data['expected']['getAverage'],
                        )
                );
@@ -422,8 +429,8 @@
        /**
         * @dataProvider provideGetAverage
         */
-       public function testGetAverage( $states, $expected ) {
-               $stats = $this->getDispatchStats( array(), $states );
+       public function testGetAverage( $expected ) {
+               $stats = $this->getDispatchStats();
 
                $this->assertStateEquals( $expected, $stats->getStalest());
        }
@@ -433,7 +440,6 @@
 
                return array(
                        array(
-                               $data['states'],
                                $data['expected']['getMedian'],
                        )
                );
@@ -442,8 +448,8 @@
        /**
         * @dataProvider provideGetMedian
         */
-       public function testGetMedian( $states, $expected ) {
-               $stats = $this->getDispatchStats( array(), $states );
+       public function testGetMedian( $expected ) {
+               $stats = $this->getDispatchStats();
 
                $this->assertStateEquals( $expected, $stats->getStalest());
        }

-- 
To view, visit https://gerrit.wikimedia.org/r/55887
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I914bbf5aa7965a6d98d2033e5b1ef83da340cb15
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Daniel Kinzler <daniel.kinz...@wikimedia.de>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to