Ultimately, we all want easy-to-replicate deployments of our apps. Perhaps we're deploying on a cloud, and deploy often on new virtual hardware. Perhaps we're just paranoid, and expect an earthquake to hit our datacenter. Or maybe we expect to grow like the 4H club's monster pumpkin, and fully anticipate moving to new/different hardware soon.
Either way, the fewer moving parts and manual steps you have to follow, the better.
To me, cronjobs are the most-often forgotten step. They don't take up visible room on the filesystem. They don't listen on a port. They're easy to forget. You can forget to install them. You can forget to remove them. In general, cronjobs annoy me.
But there's still the need to do things at certain times, or on a regularly occurring schedule.
With Rails apps, we can vendorize our dependencies. With JRuby-on-Rails, we basically vendorize the whole language. And with JBoss-Rails, we have a really nice and complete environment. Java has tried real hard to allow you to deploy entirely within a container. JBoss AS certainly provides everything we'd need.
Specifically, it provides Quartz.
Since we're running in AS, we're happy to write deployers if needed, and we have a scheduler already setup in AS, I think we can bake scheduled tasks right into application deployment.
Imagine $RAILS_ROOT/app/scheduled-tasks/blog_poller.rb.
It could have a fairly simple execute() method on it.
When your app is deployed, $RAILS_ROOT/config/scheduler.rb could be read to set up the quartz tasks.
Cron's syntax isn't exactly warm and fuzzy. I think common case is a recurring interval for a task execution. Something like...
Scheduler.deploy do |schedule|
schedule.every( 30.minutes ).run( BlogPoller )
end
Simple enough. If parameters are needed, perhaps something akin to
Scheduler.deploy do |schedule|
schedule.every( 30.minutes ).run( BlogPoller ).with(
:number_of_retries=>3,
:notify_on_failure=>true
)
end
Some syntax to support concrete time-of-day or day-of-week should be doable. It might be worth investigating the chronic gem.
And since we're handling the deployment, we don't have to wiggle these in strangely as part of the web-app. A deployer will look for config/scheduler.rb, fire up a ruby interpreter to figure out what the schedule is, and then go deploy actual scheduled tasks into the Quartz service. Scheduled tasks can be a first-class component like a Servlet, a message queue, or an EJB.
Deploy your app, your scheduled tasks get deployed too. Undeploy, and the scheduled tasks get cancelled and removed likewise.