Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

rails periodic task

I have a ruby on rails app in which I'm trying to find a way to run some code every few seconds.

I've found lots of info and ideas using cron, or cron-like implementations, but these are only accurate down to the minute, and/or require external tools. I want to kick the task off every 15 seconds or so, and I want it to be entirely self contained within the application (if the app stops, the tasks stop, and no external setup).

This is being used for background generation of cache data. Every few seconds, the task will assemble some data, and then store it in a cache which gets used by all the client requests. The task is pretty slow, so it needs to run in the background and not block client requests.

I'm fairly new to ruby, but have a strong perl background, and the way I'd solve this there would be to create an interval timer & handler which forks, runs the code, and then exits when done.
It might be even nicer to just simulate a client request and have the rails controller fork itself. This way I could kick off the task by hitting the URI for it (though since the task will be running every few seconds, I doubt I'll ever need to, but might have future use). Though it would be trivial to just have the controller call whatever method is being called by the periodic task scheduler (once I have one).

like image 619
phemmer Avatar asked Nov 12 '12 23:11

phemmer


1 Answers

Throwing out a solution just because it looks somewhat elegant and answers the question without any extra gems. In my scenario I wanted to run some code, but only after all my Sidekiq workers were done doing their thing.

First I defined a method to check if any workers were working...

def workers_working?
  workers = Sidekiq::Workers.new.map do |_process_id, _thread_id, work|
    work
  end
  workers.size > 0
end

Then we just call the method with a loop which sleeps between calls.

sleep 5 while workers_working?
like image 194
Stephen Avatar answered Nov 08 '22 20:11

Stephen