# 通知設計書 10-DelayedMailer#test_message

## 概要

本ドキュメントは、Rails ActionMailerフレームワークにおけるDelayedMailer#test_messageメソッドによる遅延配信テストメール通知の設計を記述する。

### 本通知の処理概要

DelayedMailer#test_messageは、ActionMailerのdeliver_laterによる非同期メール配信機能を実証するためのテスト用メーラーメソッドである。Active Jobを使用してメール送信をキューイングし、バックグラウンドで配信を行う機能のテストに使用される。

**業務上の目的・背景**：リクエスト-レスポンスサイクル外でメールを送信することで、ユーザーの待ち時間を短縮し、アプリケーションのパフォーマンスを向上させる。大量のメール送信やレート制限のある外部サービスとの連携に適している。本実装はテスト用であり、deliver_later、カスタムキュー、遅延配信、エラーハンドリングなどの動作確認を主目的とする。

**通知の送信タイミング**：deliver_laterが呼び出された時点でActive Jobキューにエンキューされ、ジョブワーカーによって非同期に実行される。wait/wait_untilオプションで配信を遅延させることも可能。

**通知の受信者**：`test-receiver@test.com`宛に送信される。

**通知内容の概要**：件名「Test Subject」、本文「Test Body」のシンプルなテストメールが送信される。メソッドは可変長引数を受け取るが、メール内容には影響しない（テスト用途で引数の受け渡しを検証するため）。

**期待されるアクション**：テスト用途では、deliver_laterによるキューイング、カスタムキューの使用、遅延配信、rescue_fromによるエラーハンドリングが正しく動作することを確認する。

## 通知種別

メール

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（deliver_later）※同期も可能 |
| 優先度 | カスタマイズ可能（priorityオプション） |
| リトライ | ActiveJob設定に依存 |
| キュー名 | delayed_mailers（カスタム設定） |

### 送信先決定ロジック

メソッド内で固定値として`test-receiver@test.com`が指定されている。

## 通知テンプレート

### メール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | test-sender@test.com |
| 送信元名称 | （未設定） |
| 件名 | Test Subject |
| 形式 | text/plain |

### 本文テンプレート

```
Test Body
```

テンプレートファイル: なし（bodyオプションで直接指定）

### 添付ファイル

本メソッドでは添付ファイルは使用されない。

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| （なし） | bodyオプションで直接指定 | - | - |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| API呼び出し | `DelayedMailer.test_message.deliver_later` | なし（常にエンキュー） | 非同期配信テスト用 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| メッセージアクセス後のdeliver_later | RuntimeError発生（意図的な制限） |
| perform_deliveries = false | ActionMailerの設定で配信を無効化している場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[DelayedMailer.test_message 呼び出し] --> B[MessageDelivery オブジェクト生成]
    B --> C{deliver_later or deliver_now?}
    C -->|deliver_later| D[MailDeliveryJob エンキュー]
    C -->|deliver_now| E[即時配信処理]
    D --> F[Active Job キュー: delayed_mailers]
    F --> G[ジョブワーカーが実行]
    G --> H[メーラーインスタンス生成]
    H --> I[test_message メソッド実行]
    I --> J[mail 呼び出し]
    J --> K[deliver_now/deliver_now! 実行]
    K --> L{成功?}
    L -->|Yes| M[配信完了]
    L -->|No| N[rescue_from でエラー処理]
    E --> H
    N --> O[エラーハンドリング完了]
```

## データベース参照・更新仕様

### 参照テーブル一覧

本メソッドはデータベースを参照しない（テスト用メーラー）。

### 更新テーブル一覧

本メソッドはデータベースを更新しない。

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| DelayedMailerError | test_raiseアクションで発生 | rescue_fromで捕捉、last_errorに保存 |
| ActiveJob::DeserializationError | 引数のデシリアライズ失敗 | rescue_fromで捕捉 |
| RuntimeError | messageアクセス後にdeliver_later | 例外発生（意図的な制限） |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | ActiveJob設定に依存 |
| リトライ間隔 | ActiveJob設定に依存 |
| リトライ対象エラー | rescue_fromで捕捉されないエラー |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 設定なし（キューワーカーの設定に依存） |
| 1日あたり上限 | 設定なし |

### 配信時間帯

waitオプションまたはwait_untilオプションで遅延配信が可能。

## セキュリティ考慮事項

- テスト用メーラーのため、本番環境での使用は非推奨
- deliver_laterの引数はシリアライズされるため、大きなオブジェクトは避けるべき
- DeserializationErrorのハンドリングを適切に実装する必要がある

## 備考

- deliver_later_queue_nameで使用するキューをカスタマイズ可能（デフォルト: :delayed_mailers）
- delivery_jobでカスタムジョブクラスを指定可能
- deliver_laterのオプション: wait, wait_until, queue, priority
- messageにアクセス後はdeliver_laterが使用不可（引数のみがジョブに渡されるため）
- ActionMailer.deliver_all_laterで複数メールを一括エンキュー可能

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

非同期配信の仕組みとMailDeliveryJobを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | mail_delivery_job.rb | `actionmailer/lib/action_mailer/mail_delivery_job.rb` | L1-48: MailDeliveryJobクラス全体 |
| 1-2 | queued_delivery.rb | `actionmailer/lib/action_mailer/queued_delivery.rb` | L1-12: delivery_job, deliver_later_queue_nameの定義 |

**読解のコツ**: MailDeliveryJobはメーラークラス名、アクション名、配信メソッド、引数を受け取り、ジョブ実行時にメーラーを再構築して配信を行う。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | delayed_mailer.rb | `actionmailer/test/mailers/delayed_mailer.rb` | L1-32: DelayedMailerクラス全体 |

**主要処理フロー**:
1. **L6**: `self.deliver_later_queue_name = :delayed_mailers` - カスタムキュー名設定
2. **L8-9**: クラス変数（エラー追跡用）
3. **L11-19**: rescue_fromでDelayedMailerErrorとDeserializationErrorを捕捉
4. **L21-23**: test_messageメソッド - シンプルなメール生成（可変長引数）

#### Step 3: deliver_later処理フローを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | message_delivery.rb | `actionmailer/lib/action_mailer/message_delivery.rb` | L113-138: deliver_later/deliver_later!メソッド |
| 3-2 | message_delivery.rb | `actionmailer/lib/action_mailer/message_delivery.rb` | L174-188: enqueue_deliveryメソッド |

**主要処理フロー**:
- **L136-138**: `deliver_later` → `enqueue_delivery :deliver_now, options`
- **L175-183**: processedチェック - messageアクセス後はエラー
- **L185-186**: `@mailer_class.delivery_job.set(options).perform_later(...)` - ジョブエンキュー

#### Step 4: テストケースで動作を確認する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | message_delivery_test.rb | `actionmailer/test/message_delivery_test.rb` | L62-66: deliver_laterエンキューテスト |
| 4-2 | message_delivery_test.rb | `actionmailer/test/message_delivery_test.rb` | L74-80: 遅延配信テスト |
| 4-3 | message_delivery_test.rb | `actionmailer/test/message_delivery_test.rb` | L94-98: カスタムキューテスト |
| 4-4 | message_delivery_test.rb | `actionmailer/test/message_delivery_test.rb` | L133-139: messageアクセス後の制限テスト |
| 4-5 | message_delivery_test.rb | `actionmailer/test/message_delivery_test.rb` | L220-232: エラーハンドリングテスト |

**主要処理フロー**:
- **L63-65**: MailDeliveryJobが正しい引数でエンキューされることを検証
- **L76-78**: waitオプションで遅延エンキューを検証
- **L95-97**: キュー名"delayed_mailers"でエンキューされることを検証
- **L134-138**: messageアクセス後のdeliver_laterがRuntimeErrorになることを検証
- **L228-231**: rescue_fromでエラーが捕捉されることを検証

### プログラム呼び出し階層図

```
DelayedMailer.test_message(*args).deliver_later(options)
    │
    ├─ MessageDelivery.new(DelayedMailer, :test_message, *args)
    │
    └─ MessageDelivery#deliver_later(options)
           │
           ├─ processed? チェック
           │      └─ true の場合 RuntimeError
           │
           └─ enqueue_delivery(:deliver_now, options)
                  │
                  └─ @mailer_class.delivery_job
                         .set(options)
                         .perform_later(
                             "DelayedMailer",
                             "test_message",
                             "deliver_now",
                             args: @args
                         )
                               │
                               ▼
                         [Active Job キュー: delayed_mailers]
                               │
                               ▼
                         MailDeliveryJob#perform
                               │
                               ├─ mailer.constantize
                               │      └─ DelayedMailer
                               │
                               ├─ DelayedMailer.test_message(*args)
                               │      └─ MessageDelivery生成
                               │
                               └─ message.deliver_now
                                      └─ 同期配信処理
```

### データフロー図

```
[入力]                           [処理]                              [出力]

メーラー呼び出し             ───▶ MessageDelivery 生成           ───▶ MessageDelivery
  DelayedMailer.test_message(1,2,3)   │                                (未処理)
                                       │
                                       ▼
deliver_later(wait: 10.min)    ───▶ enqueue_delivery
                                       │
                                       ├─ processed? = false
                                       │
                                       └─ MailDeliveryJob.perform_later
                                              │
                                              ▼
                                       [Active Job Queue]          ───▶ ジョブエンキュー完了
                                       queue: delayed_mailers
                                       args: ["DelayedMailer",
                                              "test_message",
                                              "deliver_now",
                                              args: [1,2,3]]
                                              │
                                              ▼
                               (ワーカー実行時)
                                              │
MailDeliveryJob#perform        ───▶ DelayedMailer.test_message(1,2,3)
                                       │
                                       └─ .deliver_now
                                              │
                                              ▼
                               ───▶ mail() で Mail::Message 生成 ───▶ 配信完了
                                       │
                                       └─ message.deliver
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| delayed_mailer.rb | `actionmailer/test/mailers/delayed_mailer.rb` | ソース | 遅延配信テスト用メーラー |
| message_delivery.rb | `actionmailer/lib/action_mailer/message_delivery.rb` | ソース | deliver_later実装 |
| mail_delivery_job.rb | `actionmailer/lib/action_mailer/mail_delivery_job.rb` | ソース | Active Job実装 |
| queued_delivery.rb | `actionmailer/lib/action_mailer/queued_delivery.rb` | ソース | キュー設定 |
| message_delivery_test.rb | `actionmailer/test/message_delivery_test.rb` | テスト | 遅延配信機能テスト |
