API Handlers for WordPress

This has been a busy, fun and productive weekend. I have created three API handlers for WordPress to make interacting with the Github, Bitbucket and New Relic APIs easier from inside WordPress.

I created them to help me fetch information from each of these services, to integrate into a website to display more interesting and dynamic information to the viewers. I hope that they will help others do the same.

You can find the them in my Github repositories, and below, each is a file you could use in the /mu-plugins/ folder or include in a theme/plugin:

Each is fully working and the README.md files contain instructions, lists the available endpoints and gives examples code. None yet cover all available endpoints, just the most commonly useful. I will be expanding the endpoints available, documentation and examples over time.

I have stuck to the WordPress way of doing things on the whole and maintained compatibility with the WordPress requirements (e.g. PHP 5.2). If you have any problems or suggestions I would love to hear them on here or via Github issues.

Blogging Resolution

I have spent the past 6 months making writing half-finished blog posts into an art form. It has been fun and I have certainly improved my writing but I really want to push myself further to improve more. In light of that I have decided to commit to writing at least one blog post each week. I hope that with will spawn interesting posts and help me to improve the quality of my writing.

So beware, this blog will soon become active!

Silent Caching in WordPress

This article is out of date and incorrect, most modern web servers
will not close the connection until after the shutdown hook runs.
I will be publishing a follow up article soon with a better method.

While reviewing the code and performance of my latest plugin, the Kebo Twitter Feed, I realised that the Widget was causing significant delays in page load time. While the majority of page loads only involved a 0.002 second increase from the Widget due to caching, when the cache had expired it was causing a delay of 0.6 seconds.

The delay when refreshing the cache is caused by the need to request the users latest Tweets using the v1.1 Twitter API. Realising that there was no way I could make this significantly faster, I needed to find a way to improve the process of refreshing the cache.

I was currently using a Transient, the inbuilt caching system for WordPress, in the default way. Which allows you to save data like this:

[code lang="php"]
<?php

// takes 'name', 'data' and 'expiry time'.
set_transient( 'transient_name', $data, 5 * MINUTE_IN_SECONDS );

?>
[/code]

Once stored, you can then request it at any point using this:

[code lang="php"]
<?php

if ( false === ( $data = get_transient( 'transient_name' ) ) ) {

// Cache has expired, need to refresh data

}

// We have the data, continue

?>
[/code]

The problem with this is that if the cache has expired, the function returns false and you must refresh the cache immediately. Being forced to refresh the cache immediately causes my problem, as in the middle of rendering the Widget, I must make a request to the Twitter API for the users latest Tweets.

So what could I do? What I needed was two levels to my caching, a soft expire which would still return the data and a hard expire like the current Transient. I opted to use a long term expire (24 hours) for the Transient and then add my own soft expire time to the data in the Transient. This allows me to call the Transient and then check my own soft expire time, if this has expired I can use the current data and then refresh the cache after the page has loaded. This involved changes to way I set the Transient:

[code lang="php"]
<?php

// Add soft expire time to the data stored
$data['expiry'] = time() + ( 5 * MINUTE_IN_SECONDS );

// Set transient using name, data and expire time.
set_transient( 'transient_name', $data, 5 * MINUTE_IN_SECONDS );

?>
[/code]

As you can see above, we add a custom ‘soft’ expire time to the data we are going to store, which we will use later on when we call the Transient to test if it has soft expired. Time to see how that is done:

[code lang="php"]
<?php

// Check for hard expire
if ( false === ( $data = get_transient( 'transient_name' ) ) ) {

// Cache has hard expired, need to refresh data

}

// Check for soft expire
elseif ( $data['expiry'] < time() ) {

// Cache has soft expired, need to refresh data

}

// We have the data, continue

?>
[/code]

We have dealt with storing the data as needed, but we are still left with a big problem. How do we refresh the cache after the page has loaded? The search for the solution to this led me to the shutdown hook, which runs just before PHP shuts down execution. This allows us to set code to run after the page has been rendered, all that is left is to put all this together while making sure we only try to update the cache in the background once. The final code to call the Transient looks like this:

[code lang="php"]
<?php

// Check for hard expire
if ( false === ( $data = get_transient( 'transient_name' ) ) ) {

// Cache has expired, need to refresh data

}

// Check for soft expire
elseif ( $data['expiry'] < time() ) {

// Set silent cache to refresh after page load.
add_action( 'shutdown', 'pb_silent_cache_refresh' );

// Add 10 seconds to soft expire, to stop
// other threads trying to update it at the same time.
$data['expiry'] = ( $data['expiry'] + 10 );

// Update soft expire time.
set_transient( 'transient_name', $data, 24 * HOUR_IN_SECONDS );

}

// We have the data, continue

?>
[/code]

If we detect that our data has soft expired, we tell WordPress to run our function which will refresh the cache data after the page has rendered. We then need to make sure that, if many simultaneous page requests are coming through, we don’t try to refresh our cache many times at once.

To accomplish this we add 10 seconds to our soft expiry time, which will prevent most other page requests from detecting the cache needs to be refreshed. The 10 second extension also means that if our background update fails for any reason, like a Twitter API call timing out, we can attempt to refresh it again soon. The last task is to create our function which will update the cache after the page has rendered:

[code lang="php"]
<?php

function pb_silent_cache_refresh() {

// Refresh the data to be cached
// Add soft expire time to the data stored
$data['expiry'] = time() + ( 5 * MINUTE_IN_SECONDS );

// Set transient using name, data and expire time.
set_transient( 'transient_name', $data, 24 * HOUR_IN_SECONDS );

}

?>
[/code]

This gives you the ability to refresh cached items which take a significant amount of time to process without impacting page load speed and this technique is being used live on my Kebo Twitter Feed plugin. If have any ideas and suggestions for making this even better, I would love to hear from you. Happy caching!

New Site

I am really pleased to finally put the new design of my site live. I have scrapped the content too, as I will using the website in a different way. I believe this site is a lot more fitting for the work I currently do and a much better reflection of myself.

Mostly I will be using the site to house the electrical impluses which race around my brain, otherwise known as thoughts. Occasionally combined with information about fun side projects I am doing.

Keep an eye out and you will soon see much more content soon!