How to run a cron job in Heroku, with a Sinatra app - ruby-on-rails

I'm writing a tiny Sinatra app, and I want to host it on Heroku for simplicity sake. But, what I have is a task that scraps some sites and adds some data into my database every hour. Currently this is just written as a ruby script that needs to be executed. What Heroku has is a rake based cron job. Now if this was a rails app, I could easily do this, but I want to avoid the clutter for something as simple as this.
Is there a way to avoid this? Or do I have to install rake as well with my app?
Thank you.
Eric

You need a Rakefile like:
desc "This task is called by the Heroku cron add-on"
task :cron do
# Do something
end
Heroku periodically executes rake cron in your app depending on whether you have selected the "cron add-on" to be hourly or daily.

You need to check out Rufus. Rufus is your friend. Rufus will be your crontab while your app is loaded.
I did not try this stuff on Heroku but, give it a try and reply to us.
http://codex.heroku.com/past/2010/4/15/rufus_scheduler_for_my_tiny_sinatra_apps/
Why Rufus is cool? Well check this out, it's clean :)
$ sudo gem install rufus-scheduler
require 'rubygems'
require 'rufus/scheduler'
scheduler = Rufus::Scheduler.start_new
scheduler.cron '00 23 30 * *' do
# Run every 30 days at 23h00m
# ...your magic code goes here...
end

Looked again and looks like I jumped the gun on the question.
For applications that aren't Rails, one just has to create a Rakefile and put the task there.
Hope this helps other people.
Cheers!

Related

Setting up a rake task with Resque Scheduler - Rails 4

I am on Rails 4 using the Resque Scheduler gem.
I am also using the sitemap generator gem in order to dynamically generate my sitemap.
I am having trouble figuring out the best way to schedule a rake task with resque scheduler. The sitemap generator recommends whenever, but I am assuming resque scheduler can accomplish the same thing (don't want to install another gem if I don't have to).
Does anyone know how to set this up?
I would like to run rake sitemap:refresh:no_ping every 5 hours.
I was thinking I would just schedule a background job and run it from there:
# resque_schedule.yml
update_sitemap:
every: 5h
class: "SitemapUpdater"
description: "This job refreshes the sitemap"
# sitemap_updater.rb
class SitemapUpdater
#queue = :sitemap_queue
def self.perform
# run rake task here
end
end
... however, I'm not sure if this is a good practice. Any advice would be much appreciated.
I don't see a problem with your approach, you just must be aware that the scheduler is reset during every deployment, so if you do frequent deploys, your scheduled jobs might be run later or even not run at all, as documented:
IMPORTANT: Rufus every syntax will calculate jobs scheduling time starting from the moment of deploy, resulting in resetting schedule time on every deploy, so it's probably a good idea to use it only for frequent jobs (like every 10-30 minutes), otherwise - when you use something like every 20h and deploy once-twice per day - it will schedule the job for 20 hours from deploy, resulting in a job to never be run.
You might also run the rake from system cron itself, which is an even more lightweight solution as it requires no scheduler gems at all, just the rake task, and will be scheduled reliably in time.
See e.g. this answer for setting up the "every 5 hours" frequency in crontab and you might also need to study RVM wrappers if you use RVM for your ruby project (you must call rake using the RVM wrappers in such case, e.g. call /home/deploy/.rvm/wrappers/ruby-2.3.0#mygemset/rake instead of just rake).

Ruby on Rails Cron Job Example

Hi um quite new to rails platform and um looking for a rails cron job scheduling tutorials . I ve gone through with tutorials use whenever and the other scheduling gems , but um looking for a core ruby implementation with the cron tab on rails . Thank you in advance
Railscasts has a decent tutorial on using Cron.
EDIT
If you would like an example of how it was implemented from scratch, you could have a look at how the Whenever Gem is implemented here
To set cron jobs, you can depend the help of a simple gem named WHENEVER
Its very easy to implement. Go for it.
Many people are against this approach (see this SO thread) but triggering your application's action with curl/wget from a cron job may be a quick-and-easy solution for periodic tasks.
You just have to keep a few things in mind:
Keep execution time of your action low (as it will block your application just like a regular web request would do)
Make sure that you do not allow anyone to trigger the action (by using IP restrictions, secret tokens or other security measures)
For more information on this topic, I have written an article about it.
For minimal setup of "cron-like" tasks in "core" rails/ruby, I created https://github.com/Ebbe/arask
No need to install anything (other than the gem) or setup anything outside of rails.
Add gem 'arask' to your Gemfile, run bundle install, rails generate arask:install and rails db:migrate.
Now you can setup your tasks in the file config/initializers/arask.rb:
arask.create task: 'send:logs', cron: '0 2 * * *' # At 02:00 every day
arask.create script: 'puts "IM ALIVE!"', interval: :daily
arask.create task: 'my:awesome_task', interval: :hourly
arask.create task: 'my:other_awesome_task', interval: 2.hours
The tasks will automatically run if the server is running.
I'm using rufus-scheduler, It uses threads to execute functions scheduled. Very simple to configure. just 3 steps:
1 - Add gem gem 'rufus-scheduler', '~> 3.6'
2 - Create file config/initializers/scheduler.rb
3 - Programming schedule in scheduler.rb:
require 'rufus-scheduler'
s = Rufus::Scheduler.singleton
s.every '5s' do
#do every 5 seconds exec this code
puts "WOWWWWWWWWWWWWWWWWWWWW"
end
s.in '2d' do
# every 2 days exec this
puts "Now it's me"
end
For more doubts : https://github.com/jmettraux/rufus-scheduler
You can also use and external free service to outsource cronjobs http://guardiano.getpeople.in
DISCLAIMER: I made it

A pulse or cron job for Rails app running in Heroku

I need some code executed once per day. Can be more than once a day and missing a day isn't the end of the world. That code will make sure users get some bonus points based on certain criteria. I'll keep track if they've already received the bonus points so it doesn't double up..
Some simple cron job calling a particular controller once in a while is perfect:
curl http://localhost/tasks/pulse
Of course a real crontab entry works great. Or is there an internal mechanism for this kind of thing in Rails? I'm using the latest stable Rails (currently 3.2.9).
The only wrinkle is this needs to work in Heroku too.
I just noticed Heroku's Scheduler. Looks great for Heroku. I can just run those tasks in my dev/test environment manually. Is this the best way to handle pulses/cron jobs in Rails? With rake tasks? Easy to incorporate running rake tasks in tests?
The Heroku Scheduler works great and is easy to set up!
You could check out this gem called whenever its a Ruby gem that provides a clear syntax for writing and deploying cron jobs. It's well maintained, not used it on Heroku myself but worth a look.
You can do loads of stuff like
every 3.hours do
runner "MyModel.some_process"
rake "my:rake:task"
command "/usr/bin/my_great_command"
end

Cron tasks in Ruby on Rails

I'm new to Ruby on Rails, and I wanted to perform some periodical tasks but I found out that I didn't know how to set up any cron task in RoR. Is there any basic tutorial how to set up cron in RoR? Currently I'm running RoR on Webbrick with Mysql DB on Windows platform.
There are few ways to solve your problem.
If you want to use Cron, the best way of using it with Rails is to use a gem whenever. To find out more about whenever, and a quick tutorial on how to use it, check this Railscast Episode 164. Cron best suits when you have actions that need to be run every constant time interval (eg. emptying your users' trashes)
You can also use DelayedJob which best suits when you have some actions that last long time and you don't want your user wait until their actions finish (eg. when you deliver a lot of emails) or when you want to take some actions in X hours. More about DelayedJob you will find here: https://github.com/collectiveidea/delayed_job
You can also Resque with Redis: https://github.com/blog/542-introducing-resque
Check out http://rubygems.org/gems/delayed_job
You can create a daemon script, which always be in memory.
For example, https://github.com/DAddYE/foreverb
For minimal setup of "cron-like" tasks in "core" rails/ruby, I created https://github.com/Ebbe/arask
No need to install anything (other than the gem) or setup anything outside of rails.
Add gem 'arask' to your Gemfile, run bundle install, rails generate arask:install and rails db:migrate.
Now you can setup your tasks in the file config/initializers/arask.rb:
arask.create task: 'send:logs', cron: '0 2 * * *' # At 02:00 every day
arask.create script: 'puts "IM ALIVE!"', interval: :daily
arask.create task: 'my:awesome_task', interval: :hourly
arask.create task: 'my:other_awesome_task', interval: 2.hours
The tasks will automatically run if the server is running.

Rails how to create a delayed job for a rake taks?

How do I create a delayed job for a rake task that should run every 15 minutes?
You can give it a try: https://github.com/defunkt/resque
I am using Resque + Redis with Heroku. Delayed job is also very much supported on their cloud service.
In lib/tasks/cron.rb
desc "This task is called by the Heroku cron add-on"
task :cron => :environment do
def resubmit_pending_jobs
Resque.enqueue(SomeJob, job.id)
end
end
One way I can think of is by using the cron addon offered by Heroku which does it every hour (not 15 mins). Perhaps the above code block can assist you in finding a similar implementation for Delayed Job.
In the case you are interested in getting Resque setup with RedisToGo and Heroku, please consult this guide.
Hope that helps!
Take a look at SimpleWorker. It's a cloud-based background processing / worker queue for Ruby apps. It's an add-on for Heroku.
You create worker classes in your code and the queue up jobs to run right away or run later -- one time or on a recurring schedule.
worker = SomeWorker.new
# Set attributes for worker to use here
worker.schedule(:start_at => 1.minute, :run_every => 900)

Resources