Merge "Use adaptive CDN TTLs for page views"
[lhc/web/wiklou.git] / includes / OutputPage.php
index a69c0e6..863a426 100644 (file)
@@ -1782,7 +1782,9 @@ class OutputPage extends ContextSource {
                }
 
                // Include profiling data
-               $this->setLimitReportData( $parserOutput->getLimitReportData() );
+               if ( !$this->limitReportData ) {
+                       $this->setLimitReportData( $parserOutput->getLimitReportData() );
+               }
 
                // Link flags are ignored for now, but may in the future be
                // used to mark individual language links.
@@ -1931,6 +1933,36 @@ class OutputPage extends ContextSource {
                $this->setCdnMaxage( $this->mCdnMaxage );
        }
 
+       /**
+        * Get TTL in [$minTTL,$maxTTL] in pass it to lowerCdnMaxage()
+        *
+        * This sets and returns $minTTL if $mtime is false or null. Otherwise,
+        * the TTL is higher the older the $mtime timestamp is. Essentially, the
+        * TTL is 90% of the age of the object, subject to the min and max.
+        *
+        * @param string|integer|float|bool|null $mtime Last-Modified timestamp
+        * @param integer $minTTL Mimimum TTL in seconds [default: 1 minute]
+        * @param integer $maxTTL Maximum TTL in seconds [default: $wgSquidMaxage]
+        * @return integer TTL in seconds
+        * @since 1.28
+        */
+       public function adaptCdnTTL( $mtime, $minTTL = 0, $maxTTL = 0 ) {
+               $minTTL = $minTTL ?: IExpiringStore::TTL_MINUTE;
+               $maxTTL = $maxTTL ?: $this->getConfig()->get( 'SquidMaxage' );
+
+               if ( $mtime === null || $mtime === false ) {
+                       return $minTTL; // entity does not exist
+               }
+
+               $age = time() - wfTimestamp( TS_UNIX, $mtime );
+               $adaptiveTTL = max( .9 * $age, $minTTL );
+               $adaptiveTTL = min( $adaptiveTTL, $maxTTL );
+
+               $this->lowerCdnMaxage( (int)$adaptiveTTL );
+
+               return $adaptiveTTL;
+       }
+
        /**
         * Use enableClientCache(false) to force it to send nocache headers
         *
@@ -2390,10 +2422,14 @@ class OutputPage extends ContextSource {
        /**
         * Output a standard permission error page
         *
-        * @param array $errors Error message keys
+        * @param array $errors Error message keys or [key, param...] arrays
         * @param string $action Action that was denied or null if unknown
         */
        public function showPermissionsErrorPage( array $errors, $action = null ) {
+               foreach ( $errors as $key => $error ) {
+                       $errors[$key] = (array)$error;
+               }
+
                // For some action (read, edit, create and upload), display a "login to do this action"
                // error if all of the following conditions are met:
                // 1. the user is not logged in
@@ -2686,15 +2722,13 @@ class OutputPage extends ContextSource {
                        $exemptStates = [];
                        $moduleStyles = $this->getModuleStyles( /*filter*/ true );
 
-                       // Batch preload getTitleInfo for isKnownEmpty() calls below
-                       $exemptModules = array_filter( $moduleStyles,
-                               function ( $name ) use ( $rl, &$exemptGroups ) {
-                                       $module = $rl->getModule( $name );
-                                       return $module && isset( $exemptGroups[ $module->getGroup() ] );
-                               }
-                       );
-                       ResourceLoaderWikiModule::preloadTitleInfo(
-                               $context, wfGetDB( DB_REPLICA ), $exemptModules );
+                       // Preload getTitleInfo for isKnownEmpty calls below and in ResourceLoaderClientHtml
+                       // Separate user-specific batch for improved cache-hit ratio.
+                       $userBatch = [ 'user.styles', 'user' ];
+                       $siteBatch = array_diff( $moduleStyles, $userBatch );
+                       $dbr = wfGetDB( DB_REPLICA );
+                       ResourceLoaderWikiModule::preloadTitleInfo( $context, $dbr, $siteBatch );
+                       ResourceLoaderWikiModule::preloadTitleInfo( $context, $dbr, $userBatch );
 
                        // Filter out modules handled by buildExemptModules()
                        $moduleStyles = array_filter( $moduleStyles,
@@ -2929,12 +2963,14 @@ class OutputPage extends ContextSource {
                        }
                }
 
-               $chunks[] = ResourceLoader::makeInlineScript(
-                       ResourceLoader::makeConfigSetScript(
-                               [ 'wgPageParseReport' => $this->limitReportData ],
-                               true
-                       )
-               );
+               if ( $this->limitReportData ) {
+                       $chunks[] = ResourceLoader::makeInlineScript(
+                               ResourceLoader::makeConfigSetScript(
+                                       [ 'wgPageParseReport' => $this->limitReportData ],
+                                       true
+                               )
+                       );
+               }
 
                return self::combineWrappedStrings( $chunks );
        }