Skip to content

Commit

Permalink
Use synchronous queue by default. Separate queued message delivery jo…
Browse files Browse the repository at this point in the history
…bs from the queued message wrappers so the queue itself needn't be marshaled (due to queue reference QueuedMessage).
  • Loading branch information
jeremy committed Sep 17, 2012
1 parent b881be7 commit 2a30150
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 27 deletions.
2 changes: 2 additions & 0 deletions actionmailer/lib/action_mailer/base.rb
Expand Up @@ -4,6 +4,7 @@
require 'active_support/core_ext/string/inflections'
require 'active_support/core_ext/hash/except'
require 'active_support/core_ext/module/anonymous'
require 'active_support/queueing'
require 'action_mailer/log_subscriber'

module ActionMailer #:nodoc:
Expand Down Expand Up @@ -393,6 +394,7 @@ class Base < AbstractController::Base
}.freeze

class_attribute :queue
self.queue = ActiveSupport::SynchronousQueue.new

class << self
# Register one or more Observers which will be notified when mail is delivered.
Expand Down
30 changes: 20 additions & 10 deletions actionmailer/lib/action_mailer/queued_message.rb
Expand Up @@ -5,23 +5,33 @@ 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
@queue = queue
@job = DeliveryJob.new(mailer_class, method_name, args)
end

def __getobj__
@actual_message ||= @mailer_class.send(:new, @method_name, *@args).message
@job.message
end

def run
__getobj__.deliver
# Queues the message for delivery.
def deliver
tap { @queue.push @job }
end

# Will push the message onto the Queue to be processed
def deliver
@queue << self
class DeliveryJob
def initialize(mailer_class, method_name, args)
@mailer_class = mailer_class
@method_name = method_name
@args = args
end

def message
@message ||= @mailer_class.send(:new, @method_name, *@args).message
end

def run
message.deliver
end
end
end
end
1 change: 0 additions & 1 deletion actionmailer/test/abstract_unit.rb
Expand Up @@ -27,7 +27,6 @@

FIXTURE_LOAD_PATH = File.expand_path('fixtures', File.dirname(__FILE__))
ActionMailer::Base.view_paths = FIXTURE_LOAD_PATH
ActionMailer::Base.queue = ActiveSupport::SynchronousQueue.new

class MockSMTP
def self.deliveries
Expand Down
23 changes: 7 additions & 16 deletions actionmailer/test/base_test.rb
Expand Up @@ -412,7 +412,7 @@ def teardown
BaseMailer.deliveries.clear
BaseMailer.expects(:deliver_mail).once
mail = BaseMailer.welcome.deliver
assert_instance_of Mail::Message, mail
assert_equal 'The first email on new API!', mail.subject
end

test "calling deliver on the action should increment the deliveries collection if using the test mailer" do
Expand All @@ -422,24 +422,15 @@ def teardown
assert_equal(1, BaseMailer.deliveries.length)
end

def stub_queue(klass, queue)
Class.new(klass) {
extend Module.new {
define_method :queue do
queue
end
}
}
end

test "delivering message asynchronously" do
testing_queue = ActiveSupport::TestQueue.new
AsyncMailer.delivery_method = :test
AsyncMailer.deliveries.clear
stub_queue(AsyncMailer, testing_queue).welcome.deliver
assert_equal(0, AsyncMailer.deliveries.length)
testing_queue.drain
assert_equal(1, AsyncMailer.deliveries.length)

AsyncMailer.welcome.deliver
assert_equal 0, AsyncMailer.deliveries.length

AsyncMailer.queue.drain
assert_equal 1, AsyncMailer.deliveries.length
end

test "calling deliver, ActionMailer should yield back to mail to let it call :do_delivery on itself" do
Expand Down
1 change: 1 addition & 0 deletions actionmailer/test/mailers/async_mailer.rb
@@ -1,2 +1,3 @@
class AsyncMailer < BaseMailer
self.queue = ActiveSupport::TestQueue.new
end

0 comments on commit 2a30150

Please sign in to comment.