Run a ruby on rails job every night at a specific time - ruby-on-rails

I have a job like this :
class LdapSyncJob < ApplicationJob
queue_as :default
require 'pp'
def perform
users = User.all
users.each do |user|
user.update("Do something")
end
end
end
and I use delayed job for the job processing .
My question is how and where to define my job to be run every night at a specific time ?
Should I call my job in an action or not ? if so how can I do that ?

The delayed job mainly used for processing tasks in queue and in background. It's usually not preferred for scheduling of tasks.
For your use case you should check out whenever a ruby gem, which works with cron jobs to schedule tasks repeatedly.
I would suggest you to move logic or method call LdapSyncJob.perform() to rake task.
In config/schedule.rb, you can do something this way
ENV['RAILS_ENV'] = "#{#pre_set_variables[:environment]}"
env :PATH, ENV['PATH']
require File.expand_path(File.dirname(__FILE__) + "/environment")
set :output, "/logs/cron_log_#{ENV['RAILS_ENV']}.log"
every 1.day, :at => '02:30 am' do
command "cd #{Rails.root}/lib/tasks && rake task_calls_peform_code"
end
Note : Don't forget to update and restart crontab using belong commands.
whenever --update-crontab app --set 'environment=production' #update crontab
service crond restart #restart crontab

Related

Scheduler works once

The project uses the task scheduler - gem 'clockwork'. Capistrano executes the hook:
after :'deploy:finished', :'clockwork:restart'
The scheduler is triggered once (after this hook), runs all rake tasks, then tasks are not started. No matter how much I put an interval, in a day or 5 minutes, the task does not start anymore. Gem 'daemons' is installed. I will be glad to any help!
UPDATE
require 'clockwork'
require_relative './boot'
require_relative './environment'
module Clockwork
handler do |job|
puts "Running job: #{job}"
end
every(1.minute, 'job:some_task') do
rake_task('job:some_task')
end
def rake_task(task_name)
AppName::Application.load_tasks
Rake::Task[task_name].invoke
end
configure do |config|
config[:sleep_timeout] = 3600 # 1 hour
config[:logger] = Logger.new("#{Rails.root}/log/clockwork.log")
config[:tz] = 'UTC'
config[:max_threads] = 15
config[:thread] = true
end
end
My guess is you're not running clockwork as a daemon, hence why it runs only once. Have a look at this gist
desc "Start clockwork"
task :start, :roles => clockwork_roles, :on_no_matching_servers => :continue do
run "daemon --inherit --name=clockwork --env='#{rails_env}' --output=#{log_file} --pidfile=#{pid_file} -D #{current_path} -- bundle exec clockwork config/clockwork.rb"
end
You could always SSH into your deployment and either check the list of PID or check in your rails application the temporal file that stores clockwork's PID:
.../tmp/pids/clockwork.pid
Alternatively check clockwork's logs:
.../log/clockwork.log

ruby - use gem 'whenever' to check the deadline

I want to use 'whenever' this gem to check my all projects are still not out of deadline. I wrote this code but it didn't work and change status in the database. Can somebody give me some advises. Thank you for helping!
config/schedule.rb
set :environment, :development
every 1.day, at: '11:3 am' do
rake 'project:close_project'
end
app/models/project.rb
def self.close_project(dt)
# 締切日が過ぎているプロジェクトを抽出
Project.where(deadline > dt).each do |project|
# 対象プロジェクトを終了状態に
project.update!(status: 'closed')
end
end
product.rake
namespace :product do
task :close_project => :environment do
Project.close_project(Date.today)
end
end
Whenever creates jobs based on CronJob format. So to run your jobs periodically, you should run whenever command and copy and pasting the results to crontab by running crontab -e or do this task automatically just by running whenever -w.

Update database monthly ruby on rails?

I have a table "Point" with an integer column "monthly_point", and a table "User" with an integer column "Give_Point". I want to update the value of "Give_Point" is value of "monthly_point" every month. How can i do that? Thanks all.
There is a gem for such tasks, called sidetiq
It uses sidekiq for background jobs.
Here is an example
class MonthlyPointWorker
include Sidekiq::Worker
include Sidetiq::Schedulable
recurrence { monthly }
def perform
# do your work here
end
end
Whenever just puts your tasks into the crontab and executes it using cron.
It's up to you which one you will use for your needs.
You should use cron-jobs to achieve this so, use the whenever gem
Just add gem 'whenever', require: false to your Gemfile and run bundle install.
Then within your application’s root directory, run the following command:
`bundle exec wheneverize`
This will add a schedule file to your config folder (config/schedule.rb). This file is where you set up your scheduled tasks. You can use regular cron scheduling, or you can use a more idiomatic DSL for scheduling. The following examples are take from the gem’s README.md:
every 3.hours do
runner "MyModel.some_process"
rake "my:rake:task"
command "/usr/bin/my_great_command"
end
every 1.day, :at => '4:30 am' do
runner "MyModel.task_to_run_at_four_thirty_in_the_morning"
end
every :hour do # Many shortcuts available: :hour, :day, :month, :year, :reboot
runner "SomeModel.ladeeda"
end
every :sunday, :at => '12pm' do # Use any day of the week or :weekend, :weekday
runner "Task.do_something_great"
end
every '0 0 27-31 * *' do
command "echo 'you can use raw cron syntax too'"
end`
Once you’ve set up your scheduled tasks in config/schedule.rb, you still need to apply them to your crontab. From your terminal, use the whenever command to update your crontab:
Change to your application's directory.
cd /my/app
View config/schedule.rb converted to cron syntax
bundle exec whenever
Whenever Gem

Sidekiq With Whenever

I'm using whenever for schedule of job with sidekiq. Also, use sidekiq-client-cli gem, that is a command line client for sidekiq and allows the cron jobs to interact with sidekiq.
This my active job file :
# jobs/clone_record_job.rb
class CloneRecordJob < ActiveJob::Base
queue_as :myapps
def perform(*args)
Core::Block.where(release_date: Date.today - 30.days).each do |block|
new_block = Core::Block.new(block.attributes)
new_block._id = BSON::ObjectId.new
new_block.save
end
end
end
schedule file :
# config/schedule.rb
job_type :sidekiq, "cd :path && :environment_variable=:environment bundle exec sidekiq-client -q myapps push :task :output"
every 1.minute, :roles => [:app] do
sidekiq "CloneRecordJob"
end
Sidekiq log :
2016-08-09T10:13:41.138Z 23668 TID-xvshg WARN: {"class":"CloneRecordJob","queue":"myapps","args":[],"retry":true,"jid":"98cb26a0dd7410a9be0f0200","created_at":1470737621.1380692,"enqueued_at":1470737621.1382036}
2016-08-09T10:13:41.141Z 23668 TID-xvshg WARN: NoMethodError: undefined method `jid=' for #<CloneRecordJob:0x0000000715cc30>
Note :
I'm sure that job is work when to call from controller.
# example method
def my_action
CloneRecordJob.perform_now
end
CloneRecordJob is an ActiveJob, not a Sidekiq::Worker. You can't use sidekiq-client-cli with ActiveJobs.

rails whenver gem , running a command only if certain condition passes.

We are using whenever gem with rails on our project. I understand that we can schedule a command using whenever gem like this.
every 1.day, :at => '6:00 am' do
command "echo 'hello'"
end
but my problem is that i want to execute this command only when some condition is met. something like this.
every 1.day, :at => '6:00 am' do
if User.any_new_user?
command "echo 'hello'"
end
end
how can we achieve this with the whenever and rails?
One possible solution i can think of is that i create a runner for this and check that condition there.Something like:
every 1.day, :at => '6:00 am' do
runner "User.say_conditional_hello"
end
and inside my user model:
def self.say_conditional_hello
`echo "Hello"`
end
Any suggestions on this approach or any new approach will be really helpful.
Thanks in advance!.
if you want to only schedule the task if the condition is true then I don't think its possible you can schedule a task then when its time for running the task, the code can decide if it should be run or not, depending on your conditions
One possible solution i can think of is that i create a runner for this and check that condition there.Something like:
Yes this is one way of handeling this, however IMO the best behavior when using whenever is creating a rake task that checks for conditions then executes your code or perform your job
Something like:
Rake Task
namespace :user do
desc "description"
task check_for_new: :environment do
if User.any_new_user?
# code
end
end
end
in your schedule.rb file
every 1.day, :at => '6:00 am' do
rake "user:check_for_new"
end

Resources