* Changed the expiry time strategy, now treating any request to ResourceLoader::respo...
authorTrevor Parscal <tparscal@users.mediawiki.org>
Mon, 13 Sep 2010 23:19:05 +0000 (23:19 +0000)
committerTrevor Parscal <tparscal@users.mediawiki.org>
Mon, 13 Sep 2010 23:19:05 +0000 (23:19 +0000)
* Added some release notes for ResourceLoader globals.
* Changed when OutputPage appends timestamps to style/script-only requests - now they are only made into versioned requests if the module is a ResourceLoaderWikiModule or a ResourceLoaderUserPreferencesModule - because they might be changed on-wiki and require immediate feedback. This would only affect logged-in users however, as cached pages will contain the latest version number as of the time they were generated. This strategy may need to be adjusted to work with ESI to add version parameters to everything all the time, but this at least presents a reasonable fallback in the event that ESI is not setup.

RELEASE-NOTES
includes/DefaultSettings.php
includes/OutputPage.php
includes/ResourceLoader.php
includes/ResourceLoaderContext.php
includes/ResourceLoaderModule.php

index 81ae1ec..8ac2531 100644 (file)
@@ -54,7 +54,14 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
   $wgUseMemCached, $wgDisableSearchContext, $wgColorErrors,
   $wgUseZhdaemon, $wgZhdaemonHost and $wgZhdaemonPort.
 * (bug 24408) The include_path is not modified in the default LocalSettings.php
-* $wgVectorExtraStyles has been removed, and is no longer in use.
+* $wgVectorExtraStyles was removed, and is no longer in use.
+* $wgLoadScript was added to specify alternative locations for ResourceLoader
+  requests.
+* $wgResourceLoaderVersionedClientMaxage, $wgResourceLoaderVersionedServerMaxage,
+  $wgResourceLoaderUnversionedClientMaxage and
+  wgResourceLoaderUnversionedServerMaxage were added to specify maxage and
+  smaxage times for responses from ResourceLoader based on whether the request's
+  URL contained a version parameter or not.
 
 === New features in 1.17 ===
 * (bug 10183) Users can now add personal styles and scripts to all skins via
index af68a55..dcb6f95 100644 (file)
@@ -1645,17 +1645,30 @@ $wgUseETag = false;
 $wgClockSkewFudge = 5;
 
 /**
- * Maximum time in seconds to cache resources served by the resource loader on
- * the client side (e.g. in the browser cache).
+ * Maximum time in seconds to cache versioned resources served by the resource
+ * loader on the client side (e.g. in the browser cache).
  */
-$wgResourceLoaderClientMaxage = 30*24*60*60; // 30 days
+$wgResourceLoaderVersionedClientMaxage = 30 * 24 * 60 * 60; // 30 days
 
 /**
- * Maximum time in seconds to cache resources served by the resource loader on
- * the server side. This means Squid/Varnish but also any other public proxy
- * cache between the client and MediaWiki.
+ * Maximum time in seconds to cache versioned resources served by the resource
+ * loader on the server side. This means Squid/Varnish but also any other public
+ * proxy cache between the client and MediaWiki.
  */
-$wgResourceLoaderServerMaxage = 30*24*60*60; // 30 days
+$wgResourceLoaderVersionedServerMaxage = 30 * 24 * 60 * 60; // 30 days
+
+/**
+ * Maximum time in seconds to cache unversioned resources served by the resource
+ * loader on the client.
+ */
+$wgResourceLoaderUnversionedClientMaxage = 5 * 60; // 5 minutes
+
+/**
+ * Maximum time in seconds to cache unversioned resources served by the resource
+ * loader on the server. This means Squid/Varnish but also any other public
+ * proxy cache between the client and MediaWiki.
+ */
+$wgResourceLoaderUnversionedServerMaxage = 5 * 60; // 5 minutes
 
 /**
  * Enable data URL embedding (experimental). This variable is very temporary and
index b8d99b8..1028e06 100644 (file)
@@ -2302,14 +2302,25 @@ class OutputPage {
                                if ( $group === 'user' ) {
                                        $query['user'] = $wgUser->getName();
                                }
-                               $context = new ResourceLoaderContext( new FauxRequest( $query ) );
+                               // Users might change their stuff on-wiki like site or user pages, or user preferences; we need to find
+                               // the highest timestamp of these user-changable modules so we can ensure cache misses upon change
                                $timestamp = 0;
                                foreach ( $modules as $name ) {
-                                       if ( $module = ResourceLoader::getModule( $name ) ) {
-                                               $timestamp = max( $timestamp, $module->getModifiedTime( $context ) );
+                                       $module = ResourceLoader::getModule( $name );
+                                       if (
+                                               $module instanceof ResourceLoaderWikiModule ||
+                                               $module instanceof ResourceLoaderUserPreferencesModule
+                                       ) {
+                                               $timestamp = max(
+                                                       $timestamp,
+                                                       $module->getModifiedTime( new ResourceLoaderContext( new FauxRequest( $query ) ) )
+                                               );
                                        }
                                }
-                               $query['version'] = wfTimestamp( TS_ISO_8601, round( $timestamp, -2 ) );
+                               // Add a version parameter if any of the modules were user-changable
+                               if ( $timestamp ) {
+                                       $query['version'] = wfTimestamp( TS_ISO_8601, round( $timestamp, -2 ) );
+                               }
                                // Make queries uniform in order
                                ksort( $query );
                                // Automatically select style/script elements
index f16f248..56437fb 100644 (file)
@@ -24,6 +24,7 @@
  * Dynamic JavaScript and CSS resource loading system
  */
 class ResourceLoader {
+
        /* Protected Static Members */
 
        // @var array list of module name/ResourceLoaderModule object pairs
@@ -188,6 +189,9 @@ class ResourceLoader {
         * @param $context ResourceLoaderContext object
         */
        public static function respond( ResourceLoaderContext $context ) {
+               global $wgResourceLoaderVersionedClientMaxage, $wgResourceLoaderVersionedServerMaxage;
+               global $wgResourceLoaderUnversionedServerMaxage, $wgResourceLoaderUnversionedClientMaxage;
+
                // Split requested modules into two groups, modules and missing
                $modules = array();
                $missing = array();
@@ -200,33 +204,31 @@ class ResourceLoader {
                        }
                }
 
-               // Calculate the mtime and caching maxages for this request. We need this, 304 or no 304
-               $mtime = 1;
-               $maxage = PHP_INT_MAX;
-               $smaxage = PHP_INT_MAX;
+               // If a version wasn't specified we need a shorter expiry time for updates to propagate to clients quickly
+               if ( is_null( $context->getVersion() ) ) {
+                       $maxage = $wgResourceLoaderUnversionedClientMaxage;
+                       $smaxage = $wgResourceLoaderUnversionedServerMaxage;
+               }
+               // If a version was specified we can use a longer expiry time since changing version numbers causes cache misses
+               else {
+                       $maxage = $wgResourceLoaderVersionedClientMaxage;
+                       $smaxage = $wgResourceLoaderVersionedServerMaxage;
+               }
 
+               // To send Last-Modified and support If-Modified-Since, we need to detect the last modified time
+               $mtime = 1;
                foreach ( $modules as $name ) {
                        $mtime = max( $mtime, self::$modules[$name]->getModifiedTime( $context ) );
-                       $maxage = min( $maxage, self::$modules[$name]->getClientMaxage() );
-                       $smaxage = min( $smaxage, self::$modules[$name]->getServerMaxage() );
-               }
-
-               // Output headers
-               if ( $context->getOnly() === 'styles' ) {
-                       header( 'Content-Type: text/css' );
-               } else {
-                       header( 'Content-Type: text/javascript' );
                }
 
+               header( 'Content-Type: ' . ( $context->getOnly() === 'styles' ? 'text/css' : 'text/javascript' ) );
                header( 'Last-Modified: ' . wfTimestamp( TS_RFC2822, $mtime ) );
-               $expires = wfTimestamp( TS_RFC2822, min( $maxage, $smaxage ) + time() );
                header( "Cache-Control: public, max-age=$maxage, s-maxage=$smaxage" );
-               header( "Expires: $expires" );
+               header( 'Expires: ' . wfTimestamp( TS_RFC2822, min( $maxage, $smaxage ) + time() ) );
 
-               // Check if there's an If-Modified-Since header and respond with a 304 Not Modified if possible
+               // If there's an If-Modified-Since header, respond with a 304 appropriately
                $ims = $context->getRequest()->getHeader( 'If-Modified-Since' );
-
-               if ( $ims !== false && wfTimestamp( TS_UNIX, $ims ) == $mtime ) {
+               if ( $ims !== false && $mtime >= wfTimestamp( TS_UNIX, $ims ) ) {
                        header( 'HTTP/1.0 304 Not Modified' );
                        header( 'Status: 304 Not Modified' );
                        return;
index c9b1bd3..269712a 100644 (file)
@@ -33,6 +33,7 @@ class ResourceLoaderContext {
        protected $user;
        protected $debug;
        protected $only;
+       protected $version;
        protected $hash;
 
        /* Methods */
@@ -49,6 +50,7 @@ class ResourceLoaderContext {
                $this->user = $request->getVal( 'user' );
                $this->debug = $request->getBool( 'debug' ) && $request->getVal( 'debug' ) === 'true';
                $this->only = $request->getVal( 'only' );
+               $this->version = $request->getVal( 'version' );
 
                // Fallback on system defaults
                if ( !$this->language ) {
@@ -63,7 +65,7 @@ class ResourceLoaderContext {
                        $this->skin = $wgDefaultSkin;
                }
        }
-       
+
        public function getRequest() {
                return $this->request;
        }
@@ -96,6 +98,10 @@ class ResourceLoaderContext {
                return $this->only;
        }
 
+       public function getVersion() {
+               return $this->version;
+       }
+
        public function shouldIncludeScripts() {
                return is_null( $this->only ) || $this->only === 'scripts';
        }
@@ -111,7 +117,7 @@ class ResourceLoaderContext {
        public function getHash() {
                return isset( $this->hash ) ?
                        $this->hash : $this->hash = implode( '|', array(
-                               $this->language, $this->direction, $this->skin, $this->user, $this->debug, $this->only
+                               $this->language, $this->direction, $this->skin, $this->user, $this->debug, $this->only, $this->version
                        ) );
        }
 }
\ No newline at end of file
index 6fb4c78..7f57e41 100644 (file)
@@ -50,30 +50,6 @@ abstract class ResourceLoaderModule {
                $this->name = $name;
        }
 
-       /**
-        * The maximum number of seconds to cache this module for in the
-        * client-side (browser) cache. Override this only if you have a good
-        * reason not to use $wgResourceLoaderClientMaxage.
-        *
-        * @return Integer: cache maxage in seconds
-        */
-       public function getClientMaxage() {
-               global $wgResourceLoaderClientMaxage;
-               return $wgResourceLoaderClientMaxage;
-       }
-
-       /**
-        * The maximum number of seconds to cache this module for in the
-        * server-side (Squid / proxy) cache. Override this only if you have a
-        * good reason not to use $wgResourceLoaderServerMaxage.
-        *
-        * @return Integer: cache maxage in seconds
-        */
-       public function getServerMaxage() {
-               global $wgResourceLoaderServerMaxage;
-               return $wgResourceLoaderServerMaxage;
-       }
-
        /**
         * Get whether CSS for this module should be flipped
         */
@@ -1013,14 +989,6 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                return $this->modifiedTime[$hash];
        }
 
-       public function getClientMaxage() {
-               return 300; // 5 minutes
-       }
-
-       public function getServerMaxage() {
-               return 300; // 5 minutes
-       }
-
        public function getFlip( $context ) {
                global $wgContLang;