From 87d2eba43130d7fd1f36d1f3bc7ee6f3a20b8295 Mon Sep 17 00:00:00 2001 From: Aaron Schulz Date: Wed, 25 Mar 2015 22:19:32 -0700 Subject: [PATCH] Introduced User::touch() method to bump the getTouched() value using memcached * This lets some callers avoid the heavyweight invalidateCache() method Bug: T91279 Bug: T92357 Change-Id: I8c1c7ff9c5574f0eca23e7effde199ab13a19231 --- includes/User.php | 54 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/includes/User.php b/includes/User.php index 97eaa5c014..a4ba4a00c3 100644 --- a/includes/User.php +++ b/includes/User.php @@ -204,8 +204,10 @@ class User implements IDBAccessObject { public $mNewpassTime; public $mEmail; - + /** @var string TS_MW timestamp from the DB */ public $mTouched; + /** @var string TS_MW timestamp from cache */ + protected $mQuickTouched; protected $mToken; @@ -429,6 +431,8 @@ class User implements IDBAccessObject { * Save user data to the shared cache */ public function saveToCache() { + global $wgMemc; + $this->load(); $this->loadGroups(); $this->loadOptions(); @@ -442,7 +446,7 @@ class User implements IDBAccessObject { } $data['mVersion'] = self::VERSION; $key = wfMemcKey( 'user', 'id', $this->mId ); - global $wgMemc; + $wgMemc->set( $key, $data ); } @@ -2214,9 +2218,10 @@ class User implements IDBAccessObject { * Called implicitly from invalidateCache() and saveSettings(). */ public function clearSharedCache() { + global $wgMemc; + $this->load(); if ( $this->mId ) { - global $wgMemc; $wgMemc->delete( wfMemcKey( 'user', 'id', $this->mId ) ); } } @@ -2255,6 +2260,31 @@ class User implements IDBAccessObject { } } + /** + * Update the "touched" timestamp for the user + * + * This is useful on various login/logout events when making sure that + * a browser or proxy that has multiple tenants does not suffer cache + * pollution where the new user sees the old users content. The value + * of getTouched() is checked when determining 304 vs 200 responses. + * Unlike invalidateCache(), this preserves the User object cache and + * avoids database writes. + * + * @since 1.25 + */ + public function touch() { + global $wgMemc; + + $this->load(); + + if ( $this->mId ) { + $key = wfMemcKey( 'user-quicktouched', 'id', $this->mId ); + $timestamp = self::newTouchedTimestamp(); + $wgMemc->set( $key, $timestamp ); + $this->mQuickTouched = $timestamp; + } + } + /** * Validate the cache for this account. * @param string $timestamp A timestamp in TS_MW format @@ -2267,10 +2297,26 @@ class User implements IDBAccessObject { /** * Get the user touched timestamp - * @return string Timestamp + * @return string TS_MW Timestamp */ public function getTouched() { + global $wgMemc; + $this->load(); + + if ( $this->mId ) { + if ( $this->mQuickTouched === null ) { + $key = wfMemcKey( 'user-quicktouched', 'id', $this->mId ); + $timestamp = $wgMemc->get( $key ); + if ( !$timestamp ) { + # Set the timestamp to get HTTP 304 cache hits + $this->touch(); + } + } + + return max( $this->mTouched, $this->mQuickTouched ); + } + return $this->mTouched; } -- 2.20.1