用于在PHP中调度电子邮件警报的策略

I'm writing a PHP project in Laravel. The admin can queue email alerts to be sent at a specific date/time. The natural choice was to use Laravel's Queue class with Beanstalkd (Laravel uses Pheanstalk internally).

However, the admin can choose to reschedule or delete email alerts that have not yet been sent. I could not find a way yet to delete a specific task so that I can insert a new one with the new timing.

What is the usual technique to accomplish something like this? I'm open to other ideas as well. I don't want to use CRON since the volumes of these emails would be pretty high, and I'd rather reuse an already tested solution for managing a task queue.

I have scoured the internet for such an answer myself.

Here's what I've found:

Beanstalkd

I think the simplest way within Beantalkd is to use its ability to delay a job (giving it a number of seconds to delay as an argument).

You can then do date math to capture the difference in time between now() and when the job ideally is run (in seconds) and delay the job that long.

Here's an example (see first answer to that SO question - it's in Python, but you can get the gist of what the person is saying/doing)

Note that this doesn't guarantee the task is run on time - the delay just make the job available after X seconds. How behind your queue is on processing tasks when the delayed job becomes available determines when the job is run in reality. (If you're queue is behind due to heavy number of jobs, then it won't necessarily run exactly on time!)

Laravel

Laravel's Queue has a later method, which you can use instead of push

Where as with Push, you'd do:

Queue::push('Some\Processing\Class', array('data' => $data));

with later(), you'd do:

$delay = 14400; // 4 hours in seconds
Queue::later($delay, 'Some\Processing\Class', array('data' => $data));

SaaS Options

  1. Google App Engine can schedule tasks
  2. iron.io can schedule tasks (works well with Laravel!)

Other languages

  1. Python's Celery has similar options to delay jobs (with the same caveats)
  2. Ruby's resque has a schedular that also sort of fits this