Search code examples
ruby-on-railsrubycronschedulerrufus-scheduler

Rails Rufus Scheduler Persistence


I have a rufus scheduler in my Rails app that I'm using to record/insert data every 5 minutes from 9:30AM to 4:00PM Mon-Fri. The method containing this action is fired as soon as user is registered. BUT this logging job is intercepted and terminated once user logs out.

Could anyone help in figuring out how to persist the logging method even when the user logs out/session is destroyed?

I am calling the logging method in my Users controller create method and I've set up the logging method in the User model.

Any help would be greatly appreciated!


Solution

  • That sounds convoluted. Why don't you use a single scheduled job that is run every 5 minutes from 9:30AM to 4:00PM Mon to Fri for every User registered in the system.

    do_log =
      lambda do
        User.where(status: 'active').each do |u|
          # do the insertion for the user...
        end
      end
    scheduler.cron('30,35,40,45,50,55 9 * * mon-fri America/New_York', &do_log)
    scheduler.cron('*/5 10-15 * * mon-fri America/New_York', &do_log)
    

    The User.where(status: 'active') is Sequel, it's probably different in Rails, but I am sure you can translate and adapt to your setting and needs.

    Thus, as soon as a User is registered in your system, the logging will begin for him, even if he's logged out.

    Yes, I know it's not a single job, it's two jobs, but that takes care of the "0930 to 1630" requirement.

    Maybe that's not what you want, but you are not very clear in your question...

    Update 2021-01-30 - 1416+0900

    @hurricanenara commented:

    I'm not certain where the do_log would be called to act as an all-encompassing job that will be applied to all "active" users during the scheduled times

    The do_log will be called '30,35,40,45,50,55 9 * * mon-fri America/New_York' and '*/5 10-15 * * mon-fri America/New_York' which corresponds to your requirement:

    every 5 minutes from 9:30AM to 4:00PM Mon-Fri

    If it is easier to you, the do_log can be "forgotten" if writing

    scheduler.cron('30,35,40,45,50,55 9 * * mon-fri America/New_York') do
      User.where(status: 'active').each do |u|
        # do the insertion for the user...
      end
    end
    scheduler.cron('*/5 10-15 * * mon-fri America/New_York') do
      User.where(status: 'active').each do |u|
        # do the insertion for the user...
      end
    end
    

    As you can see, the do_log lambda avoids a repetition (Don't Repeat Yourself, DRY).

    This method assumes that when a "User is registered" in your system, they get added to the database in a user table fronted by a User model. The do_log simply iterates over all the user whose status is "active" (not "left", or "revoked", or "whatever"), and records information for that particular user.

    Your problem description is vague. I'm guessing that you want to log for each user, because you want to log the information "even when the user logs out/session is destroyed".

    I don't know what you mean by "persist the logging method". I'm not sure you mean "persist to disk", so my guess is that you mean "keep on running".

    It is your responsibility as a developer to clearly state your problem. Most of the time that effort at clearly stating the problem will yield the answer to you without requiring another developer to listen. See also Rubber Ducking.