I’m trying to figure out how to best solve an issue I have with 3rd party API’s (OG, Foursquare, Yelp, etc.). I use the transient API to call and store the various data in order to:
- Not exceed any API limits
- Increase load speed
However, the issue arises when a new API call errors out for whichever reason; either there was an issue with the connection, or the API itself was down (hello foursquare). This leads to a scenario where you have no new data and the old data timed out (which is essentially what triggered a new transient to generate). How do you deal with such situations?
The solution I have in mind is to create a static option within the refresh function that stores a successful response or brings up the last successful response on an error, for example :
<?php
function refresh_api_data() {
... perform API call ...
if ( $response->status == 'error' ) {
$response = get_option( 'fallback_data' );
} else {
update_option( 'fallback_data', $response );
}
return $response;
}
?>
Does this make sense, or does anyone have a more elegant solution in mind?
Thank you!
Mark Jaquith made a “TLC Transients” method that you might find useful. Essentially, it implements a transient interface that does soft expiration and background updating.
https://github.com/markjaquith/WP-TLC-Transients
The idea is that you define a function to do the call that gets the data, then define the transient and pass it that function as a callback. When you make this call, it will get the data if necessary and return it, storing it in a transient for the defined time period. The “soft” updating means that it always returns the cached data immediately, and causes the update to happen after-the-fact, in the background (using a wp-cron job).
This would also have the advantage of always returning the “old” data until a successful update occurs. The way this is handled by his code is that you make your callback function throw an Exception if the retrieval of the data is unsuccessful for whatever reason.
You can set another transient on success with a long timeout. Then if the first one times out and you get an error, you will have your back-up transient. If there is a success both transients get updated.
It’s similar as your idea, so I think you can go either way.
I tend to do the following:
1) Generate the data on a backend event or schedule. The transient is set to last MUCH longer than the I would expect it to be refreshed. I also “back up” the data using
add_option
while setting the option to not autoload. If the API call errors out, I just don’t set the data again and the old data is not touched.2) On display, check for transient. If the transient exists, display it. If not, pull it from the option, display it, then put it back in cache so future requests pull from the cache. I use this method because sometimes in memcached environments, the transients get evicted. Rather than run the heavy request again, I can pull the data from the option.