Rails how to create a delayed job for a rake taks? - ruby-on-rails

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)

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).

Is there is something like cron in rails application on windows?

I'm trying to use cron in my application to send mails every week but I think it doesn't work on Windows.
Does anybody knows any equivalent to cron solution that works on Windows?
Windows equivalent of Unix's cron is a "Task Scheduler". You can configure your periodical task there.
Purely Ruby solution
If you want a purely Ruby solution look into:
rufus-scheduler - it's Windows cron gem.
crono - it's a in-Rails cron scheduler, so it should work anywhere.
Web services - there are plenty of free online services that would make a request to a given URL in specific time periods. This is basically a poor man's cronjob.
I recommend taking a look at Resque and the extension Resque-scheduler gems. You will need to have a resque scheduler process running with bundle exec rake resque:scheduler and at least one worker process running with QUEUE=* bundle exec rake resque:work.
If you want these services to run in the background as a windows service, you can do it with srvany.exe as described in this SO question.
The above assumes you are ok with installing Redis - a key-value store that is very popular among the Rails community as it can be easily used to support other Rails components such as caching and ActionCable, and it is awesome by itself for many multi-process use cases.
Resque is a queue system on top of Redis that allows you to define jobs that can be executed asynchronously in the background. When you run QUEUE=* bundle exec rake resque:work, a worker process runs constantly and polls the queue. Once a job is enqueued, an available worker pops it from the queue and starts working on it. This architecture is quite scalable, as you can have multiple workers listening to the queues if you'd like.
To define a job, you do this:
class MyWeeklyEmailSenderJob
def self.perform
# Your code to send weekly emails
end
end
While you can enqueue this job to the queue yourself from anywhere (e.g. from a controller as a response to an action), in your case you want it to automatically be placed into the queue once a week. This is what Resque-scheduler is for. It allows you to configure a file such as app/config/resque_schedule.yml in which you can define which jobs should be enqueued in which time interval. For example:
send_weekly_emails:
cron: 0 8 * * Mon
class: MyWeeklyEmailSenderJob
queue: email_sender_queue
description: "Send weekly emails"
Remember that a scheduling process has to run in order for this to work with bundle exec rake resque:scheduler.
thanks guys , actually i tried rufus scheduler gem and it worked for me , i guess it's the best and easier solution

Ruby on Rails: need to log data on a daily basis (hosted on Heroku)

Cronjob vs Scheduler for Heroku.
Sounds like you just need a periodic task to run once per day. The currently recommended way to do that at Heroku is to use the scheduler add-on:
Scheduler is an add-on for running jobs on your app at scheduled time intervals, much like cron in a traditional server environment.
A dashboard allows you to configure jobs to run every 10 minutes, every hour, or every day, at a specified time. When invoked, these jobs will run as one-off processes and show up in your logs as a process named run.N.
The basic process is pretty simple:
Set up a Rake task to do whatever it is you need to do:
desc "This task does ..."
task :your_task => :environment do
# Do something interesting...
end
Add the scheduler add-on in the usual manner:
$ heroku addons:add scheduler:standard
Then add your new Rake task through the Heroku dashboard.
If you want to run your periodic task outside Heroku then set up a cron job to run the appropriate Rake task.
You probably want to put this task into a Cron job which handles recurring processes or tasks.
Here is an excellent screencast on the subject courtesy of Ryan Bates:
http://railscasts.com/episodes/164-cron-in-ruby-revised
If you need to set up recurring jobs on Heroku, you need only add your tasks to lib/tasks/scheduler.rake and configure them using the Schedular Add-on
http://devcenter.heroku.com/articles/scheduler

"Whenever" gem running cron jobs on Heroku

I created an app that uses the whenever gem. The gem creates cron jobs. I got it working locally but can't seem to get it working on heroku cedar. What's the command to do this?
running:
heroku run whenever --update-crontab job1
doesn't work
Short answer: use the scheduler add-on: http://addons.heroku.com/scheduler
Long answer: When you do heroku run, we
spin up a dyno
put your code on it
execute your command, wait for it to finish
throw the dyno away
Any changes you made to crontab would be immediately thrown away. Everything is ephemeral, you cannot edit files on heroku, just push new code.
You need to add Heroku Scheduler addon.
You can add it directly from your dashboard or using following commands:
install the add-on:
heroku addons:create scheduler:standard
Create a rake task in lib/tasks
# lib/tasks/scheduler.rake
task :send_reminders => :environment do
User.send_reminders
end
Schedule job
Visit Heroku Dashboard
Open your app
Select Scheduler from add-ons list
Click Add Job, enter a task and select frequency.
e.g. Add rake send_reminders, select "Daily" and "00:00" to send reminders every day at midnight.
The other answers specify you should use the Heroku Scheduler add-on, and it is able to run a background tasks indeed, but it doesn't support the flexibility of cron.
There's another add-on, called Cron To Go, that is able to run your jobs on one-off dynos with cron's flexibility. You can also specify a timezone for your job and get notifications (email or webhook) when job fail, succeed or start.
(Full disclosure - I work for the company that created and operates Cron To Go)
If you want to:
Use Heroku Scheduler
Run tasks every minute (not 10 min)
Don't care about dyno hours
This was my solution hack to run jobs every minute - assuming the task completes in under 60 seconds.
task start_my_service: :environment do
1.upto(9) do |iteration|
start_time = DateTime.now
Services::MyService.call
end_time = DateTime.now
wait_time = 60 - ((end_time - start_time) * 24 * 60 * 60).to_i
sleep wait_time if wait_time > 0
end
end
Heroku doesn't support cron jobs. And there are two drawbacks to the Heroku Scheduler :
you cannot choose an arbitrary interval or time at which to run jobs (it's either every 10 mins, 1 hour or daily).
your jobs are not defined in code, hence not in your versioning system and not easy to keep track of or modify.
Heroku does provide an alternative : custom clock processes. But the clock process requires its own dyno, and "Since dynos are restarted at least once a day some logic will need to exist on startup of the clock process to ensure that a job interval wasn’t skipped during the dyno restart".
Simple scheduler is a gem made specifically made for scheduling on Heroku, but seems a bit hackish.
I ended up using sidekiq-cron. Only drawback : if sidekiq is down right when a job is scheduled to run, the job won't run.

How to run a cron job in Heroku, with a Sinatra app

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!

Resources