From: Aaron Schulz Date: Mon, 13 Apr 2015 23:02:16 +0000 (-0700) Subject: Avoid deadlocks in User::incEditCount X-Git-Tag: 1.31.0-rc.0~11710^2 X-Git-Url: http://git.cyclocoop.org/%7B%7B%20url_for%28%27admin_vote_add%27%29%20%7D%7D?a=commitdiff_plain;h=7eb982b0b4b632a064f1edcc3875b338887c77b7;p=lhc%2Fweb%2Fwiklou.git Avoid deadlocks in User::incEditCount * This makes concurrent editing less problematic Change-Id: I930222d5e831bb3729194abbdcb3cab194c70494 --- diff --git a/includes/User.php b/includes/User.php index f526fe0de4..9168c33710 100644 --- a/includes/User.php +++ b/includes/User.php @@ -4737,38 +4737,51 @@ class User implements IDBAccessObject { return $groups; } + /** + * Deferred version of incEditCountImmediate() + */ + public function incEditCount() { + $that = $this; + wfGetDB( DB_MASTER )->onTransactionPreCommitOrIdle( function() use ( $that ) { + $that->incEditCountImmediate(); + } ); + } + /** * Increment the user's edit-count field. * Will have no effect for anonymous users. + * @since 1.26 */ - public function incEditCount() { - if ( !$this->isAnon() ) { - $dbw = wfGetDB( DB_MASTER ); - $dbw->update( - 'user', - array( 'user_editcount=user_editcount+1' ), - array( 'user_id' => $this->getId() ), - __METHOD__ - ); + public function incEditCountImmediate() { + if ( $this->isAnon() ) { + return; + } - // Lazy initialization check... - if ( $dbw->affectedRows() == 0 ) { - // Now here's a goddamn hack... - $dbr = wfGetDB( DB_SLAVE ); - if ( $dbr !== $dbw ) { - // If we actually have a slave server, the count is - // at least one behind because the current transaction - // has not been committed and replicated. - $this->initEditCount( 1 ); - } else { - // But if DB_SLAVE is selecting the master, then the - // count we just read includes the revision that was - // just added in the working transaction. - $this->initEditCount(); - } + $dbw = wfGetDB( DB_MASTER ); + // No rows will be "affected" if user_editcount is NULL + $dbw->update( + 'user', + array( 'user_editcount=user_editcount+1' ), + array( 'user_id' => $this->getId() ), + __METHOD__ + ); + // Lazy initialization check... + if ( $dbw->affectedRows() == 0 ) { + // Now here's a goddamn hack... + $dbr = wfGetDB( DB_SLAVE ); + if ( $dbr !== $dbw ) { + // If we actually have a slave server, the count is + // at least one behind because the current transaction + // has not been committed and replicated. + $this->initEditCount( 1 ); + } else { + // But if DB_SLAVE is selecting the master, then the + // count we just read includes the revision that was + // just added in the working transaction. + $this->initEditCount(); } } - // edit count in user cache too + // Edit count in user cache too $this->invalidateCache(); }