(bug 10172) Move setting the "changed since last visit" flags out of the job queue:
authorRoan Kattouw <catrope@users.mediawiki.org>
Mon, 2 Mar 2009 12:15:28 +0000 (12:15 +0000)
committerRoan Kattouw <catrope@users.mediawiki.org>
Mon, 2 Mar 2009 12:15:28 +0000 (12:15 +0000)
* Move up the UPDATE query on wl_notificationtimestamp up to before scheduling the EnotifyNotifyJob
* Move up the SELECT query fetching the users to be notified to before the UPDATE, and use its result for a more efficient UPDATE
* Pass actuallyNotifyOnPageChange() and the EnotifyNotifyJob an array of user IDs
* Add UserArray::newFromIDs()

RELEASE-NOTES
includes/EnotifNotifyJob.php
includes/UserArray.php
includes/UserMailer.php

index 12801ce..2dd0ded 100644 (file)
@@ -225,10 +225,13 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
 * (bug 17546) Correct Tongan language native name is "lea faka-Tonga"
 * (bug 17621) Special:WantedFiles has no link to Special:Whatlinkshere
 * (bug 17460) Client ecoding is now correctly set for PostgreSQL
-* (bug 17648) Prevent floats from intruding into edit area in previews if no toolbar present
+* (bug 17648) Prevent floats from intruding into edit area in previews if no
+  toolbar present
 * (bug 16899) DISPLAYTITLE should allow Arabic and Persian harakats
 * (bug 17692) Added (list of members) link to 'user' in Special:Listgrouprights
 * (bug 17707) Show file destination as plain text if &wpForReUpload=1
+* (bug 10172) Moved setting of "changed since last visit" flags out of the job
+  queue
 
 == API changes in 1.15 ==
 * (bug 16858) Revamped list=deletedrevs to make listing deleted contributions
index 31fcb0d..f7178d0 100644 (file)
@@ -26,7 +26,8 @@ class EnotifNotifyJob extends Job {
                        $this->params['timestamp'],
                        $this->params['summary'],
                        $this->params['minorEdit'],
-                       $this->params['oldid']
+                       $this->params['oldid'],
+                       $this->params['watchers']
                );
                return true;
        }
index a2f54b7..d48a444 100644 (file)
@@ -12,6 +12,17 @@ abstract class UserArray implements Iterator {
                return $userArray;
        }
 
+       static function newFromIDs( $ids ) {
+               $ids = array_map( 'intval', (array)$ids ); // paranoia
+               if ( !$ids )
+                       // Database::select() doesn't like empty arrays
+                       return new ArrayIterator(array());
+               $dbr = wfGetDB( DB_SLAVE );
+               $res = $dbr->select( 'user', '*', array( 'user_id' => $ids ),
+                       __METHOD__ );
+               return self::newFromResult( $res );
+       }
+
        protected static function newFromResult_internal( $res ) {
                $userArray = new UserArrayFromResult( $res );
                return $userArray;
index 7728abf..55ab703 100644 (file)
@@ -281,11 +281,42 @@ class EmailNotification {
         * @param $oldid (default: false)
         */
        function notifyOnPageChange($editor, $title, $timestamp, $summary, $minorEdit, $oldid = false) {
-               global $wgEnotifUseJobQ;
+               global $wgEnotifUseJobQ, $wgEnotifWatchlist, $wgShowUpdatedMarker;
 
-               if( $title->getNamespace() < 0 )
+               if ($title->getNamespace() < 0)
                        return;
 
+               // Build a list of users to notfiy
+               $watchers = array();
+               if ($wgEnotifWatchlist || $wgShowUpdatedMarker) {
+                       $dbw = wfGetDB( DB_MASTER );
+                       $res = $dbw->select( array( 'watchlist' ),
+                               array( 'wl_user' ),
+                               array(
+                                       'wl_title' => $title->getDBkey(),
+                                       'wl_namespace' => $title->getNamespace(),
+                                       'wl_user != ' . intval( $editor->getID() ),
+                                       'wl_notificationtimestamp IS NULL',
+                               ), __METHOD__
+                       );
+                       while ($row = $dbw->fetchObject( $res ) ) {
+                               $watchers[] = intval( $row->wl_user );
+                       }
+                       if ($watchers) {
+                               // Update wl_notificationtimestamp for all watching users except
+                               // the editor
+                               $dbw->begin();
+                               $dbw->update( 'watchlist',
+                                       array( /* SET */
+                                               'wl_notificationtimestamp' => $dbw->timestamp( $timestamp )
+                                       ), array( /* WHERE */
+                                               'wl_user' => $watchers
+                                       ), __METHOD__
+                               );
+                               $dbw->commit();
+                       }
+               }
+
                if ($wgEnotifUseJobQ) {
                        $params = array(
                                "editor" => $editor->getName(),
@@ -293,11 +324,12 @@ class EmailNotification {
                                "timestamp" => $timestamp,
                                "summary" => $summary,
                                "minorEdit" => $minorEdit,
-                               "oldid" => $oldid);
+                               "oldid" => $oldid,
+                               "watchers" => $watchers);
                        $job = new EnotifNotifyJob( $title, $params );
                        $job->insert();
                } else {
-                       $this->actuallyNotifyOnPageChange($editor, $title, $timestamp, $summary, $minorEdit, $oldid);
+                       $this->actuallyNotifyOnPageChange( $editor, $title, $timestamp, $summary, $minorEdit, $oldid, $watchers );
                }
 
        }
@@ -310,15 +342,16 @@ class EmailNotification {
         *
         * @param $editor User object
         * @param $title Title object
-        * @param $timestamp
-        * @param $summary
-        * @param $minorEdit
-        * @param $oldid (default: false)
+        * @param $timestamp string Edit timestamp
+        * @param $summary string Edit summary
+        * @param $minorEdit bool
+        * @param $oldid int Revision ID
+        * @param $watchers array of user IDs
         */
-       function actuallyNotifyOnPageChange($editor, $title, $timestamp, $summary, $minorEdit, $oldid=false) {
+       function actuallyNotifyOnPageChange($editor, $title, $timestamp, $summary, $minorEdit, $oldid, $watchers) {
                # we use $wgPasswordSender as sender's address
                global $wgEnotifWatchlist;
-               global $wgEnotifMinorEdits, $wgEnotifUserTalk, $wgShowUpdatedMarker;
+               global $wgEnotifMinorEdits, $wgEnotifUserTalk;
                global $wgEnotifImpersonal;
 
                wfProfileIn( __METHOD__ );
@@ -363,30 +396,12 @@ class EmailNotification {
 
                        if ( $wgEnotifWatchlist ) {
                                // Send updates to watchers other than the current editor
-                               $userCondition = 'wl_user != ' . intval( $editor->getID() );
-                               if ( $userTalkId !== false ) {
-                                       // Already sent an email to this person
-                                       $userCondition .= ' AND wl_user != ' . intval( $userTalkId );
-                               }
-                               $dbr = wfGetDB( DB_SLAVE );
-
-                               list( $user ) = $dbr->tableNamesN( 'user' );
-                               $res = $dbr->select( array( 'watchlist', 'user' ),
-                                       array( "$user.*" ),
-                                       array(
-                                               'wl_user=user_id',
-                                               'wl_title' => $title->getDBkey(),
-                                               'wl_namespace' => $title->getNamespace(),
-                                               $userCondition,
-                                               'wl_notificationtimestamp IS NULL',
-                                       ), __METHOD__
-                               );
-                               $userArray = UserArray::newFromResult( $res );
-
+                               $userArray = UserArray::newFromIDs( $watchers );
                                foreach ( $userArray as $watchingUser ) {
                                        if ( $watchingUser->getOption( 'enotifwatchlistpages' ) &&
                                                ( !$minorEdit || $watchingUser->getOption('enotifminoredits') ) &&
-                                               $watchingUser->isEmailConfirmed() )
+                                               $watchingUser->isEmailConfirmed() &&
+                                               $watchingUser->getID() != $userTalkId )
                                        {
                                                $this->compose( $watchingUser );
                                        }
@@ -400,31 +415,9 @@ class EmailNotification {
                        $this->compose( $user );
                }
 
-               $latestTimestamp = Revision::getTimestampFromId( $title, $title->getLatestRevID(GAID_FOR_UPDATE) );
-               // Do not update watchlists if something else already did.
-               if ( $timestamp >= $latestTimestamp && ($wgShowUpdatedMarker || $wgEnotifWatchlist) ) {
-                       # Mark the changed watch-listed page with a timestamp, so that the page is
-                       # listed with an "updated since your last visit" icon in the watch list. Do
-                       # not do this to users for their own edits.
-                       $dbw = wfGetDB( DB_MASTER );
-                       $dbw->begin();
-                       $dbw->update( 'watchlist',
-                               array( /* SET */
-                                       'wl_notificationtimestamp' => $dbw->timestamp($timestamp)
-                               ), array( /* WHERE */
-                                       'wl_title' => $title->getDBkey(),
-                                       'wl_namespace' => $title->getNamespace(),
-                                       'wl_notificationtimestamp IS NULL', // store oldest unseen change time
-                                       'wl_user != ' . intval( $editor->getID() )
-                               ), __METHOD__
-                       );
-                       $dbw->commit();
-               }
-               
                $this->sendMails();
-
                wfProfileOut( __METHOD__ );
-       } # function NotifyOnChange
+       }
 
        /**
         * @private