Schedule e-mail notification 24 hours before certain event? - php

I have a PHP-based site with bookings/appointments stored in a MySQL database.
I want to set an e-mail notification to be sent to each person who made a booking exactly 24 hours before their booking. Bookings are added through a regular PHP form.
I know I could add a script to, for instance, the index page that checks the database for any bookings that are in the final 24 hours, but that's unreliable since I won't be getting much traffic at first. So the index page could go hours without visits, and the notification would be hours late.
The other solution that came to mind is to set a cron job that runs every minute, calls a PHP script which checks whether any e-mails should be sent and sends them. But I'm not sure if this is overkill in a way; does anyone have a better solution than having something run in the background every minute?
To sum it up - is there a way to do this without cron?

Triggering the job from a web page is a very bad idea, for two reason: (1) if you don't get traffic to your site, the job doesn't run; (2) if you get a lot of notifications, the job will be slowing down the response to the web requests (assuming you invoke the job synchronously).
I would strongly discourage you from running a job every minute either - it definitely will be an overkill. Instead, think whether you really need "exactly 24 hours" as the interval or would "between 22 and 26 hours" be ok.
We have a similar requirements - and went about it by setting a job that runs every 4 hours and checks what notifications need to be sent for events starting between 22 and 26 hours form the time the script runs. This way, the script is only execute 6 times in a day and everything gets sent correctly.
If 4 hours approximation is not good enough, then think to the largest interval that's appropriate. I'm sure 1 hour should be sufficient. Have a script run once an hour (from cron) and check for events starting between 23 and 24 hours from the time of the run.
Remember that once your email is sent, it doesn't end up in the recipient's inbox immediately: sometimes it takes a few seconds, but sometimes it may take an hour or even more - so an extra hour difference in your script won't be a problem.

You don't need to use cron as an interval'd timer. You can set a very specific date and time when you want your job done.
Here's an article on the subject
For instance:
0 0 18 5 * <php command here>
Will run every May 18th at midnight. That's more than enough time to clear it before the next iteration (next year).

there is no way other than setting cron or sending request to server through periodic calls...below is post similar to your question, you may get idea.
Live redirect based on periodic server calls with JSON or AJAX
Thanks

a cron job every minute has no sense ! but you can do a cron job every hour because i think it doesn't meter a hour difference or 2 hours . without cron it isn't any other way . it will take about 2 second (at max) to complete so it is worth

Related

Run laravel jobs one time at specific time only

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

Wait after receiving a Webhook

After some research, I haven't found anwers for what I'm trying to achieve.
I found some information about the php sleep() function, and some inforamtions about CRON jobs, but none of these options seem to solve the problem.
Here is what I try to do : I have a php file which may receive webhooks. I need to wait some time (15 minutes for example) before "reacting" to this webhook. So, basically, my script should :
1 - receive the webhook (Already done with current code)
2 - wait some time
3 - do some actions (Already done)
I've already done what I needed without the wait part, and it works very well, bu now I don't know how to do with it...
If I understood it well, Cron Jobs are executed periodically, while I want to wait some time only when the webhook is received.
I thought about the sleep() function, but I'm afraid it may use to much ressources...
How can I do this ?
Update : It seems I can't use the sleep function more than 30 seconds (max execution time I guess ?)
If I was you, I'd build a queueing system so that when a webhook comes in, a row in a database is inserted. I'd add a column for 'execution_time' and set that to 15 mins from when the webhook came in. You can then setup a cron job that runs every minute but only fires where the execution_time is 'now'.
use cron
“At every 15th minute past every hour.”
Minute Hour Day Month Weekday Command
15 * * * * php /homelink/path/filename.php
Note:
You can set an email address for the cron. Every trigger it will send an email notification. If receive email means cron is working, If not then need to check your code. Also you can debug using the appropriate echo's.

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!

Multiple time-critical background tasks

I'm new to PHP, so I need some guidance as to which would be the simplest and/or elegant solution to the following problem:
I'm working on a project which has a table with as many as 500,000 records, at user specified periods, a background task must be started which will invoke a command line application on the server that does the magic, the problem is, at each 1 minute or so, I need to check on all 500,000 records(and counting) if something needs to be done.
As the title says, it is time-critical, this means that a maximum of 1 minute delay can be allowed between the time expected by the user and the time that the task is executed, of course the less delay, the better.
Thus far, I can only think of a very dirty option, have a simple utility app that runs on the server, that at each minute, will make multiple requests to the server, example:
check records between 1 and 100,000;
check records between 100,000 and 200,000;
etc. you get the point;
and the server basically starts a task for each bulk of 100,000 records or less, but it seems to me that there must be a faster approach, something similar to facebook's notification.
Additional info:
server is Windows 2008
using apache + php
EDIT 1
users have an average of 3 tasks per day at about 6-8 hours interval
more than half of the tasks can be at least 1 time per day executed at the same time[!]
Any suggestion is highly appreciated!
The easiest approach would be using a persistent task that runs the whole time and receives notification about records that need to be processed. Then it could process them immediately or, in case it needs to be processed at a certain time, it could sleep until either that time is reached or another notification arrives.
I think I gave this question more than enough time, I will stick to a utility application(that sits on the server) that will make requests to a URL accessible only from the server's IP which will spawn a new thread for each task if multiple tasks needs to be executed at the same time, it's not really scalable but it will have to do for now.

XML Fetcher Cron job: Run how often and how many fetches?

I've got a PHP script on a shared webhost that selects from ~300 'feeds' the 40 that haven't been updated in the last half hour, makes a cURL request and then delivers it to the user.
SELECT * FROM table WHERE latest_scan < NOW() - INTERVAL 30 MINUTE ORDER BY latest_scan ASC LIMIT 0, 40;
// Make cURL request and process it
I want to be able to deliver updates as fast as possible, but don't want to bog down my server or the servers I'm fetching from (it's only a handful).
How often should I run the cron job, and should I limit the number of fetches per run? To how many?
It would be a good thing to "rate" how often each feed actually changes so if something has an average time of 24 hours per change, then you just fetch is every 12 hours.
Just store #changes and #try's and pick the ones you need to check... you can run the script every minute and let some statistics do the rest!
On a shared host you might also run into script run time issues. For instance, if your script runs longer than 30 seconds the server may terminate. If this is the case for your host, you might want to do some tests/logging of how long it takes to process each feed and take that into consideration when you figure out how many feeds you should process at the same time.
Another thing I had to do to help fix this was mark the "last scan" as updated before I processed each individual request so that a problem feed would not continue to fail and be picked up for each cron run. If desired, you can update the entry again on failure and specify a reason (if known) why the failure occurred.

Categories