jmettraux/rufus-scheduler

scheduler.every vs scheduler.cron

hurricanenara opened this issue · 14 comments

Hello,
I am in the process of incorporating the Rufus Scheduler to insert a basic row of data in my Rails application every 5 minutes from 9:30AM to 4:00PM (inclusive) MON-FRI upon user registration.

The question I have is that, when I test out the process (user registration -> check a relational database for proper record generation with Rufus Scheduler), it works smoothly with the scheduler.every 5mdoblock, but does not work when I try to use the cron string like so:

    # create record every 5 minutes from 9:30 - 9:55)
    scheduler.cron '30-55/5 9 * * 1-5' do
        # Record data
    end
    # create record every 5 minutes from 10:00 - 15:55
    scheduler.cron '*/1 10-15 * * 1-5' do
        # Record data
    end
    # create record at 16:00
    scheduler.cron '0 16 * * 1-5' do
        # Record data
    end

The reason I'm preferring the scheduler.cron method over the scheduler.every is that the cron expression argument takes care of the conditionals I would have to otherwise cast for timeframe (09:30-16:00) and days (MON-FRI).

Am I missing something that somebody can kindly help me with in terms of the scheduler.cron doing nothing?
On a final note, the cron string approach works swimmingly when tested in a separate ruby file with the exception of running the scheduler.join line at the end.

I appreciate your help in advance.

Best,
Nara

Hello,

OK, so you have two setups:

  • separate Ruby file with a scheduler join
  • actual application

You're telling me

  • the cron schedule only works in the separate Ruby file
  • the every schedule works in both the separate Ruby file and the application

Is that right? I want to know if the every works in the actual application.

A second question: what server are you running your application on? Webrick, Puma, Passenger, Unicorn?

Thanks in advance for the precisions.

Third question: what do you mean by "doesn't work"?

  • nothing at all is done, nothing appears in the logs
  • nothing is done and some error appears in the logs

If there is an error, I'd like to see it.

Hi John,

Thank you for your quick response and drying up my scribble!

Yes, your outline of my current status is correct, and the every works on the application which is running on Puma.

Thank you.

Best,
Nara

Fourth question: your three cron strings are keyed to run only from Monday to Friday. We're now Saturday or Sunday (depending on the timezone), are you testing with cron strings that may trigger? Have you tried with something like "* * * * *" (every minute)?

Hi John,

Great point. I apologize for not being specific, I tested yesterday afternoon, Saturday, from 1-3pm with the MON-FRI or * also with */1

Does

scheduler.cron "* * * * *" do
  Rails.logger.info("TRIGGER #{Time.now}")
end

logs as expected in your application?

Thanks in advance for a clear answer.

Hi John,

To your earlier question regarding what I meant by my specific cron string "doesn't work", is the former: the action does not fire within the block, whether it be saving a record or logging Time.now.

To your last question, it does log as expected every minute.

Edited:
And if it helps, I just tried the below and it didn't work (at around 11:30 AM ET), also with * instead of 0-5

        scheduler.cron "*/1 10-15 * * 0-5" do
            Rails.logger.info("TRIGGER #{Time.now}")
        end

Thank you John.

Hello,

@hurricanenara wrote:

To your last question, it does log as expected every minute.

That's good to know.

I would need you to let this schedule run in your application:

scheduler.cron '* * * * *' do |job|
  Rails.logger.info '=' * 80
  Rails.logger.info Time.now
  Rails.logger.info '-' * 80
  Rails.logger.info [ :env_tz, ENV['TZ'] ].inspect
  Rails.logger.info [ :uname, (`uname -a` rescue nil) ].inspect
  Rails.logger.info [ :rv, RUBY_VERSION, :rp, RUBY_PLATFORM ].inspect
  Rails.logger.info [ :ra, (Rails::VERSION.to_s rescue :nora) ].inspect
  Rails.logger.info EtOrbi.render_nozone_time(Time.now.to_f)
  Rails.logger.info EtOrbi.platform_info
  Rails.logger.info [ :fu, Fugit::VERSION, :rs, Rufus::Scheduler::VERSION ].inspect
  Rails.logger.info '-' * 80
  Rails.logger.info Fugit.parse('*/1 5-15 * * 0-5').inspect
  Rails.logger.info [ :nt, Fugit.parse('*/1 5-15 * * 0-5').next_time.to_s ].inspect
  Rails.logger.info '-' * 80
end

It should emit something like

================================================================================
2021-01-25 05:45:00 +0900
--------------------------------------------------------------------------------
[:env_tz, nil]
[:uname, "OpenBSD yawara 6.8 GENERIC.MP#4 amd64\n"]
[:rv, "2.6.6", :rp, "x86_64-openbsd6.7"]
[:ra, :nora]
(secs:1611521100.3075597,utc~:"2021-01-24 20:45:00.3075597286224365",ltz~:"JST")
(etz:nil,tnz:"JST",tziv:"2.0.2",tzidv:nil,rv:"2.6.6",rp:"x86_64-openbsd6.7",win:false,rorv:nil,astz:nil,
  eov:"1.2.4", eotnz:#<TZInfo::DataTimezone: Asia/Tokyo>,eotnfz:"+0900",eotlzn:"Asia/Tokyo",eotnfZ:"JST",
  debian:nil,centos:nil,osx:"Asia/Tokyo")
[:fu, "1.4.0", :rs, "3.7.0"]
--------------------------------------------------------------------------------
#<Fugit::Cron:0x00000c5bb56ab6f8 @original="*/1 5-15 * * 0-5", @cron_s=nil, @seconds=[0], @minutes=nil, 
  @hours=[5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], @monthdays=nil, @months=nil,
  @weekdays=[[0], [1], [2], [3], [4], [5]], @zone=nil, @timezone=nil>
[:nt, "2021-01-25 05:46:00 +0900"]
--------------------------------------------------------------------------------

I would like to see what the schedule logs in your application.

Thanks in advance.

Another question: are you running Puma in clustered mode or not?

Hi John,
The code block emits:

================================================================================
2021-01-24 16:34:00 -0500
--------------------------------------------------------------------------------
[:env_tz, nil]
[:uname, "Darwin Naras-iMac.lan 19.6.0 Darwin Kernel Version 19.6.0: Thu Oct 29 22:56:45 PDT 2020;
  root:xnu-6153.141.2.2~1/RELEASE_X86_64 x86_64\n"]
[:rv, "2.5.1", :rp, "x86_64-darwin19"]
[:ra, "Rails::VERSION"]
(secs:1611524040.23899,utc~:"2021-01-24 21:34:00.23899006843566895",ltz~:"UTC")
(etz:nil,tnz:"EST",tziv:"1.2.7",tzidv:nil,rv:"2.5.1",rp:"x86_64-darwin19",win:false,rorv:"5.2.4.3",
  astz:[ActiveSupport::TimeZone, "Etc/UTC"],eov:"1.2.4",eotnz:#<TZInfo::DataTimezone: Etc/UTC>,eotnfz:"+0000",
  eotlzn:"Etc/UTC",eotnfZ:"UTC",debian:nil,centos:nil,osx:"zoneinfo/America/New_York")
[:fu, "1.4.2", :rs, "3.7.0"]
--------------------------------------------------------------------------------
#<Fugit::Cron:0x00007f99c8e29280 @original="*/1 5-15 * * 0-5", @cron_s=nil, @seconds=[0], @minutes=nil,
  @hours=[5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], @monthdays=nil, @months=nil,
  @weekdays=[[0], [1], [2], [3], [4], [5]], @zone=nil, @timezone=nil>
[:nt, "2021-01-25 05:00:00 +0000"]
--------------------------------------------------------------------------------

To your second question, I am running Puma in single mode.

Thanks for your help, John.

Hello,

I think your Rails application is set to Etc/UTC.

At 2021-01-24 16:34:00 -0500 (UTC 21:34:00), the next time for the cron "*/1 5-15 * * 0-5" is 2021-01-25 05:00:00 +0000 (midnight +0500).

I have the strong impression that you're thinking local time while your application is operating on UTC.

You can change the Rails application timezone or use a cron like "* 5-15 * * 0-5 America/New_York".

Thanks in advance.

Closing. Rufus-Scheduler latched on Rails timezone UTC while the OP expected results in America/New_York.

Thank you John for your unbelievably thorough help.

@hurricanenara you're welcome, have a nice evening!