7

You would think that a transient set to expire at a certain time, would exist until that time. Unfortunately it seems they are disappearing from the database earlier, both on test and production. As a simple example to see this behavior, try:

<?php
/*
Plugin Name: Test transient
Description: Show transients bug
Version: 0.1
*/

add_action( 'wp_head', 'doAnAlert' );

function doAnAlert()
{
    if( !get_transient( 'my_messageDismiss' ) )
    {
        //Transient nonexistent or expired
        ?><script> alert("This alert should also show again in 24hr"); </script>
        <?php

        set_transient( 'my_messageDismiss', 'dismissed', 86400); //Set for a day
    }

}

So what am I missing about the Transients API? The alert shows hours later, not a day later.

  • Any hit to your site however inconsequential will trigger that alert and regen the transient, you may want to use a better test, such as a check for is_admin to ensure that you're the only person checking it, and that no other calls or checks from your browser are unintentionally triggering it. Stronger test controls! – Tom J Nowell May 10 '16 at 19:14
  • @TomJNowell I do, and this is just for purpose of a minimal test, and according to documentation it returns false if the transient does not exist : codex.wordpress.org/Function_Reference/get_transient – NoBugs May 10 '16 at 19:16
  • true, it returns false, I was referring more to when your test is ran, using false === would be better too – Tom J Nowell May 10 '16 at 19:48
10

TL;DR

  • Wordpress part of transient handling is solid, everything is pretty precise
  • Transients use object cache instead of data store for non-default implementations
  • It means that some back-end cache systems get rid of cache that hasn't been accessed recently
  • Bottom line: it's not WordPress fault, it only depends on how your back-end cache is set up

You could get transients to be more precise but it requires back-end cache tweaking which I do not recommended if you don't know what you're doing, too much cache could have opposite effect.

But even then, don't assume that it is 100% precise.


From WordPress Codex:

Everyone seems to misunderstand how transient expiration works, so the long and short of it is: transient expiration times are a maximum time. There is no minimum age. Transients might disappear one second after you set them, or 24 hours, but they will never be around after the expiration time.

You should always have a fall back method.


Why is it happening?!

WordPress only invalidates transients when attempting to read them (which has lead to garbage collection problems in the past). However, this is not guaranteed for other backends.

Transients use the object cache for non-default implementations. The really important part to note here is that the object cache is a cache, and absolutely not a data store. What this means is that the expiration is a maximum age, not a minimum or set point.

One place this can happen easily is with Memcache set in Least Recently Used (LRU) mode. In this mode, Memcache will automatically discard entries that haven’t been accessed recently when it needs room for new entries. This means less frequently accessed data (such as that used by cron data) can be discarded before it expires.

Read more from this article, it is very well explained.


Caching?

There are plenty of different systems but here's an example how MySQL database caching generally works. Im not sure how helpful it is to understand transients caching but I guess it couldn't harm.

  • Data from each different query gets cached
  • Each cached data gets a value (more complicated query == higher value)
  • These values gets decremented (like a countdown timers if you will)
  • Caching system checks these values in intervals
  • If any of these values reaches to zero, that cache gets destroyed
  • If same query is ran again, value goes back to initial value

So.. What could you conclude from that? There's no point to set transient that are:

  • Too simple
  • Not frequently used

Because these gets destroyed very quickly in most cases. I hope this gives you a clearer picture how caching generally works. It prioritizes frequent and complicated over simple and rarely used data.

Note: there's a lot of generalizations in cache explanation to make it easy to follow and understand.

  • Good answer, but this is somewhat incomplete - if transient is caching some request to some server that may take a long time, and ideally it would keep it for the full X minutes, before having to go and make that long request and download data again, how can we tune the cache so it will ignore transient closer to X minutes, rather than say, clearing it every minute and causing more long page loads? – NoBugs May 17 '16 at 0:10
  • No, it's not incomplete, this is totally another subject (even technology) and out of the scope for this site. If you want to know more about that, I would recommend to try another (database, caching related) Stack Exchange sites. Database and caching is so fragile and situational that you would usually need to hire a highly educated engineer to get it right (unless you have a small league site). You will never get a complete and right (for your situation) answer from online Q&A site. There's so many variables, database, software and hardware specs, traffic etc you need to consider. – N00b May 17 '16 at 0:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.