0

I am running some calculations on custom field data using wp_query on a large number of posts and it is taking a long time to load the result. I was advised by a user here to take advantage of wp cron to run these calculations once daily.

What I've been unable to wrap my head around is - if I create an action which contains all of this code, set it to run once daily, and call this action in a template file, won't those queries then recalculate every time that template is loaded?

My intended result is for the result of the queries to display on a template, but only actually recalculate when initiated by cron.

I feel I'm missing something simple here but all examples of wp cron I can find don't appear to cover my use case.

0

I am using transients for this scenarios. Result is saved to database (wp_options table) with expiration set. It's usable if the slow load time is below some reasonable treshold ... one (first) visitor will have to wait that long to render his request, every other will see saved result.

$results = get_transient('my_results');

if( ! $results ) {

    $results = my_intensive_calculations(); // etc...

    set_transient( 'my_results' , $results, DAY_IN_SECONDS );

}

echo $results;

There is one disadvantage against crons - first visitor will have to wait to my_intensive_calculations() response (cron request runs in background and don't block page rendering). But its result will be cached and every other visitor will see page/template as fast as possible.

| improve this answer | |
  • do you realize that transients are unreliable and the wrong tool for caching? for caching use options. In addition you should do such thing as a cron job not on page load – Mark Kaplun Jul 11 '17 at 4:10
  • Well, it's written in my answer, after all. If getting results will take 5 and more seconds, then page load blocking is a problem, and background cronjob will be better. But setting up WP cron can be overkill sometimes, and I have more problems with WP Cron not firing than with transients. Frankly, I have not had a problem with transients until today. Why they should be unreliable? – Marek Jul 11 '17 at 5:25
  • the question is explicitly on using cron for it and avoiding calculating it on front end requests.... – Mark Kaplun Jul 11 '17 at 6:53
0

Let's assume your code lives in the function calculateCityAverages() which returns (not echo!) your data, probably in form of an array.

To cache the data, you can do many things, custom option, even a post, .. I would use the Transients API

Transients API, which offers a simple and standardized way of storing cached data in the database temporarily by giving it a custom name and a timeframe after which it will expire and be deleted.

Wrap your calculating function in something like this

function getCityAverages($force = FALSE){
    $result = get_transient('my_city_averages');
    // if there is no cached data or we want to refresh cache
    if ($result === FALSE || $force === TRUE) {
        // calculate it
        $result = calculateCityAverages();
        // store it for 12h
        set_transient('my_city_averages', $result, 12 * HOUR_IN_SECONDS);
    }
    return $result;
}

But there is still one problem: For the first visitor - or anytime that the cache is empty - there will be a 40s page load. Only visitors after that will profit from the transient.

To avoid this, you can warm the cache (cold and warm cache?), because this should be done in certain intervals and in the background, use WP-Cron via wp_schedule_event().

It is advised to schedule the event in the activation of the plugin, because this should usually be done only once (the scheduling that is, of course it will run multiple times).

This code is directly from the codex. All you need to do is call getCityAverages(TRUE) (to make sure you recalculate it and not just get it from cache).

register_activation_hook(__FILE__, 'my_activation');

function my_activation() {
    if (! wp_next_scheduled ( 'my_hourly_event' )) {
    wp_schedule_event(time(), 'hourly', 'my_hourly_event');
    }
}

add_action('my_hourly_event', 'do_this_hourly');

function do_this_hourly() {
    // we don't care about the result, just warm cache
    getCityAverages(TRUE);
}

Since you now have tasks that take long in your WP Cron, I suggest using a proper crontab/cronjob instead of how WordPress does it by default.

All that is left, is call getCityAverages() anywhere you need the data.

| improve this answer | |

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.