Search code examples
multithreadingruby-on-rails-3actionmailerpostmark

How to use multi-threading in rails 3?


I am sending mail to the users using actionmailer through postmark. This is my code in controller:

@users = User.where(some condition)
@product = Product.find_by_name(some name).first
for user in @users
  UserMailer.new_product_arrival(user, @product, home_url).deliver
end

and this my user_mailer.rb

def new_product_arrival(user,product,home_url)
  @from         = Settings.mailer_from_address
  @recipients   = user.login
  @sent_on      = Time.now
  @user = user
  @product = product
  @content_type = "text/html"
  @home_url = home_url
end

The problem is that if there are more than 10 users it takes a very long time because of the for loop. I need to know if we can handle this by using multi-threading or background job. I don't want to use background job, but can anyone tell me how to implement the above using multi-threading.

I am using ruby 1.8.7 and rails 3.0.7


Solution

  • There basically two ways to wrap your loop in order to get "multi-threading":

    1. Spwan a thread for each delivery and join them back to the main thread

      threads = []
      for user in @users
         threads << Thread.new do
           UserMailer.new_product_arrival(user, @product, home_url).deliver
         end
      end
      threads.each(&:join)
      
    2. fork over the entire rails app ( pretty messy but the rails app serving the request will respond immediately ) and have the process detached:

      process = fork do
        for user in @users
          UserMailer.new_product_arrival(user, @product, home_url).deliver
        end
        Process.kill("HUP") 
        #sends the kill signal to current Process, which is the Rails App sending your emails 
      end
      Process.detach(process)
      

    Hope that helps