Skip to content

Commit 9192027

Browse files
Merge pull request rails#47408 from packagethief/jh/action-mailer-deliver-later-queue
Allow mailer classes to customize the deliver_later queue name
2 parents e6087bd + fa17c9a commit 9192027

15 files changed

+109
-38
lines changed

actionmailer/CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
* The `deliver_later_queue_name` used by the default mailer job can now be
2+
configured on a per-mailer basis. Previously this was only configurable
3+
for all mailers via `ActionMailer::Base`.
4+
5+
Example:
6+
7+
```ruby
8+
class EventsMailer < ApplicationMailer
9+
self.deliver_later_queue_name = :throttled_mailer
10+
end
11+
```
12+
13+
*Jeffrey Hardy*
14+
115
* Email previews now include an expandable section to show all headers.
216

317
Headers like `Message-ID` for threading or email service provider specific

actionmailer/lib/action_mailer.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ module ActionMailer
5353
autoload :TestHelper
5454
autoload :MessageDelivery
5555
autoload :MailDeliveryJob
56+
autoload :QueuedDelivery
5657

5758
def self.eager_load!
5859
super

actionmailer/lib/action_mailer/base.rb

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -460,12 +460,14 @@ module ActionMailer
460460
# * <tt>deliveries</tt> - Keeps an array of all the emails sent out through the Action Mailer with
461461
# <tt>delivery_method :test</tt>. Most useful for unit and functional testing.
462462
#
463-
# * <tt>delivery_job</tt> - The job class used with <tt>deliver_later</tt>. Defaults to
464-
# +ActionMailer::MailDeliveryJob+.
463+
# * <tt>delivery_job</tt> - The job class used with <tt>deliver_later</tt>. Mailers can set this to use a
464+
# custom delivery job. Defaults to +ActionMailer::MailDeliveryJob+.
465465
#
466-
# * <tt>deliver_later_queue_name</tt> - The name of the queue used with <tt>deliver_later</tt>.
466+
# * <tt>deliver_later_queue_name</tt> - The queue name used by <tt>deliver_later</tt> with the default
467+
# <tt>delivery_job</tt>. Mailers can set this to use a custom queue. Defaults to <tt>:mailers</tt>.
467468
class Base < AbstractController::Base
468469
include DeliveryMethods
470+
include QueuedDelivery
469471
include Rescuable
470472
include Parameterized
471473
include Previews
@@ -487,7 +489,6 @@ class Base < AbstractController::Base
487489

488490
helper ActionMailer::MailHelper
489491

490-
class_attribute :delivery_job, default: ::ActionMailer::MailDeliveryJob
491492
class_attribute :default_params, default: {
492493
mime_version: "1.0",
493494
charset: "UTF-8",

actionmailer/lib/action_mailer/delivery_methods.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ module DeliveryMethods
1212
# Do not make this inheritable, because we always want it to propagate
1313
cattr_accessor :raise_delivery_errors, default: true
1414
cattr_accessor :perform_deliveries, default: true
15-
cattr_accessor :deliver_later_queue_name, default: :mailers
1615

1716
class_attribute :delivery_methods, default: {}.freeze
1817
class_attribute :delivery_method, default: :smtp

actionmailer/lib/action_mailer/mail_delivery_job.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ module ActionMailer
99
#
1010
# Exceptions are rescued and handled by the mailer class.
1111
class MailDeliveryJob < ActiveJob::Base # :nodoc:
12-
queue_as { ActionMailer::Base.deliver_later_queue_name }
12+
queue_as do
13+
mailer_class = arguments.first.constantize
14+
mailer_class.deliver_later_queue_name
15+
end
1316

1417
rescue_from StandardError, with: :handle_exception_with_mailer_class
1518

actionmailer/lib/action_mailer/message_delivery.rb

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,10 @@ def processed?
6262
# * <tt>:queue</tt> - Enqueue the email on the specified queue
6363
# * <tt>:priority</tt> - Enqueues the email with the specified priority
6464
#
65-
# By default, the email will be enqueued using <tt>ActionMailer::MailDeliveryJob</tt>. Each
66-
# ActionMailer::Base class can specify the job to use by setting the class variable
67-
# +delivery_job+.
65+
# By default, the email will be enqueued using <tt>ActionMailer::MailDeliveryJob</tt> on
66+
# the +:mailers+ queue. Mailer classes can customize the queue name used for the default
67+
# job by assigning a +deliver_later_queue_name+ class variable, or provide a custom job
68+
# by assigning a +delivery_job+. When a custom job is used, it controls the queue name.
6869
#
6970
# class AccountRegistrationMailer < ApplicationMailer
7071
# self.delivery_job = RegistrationDeliveryJob
@@ -88,9 +89,10 @@ def deliver_later!(options = {})
8889
# * <tt>:queue</tt> - Enqueue the email on the specified queue.
8990
# * <tt>:priority</tt> - Enqueues the email with the specified priority
9091
#
91-
# By default, the email will be enqueued using <tt>ActionMailer::MailDeliveryJob</tt>. Each
92-
# ActionMailer::Base class can specify the job to use by setting the class variable
93-
# +delivery_job+.
92+
# By default, the email will be enqueued using <tt>ActionMailer::MailDeliveryJob</tt> on
93+
# the +:mailers+ queue. Mailer classes can customize the queue name used for the default
94+
# job by assigning a +deliver_later_queue_name+ class variable, or provide a custom job
95+
# by assigning a +delivery_job+. When a custom job is used, it controls the queue name.
9496
#
9597
# class AccountRegistrationMailer < ApplicationMailer
9698
# self.delivery_job = RegistrationDeliveryJob
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# frozen_string_literal: true
2+
3+
module ActionMailer
4+
module QueuedDelivery
5+
extend ActiveSupport::Concern
6+
7+
included do
8+
class_attribute :delivery_job, default: ::ActionMailer::MailDeliveryJob
9+
class_attribute :deliver_later_queue_name, default: :mailers
10+
end
11+
end
12+
end

actionmailer/lib/action_mailer/test_helper.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,18 +170,22 @@ def assert_enqueued_emails(number, &block)
170170
# ContactMailer.with(email: '[email protected]').welcome.deliver_later
171171
# end
172172
# end
173-
def assert_enqueued_email_with(mailer, method, params: nil, args: nil, queue: ActionMailer::Base.deliver_later_queue_name || "default", &block)
173+
def assert_enqueued_email_with(mailer, method, params: nil, args: nil, queue: nil, &block)
174174
if mailer.is_a? ActionMailer::Parameterized::Mailer
175175
params = mailer.instance_variable_get(:@params)
176176
mailer = mailer.instance_variable_get(:@mailer)
177177
end
178+
179+
queue ||= mailer.deliver_later_queue_name || ActiveJob::Base.default_queue_name
180+
178181
args = if args.is_a?(Hash)
179182
[mailer.to_s, method.to_s, "deliver_now", params: args, args: []]
180183
elsif params.present?
181184
[mailer.to_s, method.to_s, "deliver_now", params: params, args: Array(args)]
182185
else
183186
[mailer.to_s, method.to_s, "deliver_now", args: Array(args)]
184187
end
188+
185189
assert_enqueued_with(job: mailer.delivery_job, args: args, queue: queue.to_s, &block)
186190
end
187191

actionmailer/test/mailers/delayed_mailer.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
class DelayedMailerError < StandardError; end
66

77
class DelayedMailer < ActionMailer::Base
8+
self.deliver_later_queue_name = :delayed_mailers
9+
810
cattr_accessor :last_error
911
cattr_accessor :last_rescue_from_instance
1012

actionmailer/test/message_delivery_test.rb

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ class MessageDeliveryTest < ActiveSupport::TestCase
1010
setup do
1111
@previous_logger = ActiveJob::Base.logger
1212
@previous_delivery_method = ActionMailer::Base.delivery_method
13-
@previous_deliver_later_queue_name = ActionMailer::Base.deliver_later_queue_name
14-
ActionMailer::Base.deliver_later_queue_name = :test_queue
15-
ActionMailer::Base.delivery_method = :test
13+
1614
ActiveJob::Base.logger = Logger.new(nil)
15+
ActionMailer::Base.delivery_method = :test
16+
1717
ActiveJob::Base.queue_adapter.perform_enqueued_at_jobs = true
1818
ActiveJob::Base.queue_adapter.perform_enqueued_jobs = true
1919

@@ -28,7 +28,6 @@ class MessageDeliveryTest < ActiveSupport::TestCase
2828

2929
ActiveJob::Base.logger = @previous_logger
3030
ActionMailer::Base.delivery_method = @previous_delivery_method
31-
ActionMailer::Base.deliver_later_queue_name = @previous_deliver_later_queue_name
3231

3332
DelayedMailer.last_error = nil
3433
DelayedMailer.last_rescue_from_instance = nil
@@ -75,33 +74,33 @@ def test_should_enqueue_and_run_correctly_in_activejob
7574
end
7675
end
7776

78-
test "should enqueue a delivery with a delay" do
77+
test "should enqueue delivery with a delay" do
7978
travel_to Time.new(2004, 11, 24, 1, 4, 44) do
8079
assert_performed_with(job: ActionMailer::MailDeliveryJob, at: Time.current + 10.minutes, args: ["DelayedMailer", "test_message", "deliver_now", args: [1, 2, 3]]) do
8180
@mail.deliver_later wait: 10.minutes
8281
end
8382
end
8483
end
8584

86-
test "should enqueue a delivery with a priority" do
85+
test "should enqueue delivery with a priority" do
8786
job = @mail.deliver_later priority: 10
8887
assert_equal 10, job.priority
8988
end
9089

91-
test "should enqueue a delivery at a specific time" do
90+
test "should enqueue delivery at a specific time" do
9291
later_time = Time.current + 1.hour
9392
assert_performed_with(job: ActionMailer::MailDeliveryJob, at: later_time, args: ["DelayedMailer", "test_message", "deliver_now", args: [1, 2, 3]]) do
9493
@mail.deliver_later wait_until: later_time
9594
end
9695
end
9796

98-
test "should enqueue the job on the correct queue" do
99-
assert_performed_with(job: ActionMailer::MailDeliveryJob, args: ["DelayedMailer", "test_message", "deliver_now", args: [1, 2, 3]], queue: "test_queue") do
97+
test "should enqueue delivery on the correct queue" do
98+
assert_performed_with(job: ActionMailer::MailDeliveryJob, args: ["DelayedMailer", "test_message", "deliver_now", args: [1, 2, 3]], queue: "delayed_mailers") do
10099
@mail.deliver_later
101100
end
102101
end
103102

104-
test "should enqueue the job with the correct delivery job" do
103+
test "should enqueue delivery with the correct job" do
105104
old_delivery_job = DelayedMailer.delivery_job
106105
DelayedMailer.delivery_job = DummyJob
107106

@@ -114,12 +113,26 @@ def test_should_enqueue_and_run_correctly_in_activejob
114113

115114
class DummyJob < ActionMailer::MailDeliveryJob; end
116115

117-
test "can override the queue when enqueuing mail" do
116+
test "delivery queue can be overridden when enqueuing mail" do
118117
assert_performed_with(job: ActionMailer::MailDeliveryJob, args: ["DelayedMailer", "test_message", "deliver_now", args: [1, 2, 3]], queue: "another_queue") do
119118
@mail.deliver_later(queue: :another_queue)
120119
end
121120
end
122121

122+
test "delivery queue can be overridden in subclasses" do
123+
previous_queue_name = DelayedMailer.deliver_later_queue_name
124+
DelayedMailer.deliver_later_queue_name = :throttled_mailers
125+
126+
assert_equal :throttled_mailers, DelayedMailer.deliver_later_queue_name
127+
assert_equal :mailers, ActionMailer::Base.deliver_later_queue_name
128+
129+
assert_performed_with(job: ActionMailer::MailDeliveryJob, args: ["DelayedMailer", "test_message", "deliver_now", args: []], queue: "throttled_mailers") do
130+
DelayedMailer.test_message.deliver_later
131+
end
132+
ensure
133+
DelayedMailer.deliver_later_queue_name = previous_queue_name
134+
end
135+
123136
test "deliver_later after accessing the message is disallowed" do
124137
@mail.message # Load the message, which calls the mailer method.
125138

0 commit comments

Comments
 (0)