3
votes

I think Cron may be the best answer for this, but the task seems daunting and I know so little about cron, it's probably best that I ask first.

I am writing an API for an iPhone application that schedules shared tasks in a group. This will require sending push notifications at various times. Here is one example:

Person A assigns a task for Person B to complete in n days. This task is added, Person B is notified that the task has been assigned and after n-1 days a reminder notification is sent, if the task was not completed after n days, another notification is sent alerting Person B that they failed to complete the task.

My assumption here is that the process would go something like this:

  • When the task is initially assigned and the task is added to the DB, a cron scheduling script would be called which would schedule 2 cron jobs - 1 to fire the reminder notification, and one to fire the failure notification.
  • When the task is completed, it calls another script which either marks the task as completed in the DB (or removes it), and un-schedules the cron jobs.

Am I way off base here, or is this the easiest way to take this on? If it is - are there any PHP classes to make dynamically scheduling (and un-scheduling) cron jobs easier?

5
Have a cron job that runs at a set interval and poll the DB for tasks. Scheduling a one-off cron job for each unique task is a huge waste of resources and could get very complicated. This way jobs can be cancelled simply by adjusting the database, and you never have to mess about with the cron job once it is set up. - DaveRandom

5 Answers

0
votes

You could have a cron job that fires once every day.

This loops through data in the database, if a reminder needs to be sent (e.g. n-1 days is today, send the notification).

If that date has passed and it isn't complete, then it can send the failure notification.

If the task is complete, then you can change the database in that cron task, or a seperate one that fires more often.

Hopefully that helps.

0
votes

My advise would be: determine what the fastest response needed would be (every minute, every 10 minutes, every hour etc.) and run a cron script in that time frame.

The script itself could be PHP, en when the script runs it figures out what to do, what actions are needed etc.

0
votes

I worked on a mailing queue recently, and I implemented it as follows: There is a one cron job that fires every minute a script, that check if database contains any e-mails in the queue. If they are found, script sends them out.

There is another cron job, that fire every day which adds scheduled e-mails to database (with a specified time, when to send it out).

So, there is a daily cron job that generates jobs to be processed at various times, and there is another one which runs constantly and processes jobs in queue.

It's easy to add some priority mechanisms too.

0
votes

Your host will likely offer a cron capability in your hosting control panel. The few times I have used it, I have found that it is a case of putting in the file that you want to run's path on the server then from a couple of drop downs select the frequency. From there you are off..

As for the solution you could have AS A VERY SIMPLE EXAMPLE...

cron.php

<?php

/*

Steps
1 - Set any completed tasks to done
2 - Check if users need to be notified and send the notifications

*/

function send_notifications($email,$time_ends){

// insert code here to deal with sending the notification to the iphone

}



include("db.php"); // contains your MySQL connection vars or whatnot

// STEP 1 - Set any completed tasks to done
$update_db = mysql_query("UPDATE Notifications SET complete = '1' WHERE time_completed > '0000-00-00 00:00:00'");


// STEP 2 - Send any outstanding notifications out
$result = mysql_query("SELECT * FROM Notifications WHERE time_completed = '0000-00-00 00:00:00'"); // add another where clause to prevent bombarding with notifications for example " AND notification_2_days = '0'"
while($row = mysql_fetch_array($result))
{
  send_notifications($row['email'],$row['time_ends']);
  // insert an update query here to flag as a notification sent, you dont want to bombard
}


?>

WARNING - This is using depreciated connection code for simplicity (look up MySQL PDO etc) and this lacks any kind of security.

0
votes

cron is great for scripts run on a regular basis, but if you want a one-off (or two-off) script to run at a particular time you would use the unix 'at' command, and you can do it directly from php using code like this:

/****
 * Schedule a command using the AT command
 *
 * To do this you need to ensure that the www-data user is allowed to
 * use the 'at' command - check this in /etc/at.deny
 *
 *
 * EXAMPLE USAGE ::
 *
 * scriptat( '/usr/bin/command-to-execute', 'time-to-run');
 * The time-to-run shoud be in this format: strftime("%Y%m%d%H%M", $unixtime)
 *
 **/

function scriptat( $cmd = null, $time = null ) {
    // Both parameters are required
    if (!$cmd) {
        error_log("******* ScriptAt: cmd not specified");
        return false;
    }
    if (!$time) {
        error_log("******* ScriptAt: time not specified");
        return false;
    }

    // We need to locate php (executable)
    if (!file_exists("/usr/bin/php")) {
        error_log("~ ScriptAt: Could not locate /usr/bin/php");
        return false;
    }

    $fullcmd = "/usr/bin/php -f $cmd";

    $r = popen("/usr/bin/at $time", "w");
    if (!$r) {
        error_log("~ ScriptAt: unable to open pipe for AT command");
        return false;
    }
    fwrite($r, $fullcmd);
    pclose($r);

    error_log("~ ScriptAt: cmd=${cmd} time=${time}");

    return true;
}