Rufus Scheduler not running in production Nginx/Passenger - ruby-on-rails

I have a Rails app running on Nginx/Passenger. It has a rufus-scheduler cron job that runs in the background and sends out notifications via email.
When I start up the app in production on Nginx/Passenger, the emails don't get sent. In the production logs it doesn't show any logs for rufus-scheduler.
I'm stuck in this problem. Not able to debug the scheduler.
But after reading some issues & articles, I am sure that scheduler thread is kill on production by passenger.
Code snippet:
Example:
require 'rufus-scheduler'
scheduler = Rufus::Scheduler::singleton
scheduler.cron '0 12 * * *' do
puts "alert scheduler called at"
puts Time.now
system("rake trigger:email RAILS_ENV=production")
end
Kindly help me on the conf for the passenger/nginx that allow the scheduler thread to run & trigger the mails.

You need to set this in passanger config block
passenger_spawn_method direct;

Related

How can I test sidekiq-scheduler in my local?

I am trying to add couple of scheduled workers to my rails application. These workers will be crawling different sites in given intervals.
I want to test these workers but not able to do it. I am starting redis and my application. What should I do to see whether my scheduled jobs are working or not?
Here is my crawler class:
class AyedasCrawler
include Sidekiq::Worker
and my sidekiq.yml is:
:schedule:
ayedas_crawler:
cron: '0 * * * * *' # Runs once per minute
class: AyedasCrawler
start the sidekiq worker and the scheduler processes by running
bundle exec sidekiq or sidekiq from your app root in the command-line.
sidekiq-scheduler provides an extension to the Sidekiq web interface that adds a Recurring Jobs page.
There are two ways to do this:
In your routes.rb file, just below the require 'sidekiq/web', add require 'sidekiq-scheduler/web'
In your config.ru, just below the require 'sidekiq/web', add
require 'sidekiq-scheduler/web'
run Sidekiq::Web
On the browser, goto ==> http://localhost:{port}/sidekiq/recurring-jobs. where {port} is the port your application is running in.
You will see the list of scheduled jobs for your application and some other details about it.
Read more in the official documentation
You need to run Sidekiq process as well.
bundle exec sidekiq
It will start both worker/s and the scheduler
If you wish to test it using rspec, you can to the following:
it 'spawns scheduled workers' do
Sidekiq::Cron::Job.load_from_hash YAML.load_file('config/sidekiq.yml')[: schedule]
Sidekiq::Cron::Job.all.each(&:enque!)
expect(AyedasCrawler.jobs.size).to be(1)
end
It loads the YAML configuration, enqueues all the jobs, and asserts if the job has been enqued.
Using this method you can validate if your schedule YAML is correct. It will NOT test CRON syntax and scheduled intervals.
I'm also using https://github.com/philostler/rspec-sidekiq to allow sidekiq testing without jobs actually being executed.

Rufus Scheduler not running when rails server runs as daemon

I have a a rails app that is using Rufus Scheduler. When I turn on the rails server with:
rails s --port=4000
Rufus scheduler runs its tasks. If I run the rails server with:
rails s --port=4000 --daemon
Rufus no longer does its tasks. I added a couple of log messages. Here is the schedule code:
class AtTaskScheduler
def self.start
scheduler = Rufus::Scheduler.new
p "Starting Attask scheduler"
scheduler.every('5m') do
# test sending hip chat message
issue = Issue.new
issue.post_to_hipchat("Starting sync with AtTask","SYNC")
p "Launching Sync"
Issue.synchronize
end
end
end
Hipchat never gets the message from the scheduler and the log never gets the statement "Launching Sync".
Any ideas on what may be causing this?
There is documentation of this issue in the rufus-scheduler docs:
There is the handy rails server -d that starts a development Rails as
a daemon. The annoying thing is that the scheduler as seen above is
started in the main process that then gets forked and daemonized. The
rufus-scheduler thread (and any other thread) gets lost, no scheduling
happens.
I avoid running -d in development mode and bother about daemonizing
only for production deployment.
These are two well crafted articles on process daemonization, please
read them:
http://www.mikeperham.com/2014/09/22/dont-daemonize-your-daemons/
http://www.mikeperham.com/2014/07/07/use-runit/
If anyway, you need something like rails server -d, why not try bundle exec unicorn -D
instead? In my (limited) experience, it worked out of the box (well,
had to add gem 'unicorn' to Gemfile first).

Rails - Passenger and Nginx preventing rufus-scheduler from scheduling in production mode

I am using Rufus Scheduler to call a function once every 2 minutes.
In development mode when running rufus scheduler with WEBrick the system works as expected and my function is called every 2 minutes.
When I deploy to our production server which runs passenger and NGINX the scheduler does not call the function anymore.
I am assuming this is to do with threads, with the scheduler running on a separate thread that might be getting destroyed on our production server.
I have seen answers for similar issues when using Passenger and Apache together, but I am unable to come up with a solution for running rufus scheduler with passenger and NGINX in production mode.
Any help would be appreciated.
Code below setting up rufus
# :nocov:
require 'rufus-scheduler'
include TwitterParser
unless ENV['NODAEMON'] || Rails.env != 'production'
scheduler = Rufus::Scheduler.new
TwitterParser.set_up
scheduler.every '2m' do
begin
TwitterParser.parse_tweets
rescue Twitter::Error::TooManyRequests => error
puts 'Too Many Twitter requests, resets in: ' + error.rate_limit.reset_in.to_s
end
end
end
# :nocov:
Please read the rufus-scheduler FAQ.
https://github.com/jmettraux/rufus-scheduler#faq
It contains links to (old) articles about Passenger + rufus-scheduler
Amog them, this SO answer by one of the authors of Passenger might help:
rufus cron job not working in Apache/Passenger
Have a good time.

How to daemonize Sidekiq workers in Heroku?

The sidekiq workers get terminated in Heroku very frequently. It should be started every time.
How can we make these workers to run without getting terminated in Heroku?
Do we have any configurations for Sidekiq or Heroku / can we daemonize the Sidekiq and make it to run in Heroku without terminating.
Please help!
I have been using this sidekiq with rufus-scheduler for my Herokuapp.
Add your scheduler task in rails initializers(#app/config/initializers/task_scheduler.rb) It send daily status at 9am IST.
scheduler = Rufus::Scheduler.new
scheduler.cron '00 09 * * * Asia/Kolkata' do
puts "it's 9am! good morning!"
User.daily_status
end
scheduler.every '10s' do
Rails.logger.info "hello, it's #{Time.now}"
end

Rufus scheduler not logging in production

My rails app kicks off a process with rufus-scheduler in an initializer. Here's a stripped-down version of the initializer's code:
# config.logger isn't available here, so we have to grab it from the Rails object
logger = RAILS_DEFAULT_LOGGER
logger.warn(Time.now.to_s + ": Starting Rufus Scheduler")
# run every Wednesday at 10 AM
cron_string = '0 10 * * 3'
scheduler = Rufus::Scheduler.start_new
scheduler.cron cron_string do
logger.warn(Time.now.to_s + ": Starting Background Process")
(do work here)
logger.warn(Time.now.to_s + ": Finished Background Process")
end
logger.warn(Time.now.to_s + ": Rufus Scheduler set Background Process to run with the following cron string: [#{cron_string}]")
In all environments, the code runs like a champ. The populate process does its thing and finishes gracefully. The problem, however, is with logging. When RAILS_ENV is set to "production", the messages inside the cron block don't log at all.
I'm using Passenger 2.2.9 and Rails 2.3.5. I figure one of these two things is preventing the process from logging. Can anyone tell me which it is and how to get it to log in production?
OK, found the problem, thanks to this article: http://earthcode.com/blog/2009/05/rails_script_runner_logging_cron.html
Turns out the logger will not auto-flush in production. So, I just added
logger.flush
to the end of the process and BANG everything worked.

Resources