0

I synchronize some data of my plugin with an extern API. This synchronize-process should fire every minute. So I use the following code to do that:

if ( ! get_transient( 'my_task_sync_method' ) ) {
    set_transient( 'my_task_sync_method', true, 1 * MINUTE_IN_SECONDS );
    my_task_sync_method();
}

Currently I run this Code within my plugin initial code. I know this is a workaround and not the normal use case for transient, but it is the best solution I found so far.

This works fine, but sometimes when I reload a backend page (e.g. the dashboard) I'm getting some parts of a custom post admin page, which i have generated. It seems to happen when I reload the page on the time my sync-process is running. It's quite difficult to adjust this incident. But mabye some one know this kind of problem and is able to help me? If there is a better solution to do a synchronization I would be happy if you tell me the better way.

  • hmmm maybe set another transient value while my_task_sync_method is running so that can be detected by the admin page..? then you could display a message saying "Sync Running" and/or put a link to refresh the page. – majick Feb 23 '18 at 13:56
  • you should do better debugging to see if your assumption is actually right. write to a log every time your sync starts and ends which will let you see if the second sync starts before the first ends, and if a sync might simply take more than a minute. – Mark Kaplun Feb 23 '18 at 15:46
2

To my understanding, *_transient() is basically *_option() wrapped in a cache-timer.

What that means in this context, is that set_transient( '...', true, * MINUTE_IN_SECONDS ); will not run/re-evaluate every minute. Instead it will run/re-evaluate when the page has loaded by a visitor/user, and the data therein is older than 60 seconds. This is not ideal because what it does is puts the processing of the sync method onto the users load time, which isn't good, and can mess up, like the hiccup your experiencing - it correlates with this:

It seems to happen when I reload the page on the time my sync-process is running

So your visiting the admin after >60 seconds of no other visits to the site. The _transient is thus expired, and fires your my_task_sync_method() on your page load, which must be echo'ing or interrupting your load processes in some way.


To resolve this, first, you should use Wordpress Cron, not _transient. Cron jobs run in the background, and adhere to the 60-second sync, without relying on users visiting.

Here's a base snippet for a cron task:

// add a 60 second cron schedule
add_filter('cron_schedules', function ( $schedules ) {
    $schedules['everyminute'] = array(
        'interval' => 60,
        'display' => __('Every Minute')
    );
    return $schedules;
});

// register your cronjob
add_action('wp', function () {
    if ( !wp_next_scheduled( 'my_task_sync_cronjob' ) )
        wp_schedule_event(time(), 'everyminute', 'my_task_sync_cronjob');
});

// the registered cron hook, that'll fire your function
add_action('my_task_sync_cronjob', 'my_task_sync_method');

Secondly, you should ensure my_task_sync_method() isn't echo'ing any data. I am assuming it does given your symptoms.


Please note I've placed the functions in the hooks anonymously, I did this for easier display here. You may want to make them callbacks instead incase other developers want to tap into your hooks.

  • Thanks for your answer. Now I'm using Wordpress Cron instead of the transient solution. And it seems to work well, without the wrong wrong custom post page output. But your sentence Cron jobs run in the background, and adhere to the 60-second sync, without relying on users visiting is not correct. If nobody visits the site, the cron job doesn't get fired. – Carsten Schmitt Feb 26 '18 at 11:07
  • You're correct, my bad. – David Sword Feb 26 '18 at 16:57
0

Your synchronization function probably tries to do too much especially if you need to contact external resources.

The proper way to do it is to fetch the information when it is more than a minute stale instead of every minute. This way you are sure to not end up in limbo if a sync failed.

I personally hate transients as they are by design not reliable. You should use an option in which you store the next time an update should be made and check if that time had passed, with maybe an additional "flag" stored in the option that indicates when an update is on the way to prevent double updates.

Additional note: While 1 minute interval should be OK most of the time, my gut feeling is that it is too short. Web servers and web software were not designed to be very accurate about their timings, and the situation in which you site can not have information which is more than one minute stale sounds ridiculous. Assuming you are doing some additional DB writes on each sync, you are taxing your server abilities for something that might not actually be needed.

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.