mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Action Mailer async flag is true by default using a Synchronous impl
This commit is contained in:
parent
b4b5971ff7
commit
34b23e7110
10 changed files with 61 additions and 79 deletions
|
@ -1,41 +0,0 @@
|
|||
require 'delegate'
|
||||
|
||||
module ActionMailer
|
||||
module Async
|
||||
def method_missing(method_name, *args)
|
||||
if action_methods.include?(method_name.to_s)
|
||||
QueuedMessage.new(queue, self, method_name, *args)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def queue
|
||||
Rails.queue
|
||||
end
|
||||
|
||||
class QueuedMessage < ::Delegator
|
||||
attr_reader :queue
|
||||
|
||||
def initialize(queue, mailer_class, method_name, *args)
|
||||
@queue = queue
|
||||
@mailer_class = mailer_class
|
||||
@method_name = method_name
|
||||
@args = args
|
||||
end
|
||||
|
||||
def __getobj__
|
||||
@actual_message ||= @mailer_class.send(:new, @method_name, *@args).message
|
||||
end
|
||||
|
||||
def run
|
||||
__getobj__.deliver
|
||||
end
|
||||
|
||||
# Will push the message onto the Queue to be processed
|
||||
def deliver
|
||||
@queue << self
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,4 +1,5 @@
|
|||
require 'mail'
|
||||
require 'action_mailer/queued_message'
|
||||
require 'action_mailer/collector'
|
||||
require 'active_support/core_ext/string/inflections'
|
||||
require 'active_support/core_ext/hash/except'
|
||||
|
@ -464,19 +465,6 @@ module ActionMailer #:nodoc:
|
|||
super || action_methods.include?(method.to_s)
|
||||
end
|
||||
|
||||
# Will force ActionMailer to push new messages to the queue defined
|
||||
# in the ActionMailer class when set to true.
|
||||
#
|
||||
# class WelcomeMailer < ActionMailer::Base
|
||||
# self.async = true
|
||||
# end
|
||||
def async=(truth)
|
||||
if truth
|
||||
require 'action_mailer/async'
|
||||
extend ActionMailer::Async
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def set_payload_for_mail(payload, mail) #:nodoc:
|
||||
|
@ -491,10 +479,18 @@ module ActionMailer #:nodoc:
|
|||
payload[:mail] = mail.encoded
|
||||
end
|
||||
|
||||
def method_missing(method, *args) #:nodoc:
|
||||
return super unless respond_to?(method)
|
||||
new(method, *args).message
|
||||
def method_missing(method_name, *args)
|
||||
if action_methods.include?(method_name.to_s)
|
||||
QueuedMessage.new(queue, self, method_name, *args)
|
||||
else
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def queue
|
||||
Rails.queue
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
attr_internal :message
|
||||
|
|
27
actionmailer/lib/action_mailer/queued_message.rb
Normal file
27
actionmailer/lib/action_mailer/queued_message.rb
Normal file
|
@ -0,0 +1,27 @@
|
|||
require 'delegate'
|
||||
|
||||
module ActionMailer
|
||||
class QueuedMessage < ::Delegator
|
||||
attr_reader :queue
|
||||
|
||||
def initialize(queue, mailer_class, method_name, *args)
|
||||
@queue = queue
|
||||
@mailer_class = mailer_class
|
||||
@method_name = method_name
|
||||
@args = args
|
||||
end
|
||||
|
||||
def __getobj__
|
||||
@actual_message ||= @mailer_class.send(:new, @method_name, *@args).message
|
||||
end
|
||||
|
||||
def run
|
||||
__getobj__.deliver
|
||||
end
|
||||
|
||||
# Will push the message onto the Queue to be processed
|
||||
def deliver
|
||||
@queue << self
|
||||
end
|
||||
end
|
||||
end
|
|
@ -11,6 +11,7 @@ end
|
|||
require 'minitest/autorun'
|
||||
require 'action_mailer'
|
||||
require 'action_mailer/test_case'
|
||||
require 'rails/queueing'
|
||||
|
||||
silence_warnings do
|
||||
# These external dependencies have warnings :/
|
||||
|
@ -27,6 +28,14 @@ ActionView::Template.register_template_handler :bak, lambda { |template| "Lame b
|
|||
FIXTURE_LOAD_PATH = File.expand_path('fixtures', File.dirname(__FILE__))
|
||||
ActionMailer::Base.view_paths = FIXTURE_LOAD_PATH
|
||||
|
||||
class ActionMailer::Base < AbstractController::Base
|
||||
class << self
|
||||
def queue
|
||||
@queue ||= Rails::Queueing::Container.new(Rails::Queueing::SynchronousQueue.new)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class MockSMTP
|
||||
def self.deliveries
|
||||
@@deliveries
|
||||
|
|
|
@ -575,11 +575,11 @@ class BaseTest < ActiveSupport::TestCase
|
|||
end
|
||||
|
||||
test "being able to put proc's into the defaults hash and they get evaluated on mail sending" do
|
||||
mail1 = ProcMailer.welcome
|
||||
mail1 = ProcMailer.welcome['X-Proc-Method']
|
||||
yesterday = 1.day.ago
|
||||
Time.stubs(:now).returns(yesterday)
|
||||
mail2 = ProcMailer.welcome
|
||||
assert(mail1['X-Proc-Method'].to_s.to_i > mail2['X-Proc-Method'].to_s.to_i)
|
||||
mail2 = ProcMailer.welcome['X-Proc-Method']
|
||||
assert(mail1.to_s.to_i > mail2.to_s.to_i)
|
||||
end
|
||||
|
||||
test "we can call other defined methods on the class as needed" do
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
class AsyncMailer < BaseMailer
|
||||
self.async = true
|
||||
end
|
||||
|
|
|
@ -472,7 +472,6 @@ The following configuration options are best made in one of the environment file
|
|||
|+delivery_method+|Defines a delivery method. Possible values are <tt>:smtp</tt> (default), <tt>:sendmail</tt>, <tt>:file</tt> and <tt>:test</tt>.|
|
||||
|+perform_deliveries+|Determines whether deliveries are actually carried out when the +deliver+ method is invoked on the Mail message. By default they are, but this can be turned off to help functional testing.|
|
||||
|+deliveries+|Keeps an array of all the emails sent out through the Action Mailer with delivery_method :test. Most useful for unit and functional testing.|
|
||||
|+async+|Setting this flag will turn on asynchronous message sending, message rendering and delivery will be pushed to <tt>Rails.queue</tt> for processing.|
|
||||
|+default_options+|Allows you to set default values for the <tt>mail</tt> method options (<tt>:from</tt>, <tt>:reply_to</tt>, etc.).|
|
||||
|
||||
h4. Example Action Mailer Configuration
|
||||
|
@ -535,19 +534,7 @@ In the test we send the email and store the returned object in the +email+ varia
|
|||
|
||||
h3. Asynchronous
|
||||
|
||||
You can turn on application-wide asynchronous message sending by adding to your <tt>config/application.rb</tt> file:
|
||||
|
||||
<ruby>
|
||||
config.action_mailer.async = true
|
||||
</ruby>
|
||||
|
||||
Alternatively you can turn on async within specific mailers:
|
||||
|
||||
<ruby>
|
||||
class WelcomeMailer < ActionMailer::Base
|
||||
self.async = true
|
||||
end
|
||||
</ruby>
|
||||
Rails provides a Synchronous Queue by default. If you want to use an Asynchronous one you will need to configure an async Queue provider like Resque. Queue providers are supposed to have a Railtie where they configure it's own async queue.
|
||||
|
||||
h4. Custom Queues
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ module Rails
|
|||
@exceptions_app = nil
|
||||
@autoflush_log = true
|
||||
@log_formatter = ActiveSupport::Logger::SimpleFormatter.new
|
||||
@queue = Rails::Queueing::Queue
|
||||
@queue = Rails::Queueing::SynchronousQueue
|
||||
@queue_consumer = Rails::Queueing::ThreadedConsumer
|
||||
@eager_load = nil
|
||||
|
||||
|
|
|
@ -59,8 +59,5 @@ module <%= app_const_base %>
|
|||
# Version of your assets, change this if you want to expire all your assets.
|
||||
config.assets.version = '1.0'
|
||||
<% end -%>
|
||||
|
||||
# Enable app-wide asynchronous ActionMailer.
|
||||
# config.action_mailer.async = true
|
||||
end
|
||||
end
|
||||
|
|
|
@ -35,6 +35,14 @@ module Rails
|
|||
class Queue < ::Queue
|
||||
end
|
||||
|
||||
class SynchronousQueue < ::Queue
|
||||
def push(job)
|
||||
job.run
|
||||
end
|
||||
alias << push
|
||||
alias enq push
|
||||
end
|
||||
|
||||
# In test mode, the Rails queue is backed by an Array so that assertions
|
||||
# can be made about its contents. The test queue provides a +jobs+
|
||||
# method to make assertions about the queue's contents and a +drain+
|
||||
|
|
Loading…
Reference in a new issue