Skip to content
This repository has been archived by the owner on Jun 7, 2023. It is now read-only.

SUS-2571 | update the memcache when User::setNewtalk() is called #13507

Merged
merged 2 commits into from
Aug 8, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 57 additions & 39 deletions includes/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -1953,20 +1971,20 @@ public function setNewtalk( $val ) {
$field = 'user_id';
$id = $this->getId();
}
global $wgMemc;

if( $val ) {
$changed = $this->updateNewtalk( $field, $id );
} else {
$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();
}
Expand Down