Disable Object Cache Addition/Invalidation in WordPress

You can temporarily disable object caching in WordPress‬ by calling:

wp_suspend_cache_addition( true );

Ref. You can turn addition back on by passing false as the only argument. There’s a similar approach for object cache invalidation. However, there’s a big chance persistent object caching plugins won’t implement these functions like WordPress built-in object caching does, so they might be unreliable if working in an unknown environment.

Get an Expired Transient in WordPress: Good Idea or Crazy Talk?

I wonder if there’s an easy way to get an expired transient in WordPress? Now, for this to make sense I guess I should provide a little more context, so here it goes :)

The Transients API is an extremely easy way to cache parts of your WordPress code, that may be CPU/memory intensive, or rely on a third-party server and so on. A great example is grabbing a tweet from Twitter and caching it for a few minutes, so that we don’t query the Twitter API on every page load. So in theory:

if ( false === ( $tweet = get_transient( 'my_latest_tweet' ) ) ) {
    $tweet = get_my_latest_tweet(); // Queries the Twitter API
    set_transient( 'my_latest_tweet', $tweet, 60*60 );

Is a great way to cache my latest tweet for an hour. Perfect, but there’s a problem. The code above will work well for 60 minutes. When the transient expires, it will have to spend time again to fetch the tweet, thus impacting your page load time. Once every 60 minutes.

Suppose Twitter is being slow today and taking 2 seconds to respond back, and suppose I want to cache the tweet for 5 minutes, not an hour. This means that every 5 minutes, somebody will have to wait two extra seconds for my page to load. Suppose I’m querying the Flickr API, the Facebook API and fetching a few RSS feeds too, that will all add up to the page load time, to that unlucky person who visited my site, when the cache was expired. Bummer!

Is there a solution? I don’t know, but I can think of one — always serve cached data, even if it’s expired. That way visitors will never have to wait extra when you’re speaking to third party servers and APIs. I can think of a way to accomplish this by fetching the new data in a different request, transparent to the user.

Like an asynchronous request with jQuery (aka AJAX) to a special action that would revalidate expired cache. Crazy talk? Here’s the scenario:

  1. You visit your page when caches are empty, you don’t see the tweet.
  2. An async jQuery request is fired to the server which grabs the latest tweet and caches it, this happens behind your back.
  3. You refresh the page and you see the tweet from cache. Yey!
  4. Ten minutes have passed, cache is expired, but not trashed. You visit your page, you see the old tweet from (expired) cache.
  5. An async request in the back fetches a new tweet from Twitter and replaces the one expired.
  6. You refresh the page and you see the (new) tweet from cache. Yey!

So in steps 1, 3, 4 and 6 you’re always serving what’s in cache, whether it expired or not, even if it’s empty (first step) so you’re serving as fast as possible. Steps 2 and 5 happen behind your back, they don’t impact page load time, and they never return anything back. You won’t see them happening unless you’re looking at your Netwok tab in Chrome’s developer tools or Firebug.

Now, suppose Twitter is down. The visible steps are not impacted, because they return stored data, they don’t have to fetch it from Twitter. The hidden steps will fail, but your visitors will never know, since they’ll be still seeing the old tweet fetched some time earlier, right?

This can easily be done with the Options API but hey, transients are already a great tool for caching. Wouldn’t it be even easier if transients never actually expired? And a function to fetch such an expired transient, get_expired_transient perhaps? :)

Okay, that’s just off the top of my head, it’s quite late so, sorry if I’m totally on the wrong track. Let me know if there’s an easier solution, or maybe a caching plugin that already does this. Object caching can benefit too by the way. Share your thoughts in the comments section below!

Every Millisecond Counts: Page Speed for Firebug

Here’s a little video that we’ve seen at Arvind’s and Sreeram’s presentation about speeding up the web at the Google Developer Day 2009 conference in Moscow. Inspiring isn’t it?

Arvind and Sreeram talked about a very nice plugin for Firefox (built upon Firebug) which is called Page Speed, developed and maintained by the Googlers. You may read more about the plugin on the official page at Google Code: Page Speed for Firefox/Firebug plus a bunch of cool tips and tricks right here: Let’s make the web faster. I used to run with one called YSlow by Yahoo, but the Googlers seem to have made a better job.

I ran the speed tests on my homepage and got quite a few sweet suggestions, mainly about combining and minifying my CSS and JavaScript files, distributing static content to different cookie-less domains and a couple more. Well combining and minifying CSS and JS would have been quite difficult in WordPress due to the series of plugins that use their own, if it weren’t of course for the W3 Total Cache plugin. In only a few minutes I managed to combine all javascript and stylesheets into single minified versions, which were recreated whenever a plugin was updated. After doing that, running the same test didn’t yield out that problem anymore. Distributing static content to different domains, well that’s one more issue that would have been solved by that brilliant cache plugin and its CDN features, but I guess I’ll have to wait for Amazon CloudFront compatibility.

One more thing I love about Page Speed is that not only they state the problem, but also provide the solution, or at least an easy guide to the solution. Now with a few warnings left, my Page Speed overall performance is okay. I hope to optimize that later this month for even faster access, and perhaps sign up with a PubSubHubbub service (Brett Slatkin had a fantastic presentation on that one at GDD too), and I can finally pronounce that correctly, Hubbub for short.

WordPress: The template_redirect Hook Returns 404

This is a real quick one. I’ve started using the W3 Total Cache plugin a few days ago which I’m totally satisfied with. Unlike the WP Super Cache plugin, W3TC can keep the caches in memory via memcached, serve the static content through CDNs. The guys at W3 Edge promised to add Amazon CloudFront compatibility which I’m very excited about. As we all know (I guess) Mashable is running WordPress, and guess what! They’re using W3 Total Cache too, so if they could trust those guys, then I’m totally in. Their support over Twitter is awesome, you don’t even have to look for them! Just tweet your problem mentioning “W3 Total Cache” or “W3TC” – they’ll find you via search and help you solve whatever your issue is.

Anyways, that being said, after writing my post announcements to Twitter via Twitter Friendly Links some peeps shouted out that I was returning 404 errors on all of my short links. Strange, thought I, as I was able to see everything fine. Looking at the settings of the plugin I realized that I, as a logged in user, weren’t looking at cached pages, so I turned that off and guess what! I got those 404s. Creepy! After a little talk over Twitter and IM with the guys at W3 Edge, I started to look through the caching plugin code. It’s so well-written and I’ve actually learned a couple of techniques out there! Anyways, the reason I was getting 404s was because W3 TC looked at the $wp_query object and it’s $is_404 variable, which I don’t know why (Frederick from W3 Edge mentioned a redirection issue with WordPress) was returning true on all of my Twitter friendly links!

I figured out that the template_redirect hook (which is not documented in the WordPress Codex at all) didn’t quite do what I wanted it to. The easiest way out was adding a couple of lines before the redirect actually happened:

global $wp_query;
$wp_query->is_404 = false;

And guess what, it worked! This may be not the smartest decission but hey, it’s working! One more workaround would be adding a regular expression to the W3 Total Cache page settings, exclude “[0-9]+/?$” which would not cache any .com/1234 queries, but that’s not so reliable for a couple of reasons. First, why not cache if we can cache? And second, what if we’re using Twitter Friendly Links in alphanumeric mode? That would mean “[0-9a-zA-Z]+/?$” which would probably match for all the other top-level pages, thus we’re losing all the benefits from caching. Meh!

I guess this is not the only place where the template_redirect action would return a 404. Some plugins that define their own permalinks through the template_redirect hook (WP Polls for poll results for instance, not sure though) will also get 404s if they don’t set it to false in $wp_query. Many wordpress websites have profile pages which are not actual pages in the database, but are handled through the template_redirect action for .com/profile_name sort of permalinks which is indeed cool. I’m actually planning on using it with one of my upcoming projects and I’m really glad I sorted it out.

So the big shoutout goes to W3 Total Cache and the W3 Edge team!

Foller.me: MySQL Tweaking & Optimization

As I mentioned in the interview with @enked on his website Chidimar.com, I had serious problems with MySQL database optimization on the Foller.me project. The current public stable version (beta-1) is using the MyISAM engine and it’s not holding much data – profiles, locations, geo points for the followers geography.

In the new version (currently dev-1 and hopefully beta-2 in a few days) I changed most of the old tables and added new ones, and using InnoDB this time. You see, it’s not very easy to scan through ~1,000,000 relations for the @mashable account ;) and I bumped into a ~10 second delay before the @mashable profile showed up at Foller.me. Slow query showed that one of the simplest queries caused that slow-mo – it took 6 seconds to execute! The guys at Stack Overflow helped me optimize the query and the two tables I was having problems with, so I came down to ~2 seconds for that query, neat!

Digging further I managed to tune the MySQL server up a little bit (caching, all sorts of buffers, etc – you should definitely take a look at MySQLTuner, it’s a perl script that helps you tune pretty much all the MySQL config) which decreased the query execution time to 1 s. The peeps at Stack Overflow said it’s pretty okay for that kind of query to execute for 3 seconds on over 2 million rows, so I thought that 1 second is final. Phew! :)

Now, think about the MySQL query cache. It doesn’t work in my situation, simply because I shoot UPDATEs and INSERTs at the relations table every five minutes or so (via a cron job), so there actually is a way to perform even higher. Thought of temporary tables, views and triggers (and even stored procedures). Nah.. Simply caching that query would be good, right? I mean if I cache the whole profile for an hour, why wouldn’t I cache the relations result set? Cache the query.. Aha, but I thought slightly further. Why not cache the whole page with memcached? I’ll keep you updated with the results.

Linux Dummy: Unscheduled Maintenance

If anyone of you have tried to access the blog yesterday night, you might have noticed that nothing was working. Sorry! I’ll say it straight, it’s completely my fault. Yesterday evening I decided to set up a cron job for automatic backups on my VPS – a full MySQL dump and a compressed archive of the www directory. So I got a couple of error messages stating that I don’t have the right to access some files which were in the wp-content/upload and wp-content/cache folders… I was frustrated!

Next… Never attempt to do this, okay? I logged in as root, changed owner on all files and folders including sub-folders of the www directory, set it to kovshenin:kovshenin. Voila, the backup worked! In a couple of minutes my VPS ran out of memory and I couldn’t even logon via SSH to reboot the server!

Now that’s funny! I called my hosting provider this morning and asked them what happened? They said everything’s fine, rebooted my server. I managed to logon by SSH, ran the “top” command, and looked at my memory usage growth! 100% was reached in 17 minutes, and bang! Disconnect. Two more calls to my provider didn’t help. They said that the only thing they can do is reset my yesterday’s VPS state completely.

So what really happened? I’m not sure but I bet it’s the WP-Super Cache plugin for WordPress! You see, cached files were created by the user that the httpd (apache) daemon ran – thus, one called “webmaster”. The user “kovshenin” apperantly didn’t have access to those files, and the change owner command spoiled all the cache! Now the static files were owned by “kovshenin”, and “webmaster” (apache) didn’t have any rights for those files. WP-Super Cache must have been in an infinite loop trying to access those, and of course, with no luck – therefore memory leak.

After another reboot I managed to quickly get into the WordPress control panel, enable Maintenance Mode and disable all the other plugins. Enabled them one by one. Setting 0777 as the rights for the cache directory and two WP-Super Cache config files solved the problem. The site was working fine again, and the new generated cache files were owned by “webmaster”… The day has been saved.

But what about the backups? Finally, I came to a thought that both “kovshenin” and “webmaster” users should be in the same groups. So I added “webmaster” to the “kovshenin” group, and “kovshenin” to the “webmaster”. Everything’s great! Apart from the fact that my Google Analytics now shows 0 visitors for 21.05.2009. Jeez, what a dummy…

Give WordPress the iPhone Look: wpTouch Plugin

I don’t want to talk much about the wpTouch plugin, cause it’s all well documented over here. I’m writing this post for those of you who are afraid to make the first step to the terrific handheld view. Yeah, iPhone has got the Safari browser which can show my page just as it is shown on PC, and it even executes javascript! That’s the main reason why people don’t bother switching (others think that they’ll get the iPhone view on PC, duh!). But you… You should try it! Look at what I got to!

It took me about 10 minutes to set this whole thing up. It was messy with the WP Super Cache plugin serving cached pages to my iPhone, but thanks god I noticed that checkbox called ‘Mobile device support’. That saved me loads of time. Works okay now. Don’t forget to add your Google Analytics tracking code to track your mobile visitors!

BTW check out the code snippet I wrote for my brand new huge tag cloud thanks to the PHP-Exec plugin and the power of WordPress.