2010-06-09 62 views
4

当试图向用户发送电子邮件以重置其密码时,我不断收到执行超时错误。其他邮件程序功能可以工作,所以我知道配置设置是正确的。标题写着: “超时::错误的密码resetsController#创建”ActionMailer执行超时

这里是password_resets_controller:

def create 
@user = User.find_by_email(params[:email]) 
if @user 
    User.deliver_password_reset_instructions(@user.id) 
    flash[:notice] = "Instructions to reset your password have been emailed to you. " + 
    "Please check your email." 
    redirect_to '/' 
else 
    flash[:notice] = "No user was found with that email address" 
    render :action => :new 
end 
end 

这里是内部User.rb

def self.deliver_password_reset_instructions(user_id) 
user = User.find(user_id) 
user.reset_perishable_token! 
Emailer.deliver_password_reset_instructions(user) 
end 

的方法。最后,在这里是emailer.rb里面的实际方法:

default_url_options[:host] = "http://0.0.0.0:3000" #development 
def password_reset_instructions(user) 
    @subject       = "Application Password Reset" 
    @from        = '[email protected]' 
    @recipients       = user.email 
    @sent_on       = Time.now 
    @body["edit_password_reset_url"] = edit_password_reset_url(user.perishable_token) 
    @headers["X-SMTPAPI"] = "{\"category\" : \"Password Recovery\"}"#send grid category header 
    end 

为什么“密码”我n引用的错误消息导致超时::错误

回答

1

从主控制器请求线程发送电子邮件(或其他长时间运行的进程)不是一个好主意。发送电子邮件可能会由于各种原因而超时,这些原因不受您的控制(例如,出站电子邮件传送服务器处于关闭状态),并且您不希望应用程序服务器和用户因此受到影响。

更好的方法是使用延迟作业(DJ)等排队机制对这些电子邮件任务进行排队,并让它们在控制器线程之外进行处理。

参见本https://github.com/collectiveidea/delayed_job

集成(或其他排队系统)到您的Rails应用程序相当简单。据说rails 4已经建立了排队服务(我还没有使用)http://blog.remarkablelabs.com/2012/12/asynchronous-action-mailer-rails-4-countdown-to-2013

举例来说,如果你在你的应用程序中使用的DJ,新的代码看起来像下面

def self.deliver_password_reset_instructions(user_id) 
user = User.find(user_id) 
user.reset_perishable_token! 
# this is the only line that changes 
Emailer.delay.deliver_password_reset_instructions(user) 
end 

的作业存储在数据库中,当像超时错误发生重试。

您可以在github页面上阅读更多关于DJ的内容。