-1

I'm building an application where the sending of all notifications (email, SMS, fax) will be asynchronous. The application will write the notifications to the database, and a batch job will read these notifications and send them with the appropriate transport.

I was first reading at ways to run cron faster than the minute, and realized this was a bad idea.

The batch scripts are written in PHP, and I guess that writing a proper daemon would be quite an overhead (though I'm open to any suggestion, as PHP car run indefinitely as well).

What I have in mind is a solution that would:

  • Run the PHP script every 5 seconds
  • Check that the previous run has finished, or abort (never 2 concurrent batches running)
  • Kill the script if live for more than x minutes (a security in case it hangs)
  • Start with the system (if a reboot occurs)

Any idea how to do this?

BenMorel
  • 4,215
  • 10
  • 53
  • 81
  • Don't reinvent the wheel. Use an existing, well understood messaging system, such as anything that's AMQP compliant. – Michael Hampton Nov 26 '12 at 17:08
  • I don't know anything about AMQP unfortunately, and at first glance that looks a bit overkill for my simple requirement. Insert, Select and Delete from a table in a transactional database is all I need for now, and will work fine. Keep It Simple! – BenMorel Nov 26 '12 at 17:34

1 Answers1

2

It feels like you're trying to use the wrong architecture/tool for the job, and maybe you should look into using a message queue. beanstalkd has some PHP libraries available and will do blocking reads of the queue. There are some hints on how to proceed in this StackOverflow question.

nickgrim
  • 4,336
  • 1
  • 17
  • 27
  • You're probably right, but the problem is, I do want to keep storing the notifications in the database, as this is a way to ensure that the notification handling is transactional as well (if a transaction fails, everything is aborted, including sending notifications). – BenMorel Nov 26 '12 at 12:07
  • You can build it so the app enqueues a job containing the id of the notification in the database (i.e. a primary key), and delays it for enough time to allow the transaction to finish. Then, write the background worker so that it gracefully handles the case where the id is not found (e.g. if the transaction is rolled back). – nickgrim Nov 26 '12 at 12:12
  • Seems a bit of an overhead to me, and not totally failproof: that would involve connecting to yet another server to send the notification, and the "delay it for enough time to allow the transaction to finish" part looks a bit unsure to me (How do you define this time? What if it happens to take longer?) – BenMorel Nov 26 '12 at 12:16
  • Well, if the job runs before the transaction commits (which is very possible without a delay), then the worker obviously won't be able to find the notification in the database. Delaying the running of the job simplifies the code since your worker doesn't have to tell the difference between "transaction not yet committed" and "transaction rolled back". Since you're talking about sending "email, SMS, fax" an extra few seconds of latency is unlikely to cause difficulty to your end-user. – nickgrim Nov 26 '12 at 12:23
  • @Benjamin: You either have to reduce your requirements (is it *really* necessary to process the queue every 5 seconds?) so that it can handled by a cron job or live with the fact that the solution is more complex than a cron job. – Sven Nov 26 '12 at 12:26
  • Unfortunately it *is* annoying in this business that notifications can take a minute to send. It is indeed more complex that a cron job, and that's why the solution I was asking for was quite specific! – BenMorel Nov 26 '12 at 12:35