3

I am using whenever gem to run rake tasks. My code in schedule.rb is as follow.

 every 1.day, :at => '11:00 am' do
  rake "notifications:run_mailer"
 end

Above code is executing the rake task on 11am of every day. Now i want to change this. I want to run this rake task based on a table column. For that i have created a table called scheduler.rb and a column run_at. based on run_at column date and time i need to run that rake task. How to do that?

Can Can
  • 3,644
  • 5
  • 32
  • 56

2 Answers2

3

Step 1:

First we have to load all the files in the schedule.rb Then only we can execute the ActiveRecord queries.

That could be done by the below command

 require File.expand_path(File.dirname(__FILE__) + "/environment")

Step 2:

Execute the ActiveRecord query and get the time.

  run_at=Scheduler.last.run_at
  time=[run_at.hour.to_s,run_at.min.to_s].join(":")
  every 1.day, :at => time do
    rake "notifications:run_mailer"
  end

step 3:

We have to update the whenever crontab using below command.

 system "whenever --update-crontab"

system keyword is used to run linux terminal commands inside rails code.

Can Can
  • 3,644
  • 5
  • 32
  • 56
2

Assuming the table name is Scheduler:

Scheduler.find(:all).each { |scheduler|
  every 1.day, :at => scheduler.run_at do
    rake scheduler.task_to_run
  end 
}

Please note, that this code will add cron tasks on every run. This will lead to enormously huge amount of cronjobs after a while. The additional check for “was the task already scheduledmust be added as well.

Hope it helps.

Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
  • its throwing uninitialized constant Whenever::JobList::Scheduler – Can Can Oct 08 '14 at 07:18
  • Require the file with your `Scheduler` class. – Aleksei Matiushkin Oct 08 '14 at 07:22
  • Note: `find(:all)` will try to load all data at once, instead use: `find_each`. – Surya Oct 08 '14 at 07:32
  • @Surya this is a table containing cron `tasks`. One shouldn’t expect any performance penalties by reading the whole stuff into memory. – Aleksei Matiushkin Oct 08 '14 at 07:39
  • @mudasobwa: It'll be OK if you destroy the entry from table when the task is finished performing, otherwise you will definitely have an unresponsive server after certain amount of time. – Surya Oct 08 '14 at 07:48
  • @Surya I’m not sure I understand what are you talking about. `find(:all)` will return an array, which is to be garbage collected as soon as an iterator finishes. – Aleksei Matiushkin Oct 08 '14 at 07:54
  • Imagine there you start scheduling 10 jobs a day in schedulers table and you don't remove them once they're done performing, after a month you'll have 300, a year 3600 or more, my point is over a period of time you'll have way too many jobs in schedulers table and loading all of them at once will make server pay with its performance. Instead, you should always make query in batches to avoid such incidents. – Surya Oct 08 '14 at 07:58
  • @Surya Ah, got it. The problem actually is not with loading the whole table (well, I admit in _most_ cases batch load is better, but not in that particular one.) The additional check not to schedule already scheduled jobs **must** be performed. By batch-load you are going to hide the problem, not to solve it :) – Aleksei Matiushkin Oct 08 '14 at 08:04
  • Agreed, I think you should update this piece of information in your answer as well. Because, new people tend to learn and implement stuff by reading answers/posts made by someone experienced, I hope you got my point. :) – Surya Oct 08 '14 at 08:08
  • i am not able to require scheduler.rb model inside schedule.rb – Can Can Oct 08 '14 at 09:39
  • @AlekseiMatiushkin looks like we don't have to clean up crontab listings, `whenever` gem already does cleanup internally by identifying a block based on schedule file path, inside crontab file. – elquimista Nov 12 '19 at 08:47