Task/Future in Ruby

Scheduling stuff in the future

You need to create an ActionJob with rails generate job your_job_name.
Then you can delay its execution

YourJob.set(wait_until: 1.day.from_now)

For this to work you indeed need a Job queue to be configured for your project. I personally recommend Sidekiq

Sadly, you will have a hard time avoiding setting up a gem for this.

How to schedule a function to execute at a future time?

With DelayedJob you can do something like

  def in_the_future
# Some other code
end
handle_asynchronously :in_the_future, :run_at => Proc.new { 10.hours.from_now }

Very nice? :) I suggest you read the documentation as linked by jared

Schedule a task in days or months

take a look at whenever gem

Seems like using

every '0 0 23 12 *' do 
...
end

would work for this. It can take cron syntax so minute hour day month day-of-week. So this will run every December 23rd at 12:00am regardless of what day of the week that is.

Is it a bad idea to use a future inside a singleton class?

This isn't necessarily a bad thing. The Future will make sure that the objects returned will be visible across threads. The thread pool is fixed at size of 1, so if there are concurrent requests the second one blocks until the only worker thread becomes available, by which time it has handed off its results from the previous task. No overlap should be occurring.

rails periodic task

Generally speaking, there's no built in way that I know of to create a periodic task within the application. Rails is built on Rack and it expects to receive http requests, do something, and then return. So you just have to manage the periodic task externally yourself.

I think given the frequency that you need to run the task, a decent solution could be just to write yourself a simple rake task that loops forever, and to kick it off at the same time that you start your application, using something like Foreman. Foreman is often used like this to manage starting up/shutting down background workers along with their apps. On production, you may want to use something else to manage the processes, like Monit.

How do I wait for multiple asynchronous operations to finish before sending a response in Ruby on Rails?

I ended up answering my own question after some more research into the concurrent-ruby library. Futures ended up being what I was after! Simply put, they execute a block of code in a background thread and attempting to access the Future's calculated value blocks the main thread until that background thread has completed its work. My Rails controller actions end up looking like:

def index
op1 = Concurrent::Future.execute { get_request }
op2 = Concurrent::Future.execute { another_request }

render text: "The result is #{result(op1.value, op2.value)}."
end

The line with render blocks until both async tasks have finished, at which point result can begin running.



Related Topics



Leave a reply



Submit