如何在Rails 3中使用多线程?

14

我正在使用ActionMailer通过Postmark向用户发送邮件。这是我的控制器代码:

@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

这是我的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

问题在于如果有超过10个用户,由于 for 循环,会花费很长时间。我需要知道是否可以通过使用多线程或后台任务来解决这个问题。我不想使用后台任务,但有没有人能告诉我如何使用多线程实现上述操作。

我正在使用 Ruby 1.8.7 和 Rails 3.0.7。


1
我并不是一个 Ruby 专家(尚未),但 Postmark 支持发送批量电子邮件,因此如果您要向大量用户发送电子邮件,则使用它可能比为每个用户调用 API 更容易。 - Oren Mazor
4个回答

20

基本上有两种方法可以用来实现“多线程”循环:

  1. 为每个任务生成一个线程,再将它们加入到主线程中

    threads = []
    for user in @users
       threads << Thread.new do
         UserMailer.new_product_arrival(user, @product, home_url).deliver
       end
    end
    threads.each(&:join)
    
  2. 分叉整个Rails应用程序(相当混乱但处理请求的Rails应用程序将立即响应),并使进程分离:

  3. 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)
    

希望这有所帮助。


会在我的应用程序中尝试这个。 - anil.n
3
使用线程时,你可能希望在线程块的结尾处添加:ActiveRecord::Base.connection.close(如果线程会进行数据库调用,在你的示例中应该会有)。 - laffuste

1
我们的开发者 Artem最近对 Postmark gem进行了重大更新,使您能够轻松批量发送电子邮件,这应该可以让您更快地发送电子邮件。看一下吧。

0

尝试使用delayed_job宝石。这是一个基于数据库的后台作业宝石。例如,在电子商务网站中我们使用它来向用户发送订单确认电子邮件。

这些任务可以异步在后台执行,因为您的Rails应用程序不需要立即执行它们。


我不想使用后台作业。 -OP - Joshua Pinter

-4

我是来自肯尼亚内罗毕开发学校的Rails学生。我认为你可以试一试,你所遇到的问题是由于用户数量导致的延迟响应。你可以尝试使用长轮询技术,这是一个例子:

poll = function (){
  s.ajax{
       url:/'chat.json'
       data: { last_time: get last_time () }
     }}.done(function(data) {
     // handle data
     setTimeout(poll,1000);
     });
}

用你自己的方式尝试一下吧...这对于实时应用程序非常有用...你甚至可以使用ActionController::Live...我认为你对Rails中的线程很熟悉。上面的例子将帮助你,希望如此。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接