Run laravel jobs one time at specific time only - php

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

Related

handling scheduled/time bound tasks in enterprise web application

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.

Running a PHP script or function at an exact point in the future

I'm currently working on a browser game with a PHP backend that needs to perform certain checks at specific, changing points in the future. Cron jobs don't really cut it for me as I need precision at the level of seconds. Here's some background information:
The game is multiplayer and turn-based
On creation of a game room the game creator can specify the maximum amount of time taken per action (30 seconds - 24 hours)
Once a player performs an action, they should only have the specified amount of time to perform the next, or the turn goes to the player next in line.
For obvious reasons I can't just keep track of time through Javascript, as this would be far too easy to manipulate. I also can't schedule a cron job every minute as it may be up to 30 seconds late.
What would be the most efficient way to tackle this problem? I can't imagine querying a database every second would be very server-friendly, but it is the direction I am currently leaning towards[1].
Any help or feedback would be much appreciated!
[1]:
A user makes a move
A PHP function is called that sets 'switchTurnTime' in the MySQL table's game row to 'TIMESTAMP'
A PHP script that is always running in the background queries the table for any games where the 'switchTurnTime' has passed, switches the turn and resets the time.
You can always use a queue or daemon. This only works if you have shell access to the server.
https://stackoverflow.com/a/858924/890975
Every time you need an action to occur at a specific time, add it to a queue with a delay. I've used beanstalkd with varying levels of success.
You have lots of options this way. Here's two examples with 6 second intervals:
Use a cron job every minute to add 10 jobs, each with a delay of 6 seconds
Write a simple PHP script that runs in the background (daemon) to adds an a new job to the queue every 6 seconds
I'm going with the following approach for now, since it seems to be the easiest to implement and test, as well as deploy on different kinds of servers/ hosting, while still acting reliably.
Set up a cron job to run a PHP script every minute.
Within that script, first do a query to find candidates that will have their endtime within this minute.
Start a while-loop, that runs until 59 seconds have passed.
Inside this loop, check the remianing time for each candidate.
If teh time limit has passed, do another query on that specific candidate to ensure the endtime hasn't changed.
If it has, re-add it to the candidates queue as nescessary. If not, act accordingly (in my case: switch the turn to the next player).
Hope this will help somebody in the future, cheers!

Execute a timed command in a time command

I am working with an php application where i need to check a database of users for whom has birthday today.
This i do through a cron job.
Now, when i get the users with birthday, i need to send them a SMS.
The SMS has an individual time associated which determins when the SMS should be send.
Lets say John and Peter has birthday today. Peter works from 01-09 so he should get the SMS at 01 and Peter works from 08-16 so he should get his SMS at 08.
I was thinking about dynamically creating the same amount of cron jbos which equals the people who has birthday on a given date. Those cron jobs would then send the SMS to the appropiate people this one time and thats it.
My question is, is there a smarter way to do this?
Secondly, if the cron job generation idea is good enough, is there a way to remove individual old cron jobs so i dont clug up the cron job list with old jobs which will never be run again?
Thanks in advance.
If you would like to send messages to each person at a specific time using cronjobs then you would have to create a cronjob for each person. Very bad idea in my eyes as you could end up with over 1000 cronjobs!
You would be much better with a system that runs a cronjob every 5 minutes or so (however often you want), and this cronjob executes a PHP script to determine if there are any messages to send out at that time, or between now and the last cronjob.
Whilst this may mean your users could get their message up to 5 minutes late, it is unlikely because nobody I know starts work at 8:02, and therefore, if the cronjob is at 8:00, 8:05, 8:10 etc, you will almost always get the message sent right on time!
If you're worried about creating too many cron jobs (not sure how many would be a problem on your system), then why not create just one cron job at the OS level? Then you can call your program every 10 minutes or so, and it can check if there are new people that need to be sent an SMS.

PHP start task for certain time

Im having a small problem i searched a while about it but didnt found any good aswer for my problem , so here it is:
I have a PHP script with user database and i want users to have a small button that will make a certain task execute for a certain time ( imagine 2 hours ) , and this task will keep running till the job is done. The user can stop the task and hit continue , and the task will stop executing after 2 hours!
Any ideia how i can do it?
My actual hosting have crontab.
Well you haven't explained your problem in enough details , but you should this generally :
when users post tasks , write these tasks in a database table, with other information such as start time and end time (and you can update these due to user new input), then write a script which reads these tasks from database and compares current time to start time and if it is time to run, runs the task.
now put this single script in a cron job
This is actually a better idea than creating a cron job for each user defined task

Execute script at variable time

I'm aware of cron jobs to execute commands at a certain time, but what if that time is not constant? For instance, suppose a user asks for a reminder email exactly 1hr after signing up for something, is there an easy way to go about doing this?
Timing is critical. I am actually trying to create AI that will essentially act on its own but only at variable points during the day. Any help would be appreciated!
You can use at to schedule jobs for specific times. cron is for repeating jobs, at is for one-shot/oddball interval ones. Both have a resolution of 1 minute, though, so you can't specify a start period with seconds granularity.
The command's available on both Unix/Linux and Windows.
Here a workable flow:
user Requests email in 1 hour
You insert into the a table action (action_id, time)
On the PHP server create a cron job to check the action in the action table every minute, then do the action that need to be done at that time
That is a simple example from the request. It might get a bit more complex then that.
EDIT : this suggestion might be good only if you need to be very precise with the time management!
if you dont wanna use the cron triggers and you are not comfortable with them here are two php scheduling libraries..
1) http://www.php.brickhost.com/
2) http://www.phpjobscheduler.co.uk/
Try them if you like:

Categories