# バッチ設計書 20-Channels::Whatsapp::TemplatesSyncJob

## 概要

本ドキュメントは、Chatwootシステムにおける個別 WhatsApp チャネルのメッセージテンプレート同期処理を実行するバッチ処理の設計を記述するものです。

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

本バッチは、指定された WhatsApp チャネルのメッセージテンプレートを外部 WhatsApp API から取得し、Chatwootのデータベースに同期する処理を実行します。

**業務上の目的・背景**：WhatsApp Business APIを使用したメッセージ送信では、Meta（旧Facebook）に事前に承認されたメッセージテンプレートを使用する必要があります。これらのテンプレートは WhatsApp Business Manager で管理されており、テンプレートの追加・変更・削除が行われることがあります。本バッチにより、WhatsApp側のテンプレート情報をChatwootに同期することで、エージェントが常に最新のテンプレートを使用してメッセージを送信できるようにします。

**バッチの実行タイミング**：TemplatesSyncSchedulerJobからキューイングされます（5分毎のスケジュール実行で対象チャネルが検出された場合）。

**主要な処理内容**：
1. 指定されたWhatsAppチャネルのsync_templatesメソッドを呼び出し
2. プロバイダー（WhatsApp Cloud / 360Dialog）に応じたAPI呼び出し
3. メッセージテンプレートリストを取得
4. チャネルのmessage_templatesとmessage_templates_last_updatedを更新

**前後の処理との関連**：本バッチはTemplatesSyncSchedulerJob（親ジョブ）からキューイングされる子ジョブです。また、WhatsAppチャネル作成時（after_create）にも直接呼び出されます。

**影響範囲**：指定されたWhatsAppチャネルのmessage_templatesとmessage_templates_last_updatedカラムが更新されます。

## バッチ種別

データ同期 / 外部API連携

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時（親ジョブまたはチャネル作成時にトリガー） |
| 実行時刻 | 不定 |
| 実行曜日 | 毎日 |
| 実行日 | 毎日 |
| トリガー | TemplatesSyncSchedulerJob / チャネル作成時 |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| WhatsAppチャネルが存在すること | 指定されたチャネルがDBに存在する必要がある |
| プロバイダー設定が有効であること | API認証情報が正しく設定されている必要がある |
| 外部APIに接続可能であること | WhatsApp Cloud API / 360Dialog APIへのネットワーク接続が必要 |

### 実行可否判定

本バッチは無条件で実行されます。API呼び出しが失敗した場合でも、message_templates_last_updatedは更新されます（再試行の防止）。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| whatsapp_channel | Channel::Whatsapp | Yes | - | 処理対象のWhatsAppチャネルオブジェクト |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| channel_whatsapp | DB | WhatsAppチャネル設定（provider, provider_config） |
| WhatsApp Cloud API / 360Dialog API | 外部API | メッセージテンプレートリスト |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| channel_whatsapp | DB | message_templates, message_templates_last_updatedが更新される |

### 出力ファイル仕様

ファイル出力はありません。

## 処理フロー

### 処理シーケンス

```
1. バッチ開始
   └─ lowキューから起動
2. チャネルのsync_templatesメソッド呼び出し
   └─ delegate to provider_service
3. message_templates_last_updatedを更新（処理開始マーク）
   └─ mark_message_templates_updated
4. プロバイダーに応じたAPI呼び出し
   └─ WhatsApp Cloud: business_account_path/message_templates
   └─ 360Dialog: api_base_path/configs/templates
5. テンプレートリストを取得
   └─ ページネーション対応（WhatsApp Cloud）
6. チャネルレコードを更新
   └─ message_templates, message_templates_last_updated
7. バッチ終了
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[sync_templates呼び出し]
    B --> C[mark_message_templates_updated]
    C --> D{プロバイダー判定}
    D -->|WhatsApp Cloud| E[Cloud API呼び出し]
    D -->|360Dialog| F[360Dialog API呼び出し]
    E --> G{ページネーションあり?}
    G -->|Yes| H[次ページ取得]
    H --> G
    G -->|No| I[テンプレート結合]
    F --> J[waba_templates取得]
    I --> K[チャネル更新]
    J --> K
    K --> L[バッチ終了]
```

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

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

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 更新マーク | channel_whatsapp | UPDATE | message_templates_last_updatedを更新 |
| テンプレート同期 | channel_whatsapp | UPDATE | message_templates, message_templates_last_updatedを更新 |

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

#### channel_whatsapp

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | message_templates_last_updated | Time.zone.now | mark_message_templates_updated（処理開始時） |
| UPDATE | message_templates | APIから取得したテンプレート配列 | JSON形式 |
| UPDATE | message_templates_last_updated | Time.now.utc | 処理完了時 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | HTTParty::Error | API接続失敗時 | message_templates_last_updatedは更新済みのため次回実行まで待機 |
| - | StandardError | 処理失敗時 | Sidekiqの標準リトライ機構により再実行 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | Sidekiqのデフォルト設定 |
| リトライ間隔 | 指数バックオフ |
| リトライ対象エラー | StandardError全般 |

### 障害時対応

API呼び出し失敗時でもmessage_templates_last_updatedは更新されるため、同一チャネルへの過剰なAPI呼び出しは防止されます。緊急時はRailsコンソールから手動実行可能です：
```ruby
Channels::Whatsapp::TemplatesSyncJob.perform_now(Channel::Whatsapp.find(1))
```

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | 各update操作は個別トランザクション |
| コミットタイミング | 各update完了時 |
| ロールバック条件 | 個別update操作の失敗時 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 1チャネルあたり1回 |
| 目標処理時間 | 数秒〜数十秒（API応答時間依存） |
| メモリ使用量上限 | テンプレート数に依存 |

## 排他制御

- 同一チャネルでの重複実行が発生する可能性あり
- 外部API呼び出しは冪等であるため、重複実行の影響は軽微
- message_templates_last_updatedの更新により、短期間での重複呼び出しは防止

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 開始ログ | バッチ開始時 | Sidekiq標準ログ |
| 進捗ログ | - | 明示的なログ出力なし |
| 終了ログ | バッチ終了時 | Sidekiq標準ログ |
| エラーログ | エラー発生時 | Sidekiq標準エラーログ / [WHATSAPP] Webhook setup failed |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| 処理時間 | 1分以上 | Sidekiq監視システム |
| エラー件数 | 1件以上 | Sidekiq監視システム |
| API応答エラー | 連続失敗 | 運用チーム |

## 備考

- プロバイダー種別：
  - `whatsapp_cloud`: Meta WhatsApp Cloud API
  - `default`: 360Dialog API
- sync_templatesはChannel::Whatsappモデルからprovider_serviceにdelegateされる
- WhatsApp Cloud APIではページネーション対応が必要（fetch_whatsapp_templates再帰呼び出し）
- 360Dialog APIではwaba_templatesキーからテンプレートを取得
- mark_message_templates_updatedはupdate_columnを使用（バリデーションスキップ）
- テンプレートはJSON配列としてmessage_templatesカラムに保存される
- チャネル作成時（after_create）にも自動的に呼び出される
