<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[3944] sites/trunk/wordpress.org/public_html/wp-content/plugins/support-forums/inc/class-performance-optimizations.php: Support Forums: Cache lastpostmodified and sort by post id rather than post_modified_date.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="http://meta.trac.wordpress.org/changeset/3944">3944</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"http://meta.trac.wordpress.org/changeset/3944","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>jmdodd</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2016-09-03 18:13:25 +0000 (Sat, 03 Sep 2016)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Support Forums: Cache lastpostmodified and sort by post id rather than post_modified_date.

The forums have enough traffic that running a sort by post_modified_gmt over all published posts is very expensive, and the cache is constantly invalidated by new topics and replies.

This uses an alternate query to find the date of the most recent topic or reply and uses that instead of a post_modified lookup. Instead of expiring the cached date when new topics or replies are added, the cached value is used for five minutes.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#sitestrunkwordpressorgpublic_htmlwpcontentpluginssupportforumsincclassperformanceoptimizationsphp">sites/trunk/wordpress.org/public_html/wp-content/plugins/support-forums/inc/class-performance-optimizations.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="sitestrunkwordpressorgpublic_htmlwpcontentpluginssupportforumsincclassperformanceoptimizationsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: sites/trunk/wordpress.org/public_html/wp-content/plugins/support-forums/inc/class-performance-optimizations.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- sites/trunk/wordpress.org/public_html/wp-content/plugins/support-forums/inc/class-performance-optimizations.php   2016-09-03 16:14:56 UTC (rev 3943)
+++ sites/trunk/wordpress.org/public_html/wp-content/plugins/support-forums/inc/class-performance-optimizations.php     2016-09-03 18:13:25 UTC (rev 3944)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -13,6 +13,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                add_filter( 'bbp_after_get_topic_author_link_parse_args', array( $this, 'get_author_link' ) );
</span><span class="cx" style="display: block; padding: 0 10px">                add_filter( 'bbp_after_get_reply_author_link_parse_args', array( $this, 'get_author_link' ) );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                // Don't use post_modified/post_modified_gmt to find the most recent content change.
+               add_filter( 'pre_get_lastpostmodified', array( $this, 'pre_get_lastpostmodified' ), 10, 3 );
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 // Query simplification.
</span><span class="cx" style="display: block; padding: 0 10px">                add_filter( 'bbp_after_has_topics_parse_args', array( $this, 'has_topics' ) );
</span><span class="cx" style="display: block; padding: 0 10px">                add_filter( 'bbp_after_has_replies_parse_args', array( $this, 'has_replies' ) );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -31,6 +34,62 @@
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         * Forum traffic is high enough that we can avoid a query on post_modified_date
+        * and just look at the date on the post with the highest id. This filters
+        * on pre_get_lastpostmodified and caches the result of the simplified query.
+        *
+        * By using a different cache key, we can avoid constantly modifying this and
+        * allow it to time out after five minutes. Otherwise, certain feeds will be
+        * always have a changed status.
+        */
+       public function pre_get_lastpostmodified( $retval, $timezone, $post_type ) {
+               global $wpdb;
+
+               // This is largely derived from _get_last_post_time().
+               $timezone = strtolower( $timezone );
+
+               $cache_key = "wporg:lastpostmodified:$timezone";
+               if ( 'any' !== $post_type ) {
+                       $cache_key .= ':' . sanitize_key( $post_type );
+               }
+               $cache_group = 'wporg-forums-timeinfo';
+
+               $date = wp_cache_get( $cache_key, $cache_group );
+
+               if ( ! $date ) {
+                       if ( 'any' === $post_type ) {
+                               $post_types = get_post_types( array( 'public' => true ) );
+                               array_walk( $post_types, array( $wpdb, 'escape_by_ref' ) );
+                               $post_types = "'" . implode( "', '", $post_types ) . "'";
+                       } else {
+                               $post_types = "'" . sanitize_key( $post_type ) . "'";
+                       }
+
+                       switch ( $timezone ) {
+                               case 'gmt' :
+                                       $date = $wpdb->get_var( "SELECT post_date_gmt FROM $wpdb->posts WHERE post_status = 'publish' AND post_type IN ({$post_types}) ORDER BY `ID` DESC LIMIT 1" );
+                                       break;
+                               case 'blog' :
+                                       $date = $wpdb->get_var( "SELECT post_date FROM $wpdb->posts WHERE post_status = 'publish' AND post_type IN ({$post_types}) ORDER BY `ID` DESC LIMIT 1" );
+                                       break;
+                               case 'server' :
+                                       $add_seconds_server = date( 'Z' );
+                                       $date = $wpdb->get_var( "SELECT DATE_ADD( post_date_gmt, INTERVAL '$add_seconds_server' SECOND ) FROM $wpdb->posts WHERE post_status = 'publish' AND post_type IN ({$post_types}) ORDER BY `ID` DESC LIMIT 1" );
+                                       break;
+                       }
+
+                       if ( $date ) {
+                               wp_cache_set( $cache_key, $date, $cache_group, 5 * MINUTE_IN_SECONDS );
+                       }
+               }
+               if ( empty( $date ) ) {
+                       return $retval;
+               }
+
+               return $date;
+       }
+
+       /**
</ins><span class="cx" style="display: block; padding: 0 10px">          * Optimize queries for has_topics as much as possible.
</span><span class="cx" style="display: block; padding: 0 10px">         */
</span><span class="cx" style="display: block; padding: 0 10px">        public function has_topics( $r ) {
</span></span></pre>
</div>
</div>

</body>
</html>