# バッチ設計書 3-Inboxes::FetchImapEmailInboxesJob

## 概要

本ドキュメントは、Chatwootアプリケーションにおける`Inboxes::FetchImapEmailInboxesJob`バッチの設計仕様を記載したものである。

### 本バッチの処理概要

このバッチは、IMAP有効なメールインボックスを検索し、各インボックスに対してメール取得ジョブ（FetchImapEmailsJob）をキューイングする親ジョブである。

**業務上の目的・背景**：Chatwootでは、顧客からのメールを会話として取り込むためにIMAPプロトコルを使用したメール取得機能を提供している。このバッチは、IMAP設定が有効化されたすべてのメールチャネルを定期的にスキャンし、実際のメール取得処理を行う子ジョブを適切にスケジュールすることで、メール取り込み機能の中央スケジューラーとして機能する。

**バッチの実行タイミング**：毎分実行される（*/1 * * * *）。これにより、新着メールをほぼリアルタイムで取り込むことが可能となる。

**主要な処理内容**：
1. Channel::Email型のすべてのインボックスを検索
2. 各インボックスに対してメール取得条件を判定
3. 条件を満たすインボックスに対してFetchImapEmailsJobをキューイング

**前後の処理との関連**：本バッチは親ジョブとして機能し、Inboxes::FetchImapEmailsJobを子ジョブとしてトリガーする。FetchImapEmailsJobが実際のIMAPサーバーへの接続とメール取得を行う。

**影響範囲**：直接的なデータ変更は行わない。子ジョブ（FetchImapEmailsJob）をキューイングするのみ。

## バッチ種別

メール取込 / ジョブスケジューリング

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 毎分 |
| 実行時刻 | 毎分0秒 |
| 実行曜日 | 毎日 |
| 実行日 | - |
| トリガー | cron（sidekiq-cron） |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| なし | 特別な前提条件なく常に実行される |

### 実行可否判定

ジョブ自体は常に実行される。各インボックスに対するメール取得ジョブのキューイング条件は以下：
- アカウントが停止されていないこと（`account.suspended?`がfalse）
- チャネルでIMAPが有効化されていること（`channel.imap_enabled`がtrue）
- 再認証が不要であること（`channel.reauthorization_required?`がfalse）
- Chatwoot Cloud環境の場合、デフォルトプラン以外であること

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| なし | - | - | - | 本バッチは引数を取らない |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| inboxes | DB | channel_type = 'Channel::Email'のインボックス一覧 |
| accounts | DB | アカウントの停止状態確認 |
| channel_email | DB | IMAP有効化状態、再認証要否の確認 |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| Sidekiqキュー | ジョブ | FetchImapEmailsJobをキューイング |

### 出力ファイル仕様

ファイル出力なし

## 処理フロー

### 処理シーケンス

```
1. メールインボックスの検索
   └─ Inbox.where(channel_type: 'Channel::Email')で対象インボックス取得
   └─ batch_size: 100で分割処理
2. 各インボックスの条件判定
   └─ should_fetch_emails?メソッドで判定
   └─ アカウント停止チェック
   └─ IMAP有効化チェック
   └─ 再認証不要チェック
   └─ Chatwoot Cloud時のプランチェック
3. 子ジョブのキューイング
   └─ 条件を満たすインボックスに対してFetchImapEmailsJob.perform_later
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[メールインボックス検索]
    B --> C[各インボックスをループ処理]
    C --> D{アカウント停止?}
    D -->|Yes| E[スキップ]
    D -->|No| F{IMAP有効?}
    F -->|No| E
    F -->|Yes| G{再認証必要?}
    G -->|Yes| E
    G -->|No| H{Chatwoot Cloud?}
    H -->|No| I[FetchImapEmailsJobをキューイング]
    H -->|Yes| J{デフォルトプラン?}
    J -->|Yes| E
    J -->|No| I
    E --> K{次のインボックスあり?}
    I --> K
    K -->|Yes| C
    K -->|No| L[バッチ終了]
```

## データベース操作仕様

### 操作別データベース影響一覧

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| インボックス検索 | inboxes | SELECT | channel_type = 'Channel::Email'のレコード取得 |
| アカウント状態確認 | accounts | SELECT | suspended状態の確認 |
| チャネル状態確認 | channel_email | SELECT | imap_enabled、reauthorization_required状態の確認 |

### テーブル別操作詳細

#### inboxes

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, channel_type, channel_id, account_id | channel_type = 'Channel::Email' | batch_size: 100で分割取得 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | StandardError | 予期しないエラー | Sidekiqのリトライ機構に委譲 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | Sidekiqのデフォルト設定に依存 |
| リトライ間隔 | Sidekiqのデフォルト設定に依存 |
| リトライ対象エラー | ジョブ実行時の例外全般 |

### 障害時対応

本ジョブが失敗した場合、次回の定期実行（1分後）で再度処理される。

## トランザクション仕様

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | なし（読み取りとジョブキューイングのみ） |
| コミットタイミング | - |
| ロールバック条件 | - |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | メールインボックス数に依存 |
| 目標処理時間 | 数秒〜数十秒 |
| メモリ使用量上限 | 最小限（find_eachで分割処理） |

## 排他制御

同時実行の制御は特になし。毎分実行のため、前回実行中に次回実行が開始される可能性がある。ただし、子ジョブ（FetchImapEmailsJob）側でインボックス単位のミューテックスロックを取得するため、同一インボックスの重複処理は防止される。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| - | - | 本ジョブ自体はログ出力を行わない |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| ジョブ失敗 | 連続失敗 | Sidekiq監視 |
| メール取込遅延 | 設定による | 運用監視（任意） |

## 備考

- BillingHelperをincludeしており、Chatwoot Cloud環境でのプラン判定に使用される
- Chatwoot Cloud環境では、デフォルトプランのアカウントはIMAPメール取得がスキップされる（有料機能の可能性）
- batch_size: 100で分割処理されるため、大量のメールインボックスがある場合でもメモリ効率的に処理される
