Scheduler works once - ruby-on-rails

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

Related

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

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

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.

Scheduled Jobs and Custom Clock Processes with Clockwork

I am trying to understand how to execute custom code with clockwork. This is the example lib/clock.rb file that Heroku uses in its devcenter document.
require File.expand_path('../../config/boot', __FILE__)
require File.expand_path('../../config/environment', __FILE__)
require 'clockwork'
include Clockwork
every(4.minutes, 'Queueing interval job') { Delayed::Job.enqueue IntervalJob.new }
every(1.day, 'Queueing scheduled job', :at => '14:17') { Delayed::Job.enqueue ScheduledJob.new }
What is IntervalJob and ScheduledJob? Where are these files supposed to be located? I want to run my own custom job that has access to my database records.
EDIT
This is my /lib/clock.rb
require 'clockwork'
require './config/boot'
require './config/environment'
module Clockwork
handler do |job|
puts "Running #{job}"
end
every(2.minutes, 'Filtering Streams') { Delayed::Job.enqueue FilterJob.new}
end
This is my /lib/filter_job.rb
class FilterJob
def perform
#streams = Stream.all
#streams.each do |stream|
# manipulating stream properties
end
end
end
I get the error:
uninitialized constant Clockwork::FilterJob (NameError)
/app/lib/clock.rb:11:in `block in <module:Clockwork>'
You need to do the following:
Firstly install the clockwork gem.
In your lib folder create a clock.rb
require 'clockwork'
require './config/boot'
require './config/environment'
module Clockwork
handler do |job|
puts "Running #{job}"
end
every(1.day, 'Creating Cycle', :at => '22:00') { Delayed::Job.enqueue CyclePlannerJob.new}
end
In the example your provided IntervalJob and ScheduledJob, are delayed jobs. Clockwork triggers them on the time specified. I am calling the CyclePlannerJob, this is what my file looks like.
lib/cycle_planner_job.rb
class CyclePlannerJob
def perform
CyclePlanner.all.each do |planner|
if Time.now.in_time_zone("Eastern Time (US & Canada)").to_date.send("#{planner.start_day.downcase}?")
planner.create_cycle
end
end
end
end
In my example everyday at 10pm, I am running the CyclePlanner job, which runs the delayed job I have setup. Similar to the Heroku example.
Bare in mind to use this you need to setup the clock work and delayed jobs on your Heroku app in the dashboard.
Also your Procfile should look like this.
worker: bundle exec rake jobs:work
clock: bundle exec clockwork lib/clock.rb
Let me know if you have any questions, I can go into more detail if needed.
Looks like name space issue. Move your filter_job.rb to models directory and try.

Resque scheduled jobs are stuck in pending queue

I'm creating a DripEmail campaign for my app and using resque scheduler to schedule the tasks.
I've sceduled a static job, which runs every day at a specific time and collect the user's list based on the drip settings and sends out an emailer to them.
This is my resque job user_follow_up.rb
class UserFollowUp
#queue = :user_follow_up
def self.perform
User.each do |u|
# Send the emailers to only those who are not converted
if !user.is_converted and Date.today <= user.next_email
stage(u)
end
end
end
end
This is my scheduler.yml
UserFollowUp:
cron: "0 16 * * *"
I have 2 resque workers, one has my default set of tasks and the other for scheduler.
rake environment resque:work QUEUE=publish_story,accept_story,image_queue,Mango_mailer
and
rake environment resque:scheduler QUEUE=user_follow_up
When I open the resque admin interface, I'm able to see my static job detected in the list. I clicked the Queue Now button to test it. It properly enqueues the task to the queue, but doesn't execute. It keeps these tasks in the pending queue forever.
This is my resque.rake, it's required
require 'resque/tasks'
require 'resque/scheduler/tasks'
require 'resque/scheduler/server'
require 'active_record'
require 'mongoid'
require 'action_controller/railtie'
require 'active_support/buffered_logger'
# load the Rails app all the time
namespace :resque do
puts 'Loading Rails environment for Resque'
task :setup => :environment do
# The schedule doesn't need to be stored in a YAML, it just needs to
# be a hash. YAML is usually the easiest.
Resque.schedule = YAML.load_file("#{Rails.root}/config/scheduler.yml")
Resque::Scheduler.dynamic = true
Resque.logger.info 'Resque Scheduler Initialized!'
Resque.before_first_fork do
# Open the new separate log file
logfile = File.open(File.join(Rails.root, 'log', 'resque.log'), 'a')
# Activate file synchronization
logfile.sync = true
# Create a new buffered logger
Resque.logger = ActiveSupport::BufferedLogger.new(logfile)
Resque.logger.level = Logger::INFO
Resque.logger.info 'Resque Logger Initialized!'
puts 'Resque Logger Initialized!'
end
end
task 'resque:pool:setup' do
Resque::Pool.after_prefork do |job|
Resque.redis.client.reconnect
end
end
end
And this is my Gemfile
gem 'resque', github: 'resque/resque' , branch: '1-x-stable'
gem 'resque_mailer', github: 'zapnap/resque_mailer'
gem 'resque-scheduler'
I'm not sure what is the issue here. Please help me with this fix.

Rake task not running from within worker

I don't understand why my rake task is not running from within a resque worker. Running
rake :send_this_email
from the console works fine, I just want to run it as a cron job (as follows) but something is not working proplerly while invoking the rake task from within the worker.
My rescue_schedule.yml
send_this_email:
cron: "*/2 * * * *"
class: SendThisEmailWorker
args:
description: "Send email when condition defined in rake task is met"
My send_this_email_worker.rb in workers directory, where the problem must be if I can manually call the rake task myself from the console?
require 'rake'
module SendThisEmailWorker
#queue = :send_this_email
def self.perform
Rake::Task["send_this_email"].invoke
end
end
When I start my dev server this send_this_email rake task should run every 2 minutes correct? It's not and the resque admin panel shows it as a job in the queue. What am I missing here?
Thanks for your attention.
UPDATED from gerep comment
require 'rake'
module SendThisEmailWorker
#queue = :send_this_email
def self.perform
puts "Hi from the console, I'm started"
Rake::Task["send_this_email"].invoke
end
end
Only require 'rake' is not enough. For example if you do
Rake::Task.tasks #list down all task
You will get []
You need to tell your worker class to load tasks.
Try this
require 'rake'
Rake::Task.clear # necessary to avoid tasks being loaded several times in dev mode
YOUR_APP_NAME::Application.load_tasks
module SendThisEmailWorker
#queue = :send_this_email
def self.perform
puts "Hi from the console, I'm started"
Rake::Task["send_this_email"].invoke
end
end
YOUR_APP_NAME is the name of your app and can be found at config/application.rb

Resources