Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 4 - Mailer deliver_later not doing what I expect, blocks the UI

I have a rails app in which I have a function that send out quite a few emails. I would like to do it asynchronously and I thought that the method deliver_later would do that. Currently I have some delay from when the user clicks submit until the form is submitted - which is leads to a bad user experience (It is a quite simple form). My implementation looks like this:

def create

  respond_to do |format|
    if @competition.save
      [...]
      send_notification_to_team_members
    end
end

def send_notification_to_team_members
  @team.members.each do |member|
    unless member.user.eql?(current_user)
      Mailer.deliver_new_competition_notification(member.user,   @competition).deliver_later
    end
  end
end 

Currently it takes ~ 4 seconds for the action to be finished. I have also tried:

Mailer.deliver_new_competition_notification(member.user,  @competition).deliver_later(wait: 1.minute)

Then it takes even longer - I would estimate ~1 minute.

So, am I using deliver_later wrongly, or is the method not doing what I expect. In that case, is there another method I can use to improve my performance?

like image 530
Anders Avatar asked Feb 28 '15 08:02

Anders


1 Answers

deliver_later uses ActiveJob to provide asynchronous execution.

However ActiveJob does not provide asynchronicity itself - it is a unifying api layer that can be fulfilled by many backends. The default one just runs everything inline it is not async.

To get async usage you need to pick an asynchronous backend. You can configure the backend in your application's config

 config.active_job.queue_adapter = ...

In general most adapters require a corresponding gem (eg delayed_job, sidekiq, sucker_punch) which may have their own dependencies too (for example sidekiq requires that you use redis.

like image 179
Frederick Cheung Avatar answered Nov 14 '22 22:11

Frederick Cheung