I'm registering an event like:
wp_schedule_single_event( time(), 'do_custom_hook', array( $body ) );
Above that, I have added the following action:
add_action('do_custom_hook', 'process_custom_hook', 10);
function process_custom_hook($body){
// custom code here
}
However, sometimes the process_custom_hook function fires, while other times, it simply doesn't (it fires most times, though. It's missed about 10%-20% of the time)
The event is always returning true, meaning that it must have registered.
Also, while testing, I made sure that the arguments (body) is always different.
Any reason why this may occur?
From the codex:
Note that scheduling an event to occur before 10 minutes after an existing event of the same name will be ignored, unless you pass unique values for $args to each scheduled event.
If your custom hook is only working some of the time, then this might be an avenue to look at. If you require the hook to be handled immediately, then it might be prudent to look at giving a hook a unique name, or passing unique values to the hook.
If you do not need your job to execute immediately, then you could look at utilising wp_next_scheduled() to determine when the job will next run, and set a job to run after the next scheduled job.
It's also worth noting that if this task is something which seems to have consistent logic behind it (as seems to be the case) - why not store the job information in to the database and run a cron job every 5-10 minutes to pick up any new jobs from the database and handle them as such? This would avoid needing to deal with the behaviour of wp_schedule_single_event().
According to the official documentation on this instance,
Scheduling an event to occur within 10 minutes of an existing event with the same action hook will be ignored unless you pass unique $args values for each scheduled event. which you have stated tht you did but maybe a double check will help.
It is dependent on when a user visits the site so the action will trigger when someone visits your WordPress site if the scheduled time has passed.
Documentation also says you could use wp_next_scheduled() to prevent duplicate events and use wp_schedule_event() to schedule a recurring event.
The schedule might return true in certain instances where it run but was ignored. so it did run but it was ignored.
I would suggest a detailed log of everything that is sent and received so you can see for yourself if what is occuring is same as what you are confident on.
here are a few links with similar issues and documentation you could look at.
I hope this helps. if not, lets figure it out together.
https://developer.wordpress.org/reference/functions/wp_schedule_single_event/
https://wordpress.stackexchange.com/questions/15475/using-wp-schedule-single-event-with-arguments-to-send-email
https://rudrastyh.com/wordpress/wp_schedule_single_event.html
http://hookr.io/functions/wp_schedule_single_event/
From Wordpress Document:
WP-Cron works by checking, on every page load, a list of scheduled
tasks to see what needs to be run. Any tasks due to run will be called
during that page load.
WP-Cron does not run constantly as the system cron does; it is only
triggered on page load.
Scheduling errors could occur if you schedule
a task for 2:00PM and no page loads occur until 5:00PM.
I think your cron event may be missed because there is no page loads occur the scheduled time.
Here is a solution for your problem:
Hooking WP-Cron Into the System Task Scheduler
As previously mentioned, WP-Cron does not run continuously, which can
be an issue if there are critical tasks that must run on time. There
is an easy solution for this. Simply set up your system’s task
scheduler to run on the intervals you desire (or at the specific time
needed). The easiest solution is to use a tool to make a web request
to the wp-cron.php file...
In my case this exact issue occurred when also Woocommerce's action scheduler was running. Action Scheduler is a cron task manager that ships with Woocommerce, but also other plugins like for instance wp-mail-smtp.
I had exactly the same issue and couldn't figure out what was wrong. I've tried to debug the Wordpress code, and came to the conclusion that when a task was scheduled (meaning, the moment it was added to the scheduled tasks) within 10 second of each whole minute, it just got removed straight away. It seemed some sort of racing condition where the action scheduler just popped it of the stack without the normal wp cron being able to execute it, because the task was already gone.
I need to also say, that I've setup crontab calling wp-cron.php every minute on the minute (instead of the 'fake cron' of Wordpress).
When I replaced wp_schedule_single_event with the as_enqueue_async_action function of the Action Scheduler, no tasks were dropped anymore.
I think an alternative is deinstalling anything that uses Action Scheduler, but I haven't tried that.
You are using cron from Wordpress but some plugins disable or prevent CRON from working. My recommendation in this case is either you create this schedule through the Server Cron or you install a plugin to reaffirm your schedule.
I had the same problem it was even a little difficult to find ... And as you will see it doesn't have a current update, but for me it works. https://wordpress.org/plugins/wp-crontrol
&
https://br.wordpress.org/plugins/advanced-cron-manager/
you can identify which Cron you want to edit and thus have more precision in your edition. There are other plugins that can and should be related to this one. you mentioned about cron's schedule. That's why I indicated this one. So, you can know the Chrome configuration on the calendar. WP Cron you can edit your Cron schedule
Related
I came across a situation i want to trigger some code at specific time, i.e when user does booking, the freelancer must accept/reject the booking request, if he doesnt, after x duration (15* mins lets say) it would be rejected and user would get push notification. All code is done but currently im running a cronjob after each 1 minute which checks for any unresponded bookings and checks when their time (15mins, dynamic) passed so then I execute my code for afterward, it is not good i guess as its running db queuries over and over each minute.
I'm aware with laravel queue jobs as well but didnt see anything for me to run that job for a specific time only (i.e execute this job after 15mins, if it isnt responded, reject it)
have you looked at Queue delay?
https://laravel.com/docs/9.x/queues#delayed-dispatching
This sounds like what you are looking for, I would just trigger the queue and delay when they make a booking so it executes 15 minutes after.
Use scheduled tasks.
use App\Console\Commands\SendEmailsCommand;
$schedule->command('emails:send Taylor --force')->daily();
$schedule->command(SendEmailsCommand::class, ['Taylor', '--force'])->daily();
https://laravel.com/docs/9.x/scheduling#scheduling-artisan-commands
On the surface it looks very simple problem that I am facing. In an enterprise web app (LAMP stack) we need to add some time based & schedule based tasks. Some examples are
when a user logs in and has stayed active for more than 30 minutes, send them a lucky coupon.
send a newsletter to subscribers every Monday. [easily handled by a cron job]
If a user does not login for 3 days, start stalking her. [doable by cron job but ...]
deduct phone bill amount from user account on 1st working day of every month at 9.
repeat failed deduction every subsequent work day at 9 for a max of 15 retries.
I hope that give you an idea of what is going on that needs to be handled.
At the moment we have cron jobs of almost every possible situation and they are kind of working but as you can see with the above scenarios, we are forced to run those crons almost every second (bit exaggeration but almost).
To handle the issue more elegantly and better implement the ddd concepts, we are thinking to make clock ticking as first class citizen of the application.
We would like to make a simple central clock ticker class, that will emit ticks as time events every second.
The ticks will be published to the central event bus.
And all the classes that are interested to act on the tick, will subscribe to the event bus.
What I am unable to figure out yet is that this will result in making a lot of subscriber/registrant classes code to run on every tick. As this is already the case with cron, could there be a better way to handle the subscription part so that a specific subscription is notified only when it needs to be notified?
And before we even get into solving this problem the way I am proposing, is there is a better way to handle this kind of problems? The key point in this whole scenario seems to be how to trigger something X based on how much time has passed since something Y happened in the domain. I believe I am not the first one to face this issue and this problem must have been long solved already but I am unable to stumble upon any road sign pointing me to the right direction.
The way I have handled this in the past is to queue commands as soon as I know something should happen and then the scheduler will fire off the commands when the time has come.
The scheduler is simply a process that runs as a service and wakes every N milliseconds to find any commands that have passed their ScheduledTime.
For example:
The user has logged in. Queue a command for 30 minutes hence to give them a coupon. After 30 minutes, the scheduler will send the command. If the session is still active, then the command is accepted and a coupon is presented. Otherwise, it simply does nothing.
You also mention several examples that are best handled by a traditional scheduler (cron as you mentioned) and will fire off a batch command. Depending on how knowledgeable your domain is about things like newsletters, you would either issue individual commands to your domain objects or simply pull a report and run a job to send emails.
If you do handle these types of processes in your domain, then your domain should also queue the next command. A saga or process manager would be most suitable for this type of operation. E.g.
CreateNewsletter (This is the batch) -> NewsletterCreated
Accounts.Each(SendAccountNewsletter) -> AccountNewsletterSent
NewsletterCompleted (This is the batch) ->
Queue(command: CreateNewsletter, when: NextMondayAt9) (This is the next batch)
Hope that helps.
P.S. If you publish ticks on your bus, you will have a ton of noise to filter through.
Does anybody know how WordPress stores it's CronJob events? I'm developing a plugin with multiple concurrent CronJobs, which behaves really strange. When configuring the plugin the first Event will generate some page data over a period of roughly 10-15 mins and is split into multiple packages. These packages will reschedule themselves to get the maximum running time, without hitting the script execution limit. However when the first CronJob is executed, the user can start a second one (not the same one, it's from another section), which will always result in the second one being scheduled, staying in standby and getting removed after the first one has finished an execution.
We had problems with long running CronJobs and the database cache before: Some of our data is bundled into an option and inserting data into this package will overwrite changes made outside of the CronJob. Maybe something similar is happening here. For reference: The reshedule of the first CronJob happens inside said CronJob. Could that be a problem too?
This is how the error is behaving:
Init
Cron 1 is sheduled to a past timestamp.
Cron 1 is starting.
Cron 2 is sheduled to a past timestamp.
Cron 1 is working.
Cron 1 is finished.
Cron 1 is resheduled to a new timestamp.
Cron 2 gets removed from the event queue.
Cron 1 is starting...
I have checked everything that correlates to the scripts themselves: The events are properly registered, have a unique argument (just in case) and even pull a new version of the database options they change, before doing so. Limits are set beforehand and every related function is wrapped in a try-catch-block.
My questions so far: Does anybody know what can cause a CronJob do get deleted (besides "wp_clear_sheduled_hook")? Does WordPress store the events as an option? Can a CronJob overwrite these settings, when it is running for a long time?
Thanks for your help and greetings
SOLUTION: Thanks #kyon147 for pointing out that WordPress is using the wp-options table to store information about the sheduled events. In case anyone has similar problems: Wordpress will load ALL options into it's cache, when it is called. Meaning when starting Cron1 the "cron"-array with your events might look like this:
array('cron1' => 'time')
When something is changing this option while the script is still runing, this change will not be reflected to the script. Meaning the array will still be as above, even when an event is added from another script/session. So when resheduling the event INSIDE Cron1 WordPress took the array above, not the new one. This resulted in the changes being reset to the state, when Cron1 was started and thus the event appearing missing.
Is it possible to tell PHP to execute a piece of code on a given date and time? For example, Blogger.com allows someone to set a blogpost to be published in the future (e.g. 12/12/14 6:00AM).
Can PHP do something similar?
(Sorry, I don't even know what the correct term for events like these would be to be able to even search for them! :( )
You can do this using a cron job (or scheduled task on Windows); although they are typically used for reoccurring jobs.
If you're using a database, most platforms come with a scheduler.
You can schedule your action in your database and use a cronjob on your server or use a cron job service To run your actions.
https://www.setcronjob.com/
For example when you want to publish your blog in the future, you save your publish date in the future and set some sort of auto-publish bit.
Then every hour a PHP script is ran by a cronjob, this script checks the database for all blogs which need to be published.
It's not possible to tell PHP to do this itself, since it would require a process to run forever to periodically call your PHP code. Thankfully though, there's a couple of things which do this:
1) Call a PHP script from a cron job, which then does any necessary work. If you don't have access to a crontab, you can periodically call this when a user pings your site instead, although that will be less reliable, of course.
2) Use at. This works in basically the same way as cron on Linux systems, but will schedule once and at an exact time.
for "triggering code at a certain time", cron works. But for something as simple as publishing an article at a specific time, it isn't needed. You can just store a publish date with your article. When displaying a list of articles you can adjust your query to something like WHERE PUBLISH_DATE <= NOW() and on the article page check if the article's publish date has passed before showing the article.
On Unix-like systems, there's Cron. You can manage Cron from PHP.
On Windows, there are scheduled tasks - you can also use PHP to manage scheduled tasks.
Be careful with this though - it's kinda hard to test, and you may end up with a schedule that cripples your server.
Hi there I'd like to make a recurring event based on calendar basis. The thing I want to ask is this: How to trigger the event? If the client doesn't login or open the webapp to trigger the event in the constructor, how do I make the code to run anyways.
I know cron jobs maybe the solution, but is there any other solution?(I want to avoid cron jobs).
You have to have something running in order for this to work; a cron is ideal for this, as it can run a script at regular intervals to check for things like events.
Without that, you are left by this being triggered by user action, but like you said, that user might not always log in to trigger it.
You could modify your code to have any user trigger actions for all users. It's a little more complex, as you'd need to allow for multiple users logging in at the same time when you only want one of them to trigger stuff. I would set up a table in your database to keep track of the last time things were triggered, and then if the gap since then and now is large enough when a user logs in, add a new entry in the table with the time now to prevent another user triggering this, and trigger the bits you need to run.
Like I said though, this won't be a perfect solution, and I really would recommend using cron. Is there any reason why you want to avoid using cron?
If that job should be triggered to keep the server in a good state, it should be run using a cron job, if its a database management, the database manager have the event's table to make cron jobs, if it's needed for only for the user, it can be a workload safe if you just don't do it until user login. You can manually login to trigger the event too, to an admin page maybe.