开发者

ActionMailer execution timeout

When trying to send an email to the user for reseting their password, I keep getting an execution timed out error. Other mailer functions work, so I know that the config settings are correct. The header reads: "Timeout::Error in Password resetsController#create"

Here is the 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

Here is the method inside of 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

Finally, here is the actual method inside of emailer.rb:

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

Why is "Password" in the error message referred to causing a timeout::error


Sending email (or other long running processes) from the main controller request thread is not a good idea. The sending of the email can time out for a variety of reasons that are not under your control (e.g. the outbound email delivery server being down) and you don't want your application server and users to suffer due to that.

A better approach is to use a queuing mechanism like Delayed Job (DJ) to queue these email tasks, and have them be processed outside of your controller threads.

See https://github.com/collectiveidea/delayed_job

Integration of this (or another queuing system) into your rails app is fairly simple. And rails 4 is said to have built in queuing services (which I'm yet to use) http://blog.remarkablelabs.com/2012/12/asynchronous-action-mailer-rails-4-countdown-to-2013.

For instance, if you use DJ in your app, the new code will look like below

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

The jobs are stored in the database, and re-tried when errors like time outs happen.

You can read more about DJ on the github page.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜