Question

  1. I have a rake task send_emails which send e-mails to lot of people. I call this rake task from controller as mentioned in Rake in Background railscast. But I want to schedule this rake task to run at a particular date and time, which is not same for everyday (it's not a cron job). The date and time are set dynamically from a form.

  2. For the above implemented rake task for sending emails, I want to show the status of the mailing process to the end-user. For instance, say there is a response object in the rake task which I can use as response.status,response.delivered?,response.address, etc. How can I access this object ( or any variable) in the rake file in my controller?

I don't want to use delayed_job but want to implement it's functionality of run_at and in_the_future. Also the whenever gem won't be able to solve my first problem coz I won't be able to pass date and time to it's scheduler.

Was it helpful?

Solution

First thing, calling rake task from controller is a bad practice. Ryan published that video at 2008 since that many better solution have came up. You shouldn't ignore it.

I suggest you to use delayed_job, it serves your needs in a great way. Since, if you want to invoke task dynamically, there should be some checker which will continuously check the desire field every second. Delayed job keep checking its database every time, you can use that.

Anyway,You can use something like this

def self.run_when
  Scheduler.all.each do |s|
    if d.dynamically_assigned_field < 1.second.ago
       d.run_my_job!
       d.status = "finished"
       d.save
    end
  end
end 

And, in model you can do something like this

 def run_my_job!
   self.status = "processing"
   self.save
   long_running_task
 end

One thing also you should keep in mind that if too many workers/batch/cron job starts at run at same it will fight for resources and may enter into deadlock state. As per your server capacity, you should limit the running jobs.

Sidekiq is also a good option you can consider. Personally, i like sidekiq because it doesn't hit my database everytime , scales very effectively. It uses redis but it is expensive.

OTHER TIPS

I would create new model for mail job, like this:

app/models/mail_job.rb

class MailJob

    attr_accessible :email, :send_at, :delivered

    scope :should_deliver, -> { where(delivered: false).where('send_at <= ?', Time.now) }

    def should_deliver?
        !delivered? && send_at <= Time.now 
    end        

    ...   

end 

And use Sidekiq + Sidetiq, running every minute (or any other interval) and checking for mail jobs that should be delivered.

Hope this helps!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top