diff --git a/includes/User.php b/includes/User.php index 1fa3ed52c016..abac876f23f0 100644 --- a/includes/User.php +++ b/includes/User.php @@ -1814,42 +1814,64 @@ public function getTitleKey() { * @return Bool True if the user has new messages */ public function getNewtalk() { + # Wikia change - begin + # leave early, don't check it for our varnish ip addresses + global $wgSquidServers, $wgSquidServersNoPurge; + if( in_array( $this->getName(), $wgSquidServers ) || + in_array( $this->getName(), $wgSquidServersNoPurge ) + ) { + return false; + } + # Wikia change - end + $this->load(); # Load the newtalk status if it is unloaded (mNewtalk=-1) if( $this->mNewtalk === -1 ) { - $this->mNewtalk = false; # reset talk page status - - # Check memcached separately for anons, who have no - # entire User object stored in there. - if( !$this->mId ) { - # hack: don't check it for our varnish ip addresses - global $wgSquidServers, $wgSquidServersNoPurge; - if( in_array( $this->getName(), $wgSquidServers ) || - in_array( $this->getName(), $wgSquidServersNoPurge ) - ) { - return $this->mNewtalk; - } + $this->mNewtalk = (bool) WikiaDataAccess::cache( + $this->getNewTalkMemcKey(), + WikiaResponse::CACHE_LONG, + function() : int { + // WikiaDataAccess::cache assumes that there's a cache miss + // when we get either null or false from the caching layer - cast the result to an integer + + // Check memcached separately for anons, who have no + // entire User object stored in there. + if ( !$this->mId ) { + global $wgDisableAnonTalk; + if ( $wgDisableAnonTalk ) { + // Anon newtalk disabled by configuration. + $result = false; + } else { + $result = $this->checkNewtalk( 'user_ip', $this->getName() ); + } + } else { + $result = $this->checkNewtalk( 'user_id', $this->mId ); + } - global $wgMemc; - $key = wfMemcKey( 'newtalk', 'ip', $this->getName() ); - $newtalk = $wgMemc->get( $key ); - if( strval( $newtalk ) !== '' ) { - $this->mNewtalk = (bool)$newtalk; - } else { - // Since we are caching this, make sure it is up to date by getting it - // from the master - $this->mNewtalk = $this->checkNewtalk( 'user_ip', $this->getName(), true ); - $wgMemc->set( $key, (int)$this->mNewtalk, 1800 ); + return (int) $result; } - } else { - $this->mNewtalk = $this->checkNewtalk( 'user_id', $this->mId ); - } + ); } return (bool)$this->mNewtalk; } + /** + * Wikia change + * @see SUS-2571 + * + * @return string + */ + private function getNewTalkMemcKey() : string { + if ( $this->isAnon() ) { + return wfMemcKey( 'newtalk', 'ip', $this->getName() ); + } + else { + return wfMemcKey( 'newtalk', 'user', $this->getId() ); + } + } + /** * Return the talk page(s) this user has new messages on. * @return string[] page URLs @@ -1879,15 +1901,11 @@ public function getNewMessageLinks() { * @see getNewtalk() * @param $field String 'user_ip' for anonymous users, 'user_id' otherwise * @param $id String|Int User's IP address for anonymous users, User ID otherwise - * @param $fromMaster Bool true to fetch from the master, false for a slave * @return Bool True if the user has new messages */ - protected function checkNewtalk( $field, $id, $fromMaster = false ) { - if ( $fromMaster ) { - $db = wfGetDB( DB_MASTER ); - } else { - $db = wfGetDB( DB_SLAVE ); - } + protected function checkNewtalk( $field, $id ) { + $db = wfGetDB( DB_SLAVE ); + $ok = $db->selectField( 'user_newtalk', $field, array( $field => $id ), __METHOD__ ); return $ok !== false; @@ -1953,7 +1971,6 @@ public function setNewtalk( $val ) { $field = 'user_id'; $id = $this->getId(); } - global $wgMemc; if( $val ) { $changed = $this->updateNewtalk( $field, $id ); @@ -1961,12 +1978,13 @@ public function setNewtalk( $val ) { $changed = $this->deleteNewtalk( $field, $id ); } - if( $this->isAnon() ) { - // Anons have a separate memcached space, since - // user records aren't kept for them. - $key = wfMemcKey( 'newtalk', 'ip', $id ); - $wgMemc->set( $key, $val ? 1 : 0, 1800 ); - } + // Wikia change - start + // SUS-2571 - store the updated new talk state to avoid database queries + // cast the value to an integer to avoid false cache misses in WikiaDataAccess::cache + global $wgMemc; + $wgMemc->set( $this->getNewTalkMemcKey(), (int) $val, WikiaResponse::CACHE_LONG ); + // Wikia change - end + if ( $changed ) { $this->invalidateCache(); }