Action Mailerを利用したメールJobがエンキューされるまでの流れ
初めに
ポート株式会社 サービス開発部 Advent Calendar 2023 17日目の記事です。
ポート株式会社サービス開発部に所属している原です。業務では、Railsを用いてバックエンド開発を行なっています。
調査動機
業務でメール送信周りでバグが起こり、Action Mailerでのメール送信周りの処理が気になったので、今回コードリーディングをしてみました。
Railsでメール送信する場合の流れ
Railsはメール送信する場合は、Action Mailerを利用します。また、非同期でメールを送信する場合は、Active Jobも利用されるので今回は、Action MailerとActive Jobそれぞれコードリーディングしていこうと思います。
Action Mailerとは?
基本的な使い方は下記Railsガイドを参照してください。
Active Jobとは?
基本的な使い方は下記Railsガイドを参照してください。
コードリーディング編
Action Mailer部分
自分が普段開発しているプロダクトのRailsのバージョンが7.0.8なので、同様のバージョンをコードリーディングしていこうと思います。また、実際のプロジェクトのメイラー名などは使用せず、RailsガイドからMailer名やメソッド名などを拝借させていただいています。
UserMailerMailer.welcome_email.deliver_later
上記のようにメール送信処理を行なったときは、まず下記部分が呼ばれます。
早速エンキューしようとしてますね。UserMailerMailer.welcome_email.deliver_later(wait: 1.minute)
などを渡した場合は変数optionsに{:wait=>1 minute}
が入るようです。
正常にメールが送信される場合は、下記のelse句の内容が呼ばれます。@mailer_class.delivery_job
はActionMailer::MailDeliveryJob
のようでした。このJobに対して、mailerのクラスやアクション、mailerに渡した引数などを渡しています。
下記から#perform_later
以降の処理はActive Jobを読みにいく必要があることはわかったのですが、一旦ActionMailer::MailDeliveryJob
内のコードを読みにいきます。
@mailer_class.delivery_job.set(options).method(:perform_later).source_location
=> ["/app/rails/activejob/lib/active_job/configured_job.rb", 14]
ActionMailer::MailDeliveryJob
のコードは下記になります。
ActionMailer::MailDeliveryJob
は、ActiveJob::Base
を継承して作成されたJobになってますね。
Active Job部分
今度はActive Jobの中を見にいきます。上述したようにメールを非同期で送信するようにした場合は、下記コードが参照されます。
実際のエンキューの処理は下記で行われてます。
開発しているプロジェクトではActive JobのアダプタはSidekiqが使用されていますので、下記部分でActiveJob::QueueAdapters::SidekiqAdapter
内の#enqueue
が呼ばれます。
ActiveJob::QueueAdapters::SidekiqAdapter#enqueue
では、Sidekiq::Client
がpushしてますね。
ここからredisなどにエンキューする処理を見にいくには、Sidekiq内のコードを見にいく必要がありますが、そこはまた次回にしようと思います!
終わりに
今回Rails内のコードを読んでみて、普段何気なく使用している機能が裏でどのように動いているか知ることができました。
これからもRailsなどのOSSのコードは積極的に読んで行くようにしたいです。
Discussion