Resque::Mailer的运作
跟踪一下include了Resque::Mailer的一个ActionMailer::Base子类Notifier的运作
[2] pry(main)> binding.trace_tree(htmp: 'resque_mailer'){ Notifier.send_an_email('a@b.com', 'subject', 'content').deliver }
Rendered notifier/send_an_email.html.erb within layouts/notifier (1.7ms)
Notifier#send_an_email: processed outbound mail in 70.8ms
=> true
得调用栈如下:
基本流程如下:

ActionMailer::Base的子类只需定义实例方法,调用时按类方法来调,然后进入method_missing,如果方法action_methods计算出的controller实例方法包含该方法名,则将实际类名、方法名和参数包装成一个MessageDecoy
module Resque
module Mailer
class << self
def included(base)
base.extend(ClassMethods)
end
end
module ClassMethods
def method_missing(method_name, *args)
if action_methods.include?(method_name.to_s)
MessageDecoy.new(self, method_name, *args)
else
super
end
end
MessageDecoy的deliver就是通过Resque塞到redis里
def deliver
return deliver! if environment_excluded?
if @mailer_class.deliver?
begin
resque.enqueue(@mailer_class, @method_name, @serialized_args)
rescue Errno::ECONNREFUSED, Redis::CannotConnectError
logger.error "Unable to connect to Redis; falling back to synchronous mail delivery" if logger
deliver!
end
end
end
注意塞进resque的参数应是能准确序列化和反序列化的