jmettraux/rufus-scheduler

Running as standalone server

jjb opened this issue · 3 comments

jjb commented

Hi,

Thanks for what looks like a great project!

Maybe I'm misreading the readme but it seems like there is no explicit explanation for how to run rufus as a standalone server. I'm not sure if I'm not seeing this because it's very obvious that it's possible or because it's totally not intended to be used as such 😅

If I have a script schedule.rb

require 'rufus-scheduler'

scheduler = Rufus::Scheduler.new
scheduler.every '3h' do
  `rails runner 'Foo.archive_old_things'`
end

Is it good practice to then run this as a persistent process (e.g. in a heroku Procfile or with systemd) with bundle exec schedule.rb?

Furthermore, if I have a script that needs access to a rails app environment:

require 'rufus-scheduler'

scheduler = Rufus::Scheduler.new
scheduler.every '3h' do
  Foo.archive_old_things
end

Can I run it in a persistent process with bundle exec rails runner schedule.rb?

or will that not work for some reason, and it's better to use the approach suggested by https://github.com/Rykian/clockwork:

require 'config/boot'
require 'config/environment'

require 'rufus-scheduler'

scheduler = Rufus::Scheduler.new
scheduler.every '3h' do
  Foo.archive_old_things
end

Sorry if this is already covered somewhere - I'll try to submit an update for the readme if you think that's a good idea.

Hello,

the explicit explanation is "rufus-scheduler is not a cron replacement". It's not a crond, nor an atd replacement.

Maybe https://github.com/javan/whenever is a better tool for you.

I, personally, mostly use rufus-scheduler inside of Ruby applications (Rack - Sequel) to run jobs intermittently.

I think that testing will give the answer to your bundle exec ruby schedule.rb vs bundle exec rails runner schedule.rb. If your job requires the Rails support, bundle exec rails runner with require 'config/boot' et al is probably what you are looking for.

Regarding good practice, one has to know if the scheduling process is running or not, and, in case of errors, the errors must be logged somewhere. Heroku or self-hosted or whatever the solution, this differs.

These might also be interesting to you: https://devcenter.heroku.com/articles/scheduler and https://devcenter.heroku.com/articles/scheduled-jobs-custom-clock-processes#custom-clock-processes

I am not sure I'd want an addition to the README. That'd be widening the area for which people expect me to provide answers.

Closing the issue but not the conversation. Thanks.

jjb commented

Thanks for the quick response! everything you said to get me away from rufus-scheduler is pretty much the exact line of reasoning that brought me to rufus-scheduler 😄

  • heroku scheduler and cron have to instantiate a rails instance for each job, so don't allow running things every minute or 30 seconds or second
  • cron jobs, each with their own rails instance, have to fight each other for memory
  • the heroku custom clock process docs are a big contribution to how i'm thinking about the problem... but they never make recommendations for ruby projects to use to implement it. so in my search for a solution, i found rufus-scheduler to be the best-maintained solution
  • making sure it stays up is def something to explore... I think with a bare-bones invocation, heroku and other PaaS will behave as desired, but I should test
  • I've already got a good solution for error reporting in rails runners (below)

app/lib/runner_error_reporter.rb

class RunnerErrorReporter < Rails::Railtie
  runner do
    at_exit do
      next unless $!
      next if SystemExit == $!.class && $!.success?
      ErrorTrackerService.track_exception($!)
    end
  end
end

here's my analysis of the space:

image

Here's my POC (no require 'config/boot' needed)

schedule.rb

require 'rufus-scheduler'
scheduler = Rufus::Scheduler.new

scheduler.every '1 second' do
  puts User.count
end

scheduler.join

bundle exec rails runner schedule.rb

Excellent!