# バッチ設計書 16-Event::WebhookDispatchJob

## 概要

本ドキュメントは、WebhookディスパッチジョブEvent::WebhookDispatchJob）の設計仕様を記載したものです。

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

Event::WebhookDispatchJobは、イベント発生時に登録されているWebhookに対してトリガーを発行する非同期ジョブです。ActiveJob::Continuableを使用した継続可能なジョブとして実装されています。

**業務上の目的・背景**：Fizzyで発生するカード関連のイベント（作成、アサイン、完了等）を外部システム（Slack、Basecamp、Campfire等）に通知するため、Webhookを介した連携が必要です。非同期で処理することで、ユーザー操作をブロックせずに複数のWebhookに効率的に通知を配信できます。

**バッチの実行タイミング**：イベント（Event）が作成された後、after_create_commitコールバックによりジョブがキューに投入されます。

**主要な処理内容**：
1. イベントを受け取り、該当するWebhookを検索
2. アクティブかつ該当イベントを購読しているWebhookを取得
3. 各Webhookに対してtriggerメソッドを呼び出し
4. Webhook::Deliveryレコードを作成し、実際の配信はDeliveryJobで実行

**前後の処理との関連**：Eventモデルの作成後に実行されます。このジョブがWebhook::Deliveryを作成し、その後Webhook::DeliveryJobが実際のHTTP配信を行います。

**影響範囲**：webhook_deliveriesテーブルへのレコード作成。

## バッチ種別

通知配信

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時（イベント駆動） |
| 実行時刻 | - |
| 実行曜日 | - |
| 実行日 | - |
| トリガー | Event作成後のafter_create_commitコールバック |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Eventレコードが存在 | 有効なイベントが作成されていること |
| アクティブなWebhookが存在 | active: trueのWebhookが設定されていること |
| Webhookがイベントを購読 | subscribed_actionsにイベントのactionが含まれること |

### 実行可否判定

Eventレコードがデシリアライズ可能な場合に実行。削除済みの場合はジョブを破棄。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| event | Event | Yes | - | Webhookをトリガーするイベント |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| events | DB | イベント情報 |
| webhooks | DB | Webhook設定情報 |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| webhook_deliveries | DB | 配信レコードの作成 |

### 出力ファイル仕様

ファイル出力なし

## 処理フロー

### 処理シーケンス

```
1. Eventオブジェクトを受け取り
   └─ ActiveJob::DeserializationErrorの場合はジョブを破棄
2. dispatchステップ開始
   └─ step :dispatchブロック内で処理
3. 対象Webhook取得
   └─ Webhook.active.triggered_by(event)で取得
4. 各Webhookをfind_eachでイテレート
   └─ step.cursorから再開可能
5. webhook.trigger(event)を実行
   └─ アカウントがキャンセル済みでない場合のみ
   └─ Webhook::Deliveryレコード作成
6. step.advance!で進捗を更新
   └─ webhook.idを記録
7. 全Webhook処理後、ジョブ終了
```

### フローチャート

```mermaid
flowchart TD
    A[ジョブ開始] --> B{デシリアライズ成功?}
    B -->|失敗| C[ジョブ破棄]
    B -->|成功| D[dispatchステップ開始]
    D --> E[Webhook.active.triggered_by取得]
    E --> F{対象Webhook存在?}
    F -->|なし| G[ジョブ終了]
    F -->|あり| H[find_eachでループ]
    H --> I{アカウントキャンセル済み?}
    I -->|はい| J[スキップ]
    I -->|いいえ| K[webhook.trigger実行]
    K --> L[Webhook::Delivery作成]
    L --> M[step.advance!で進捗更新]
    J --> M
    M --> N{次のWebhook?}
    N -->|あり| H
    N -->|なし| G
```

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

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

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| イベント取得 | events | SELECT | イベント情報取得 |
| Webhook取得 | webhooks | SELECT | アクティブなWebhook取得 |
| 配信レコード作成 | webhook_deliveries | INSERT | 配信情報の作成 |

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

#### webhooks

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | active = true AND board_id = event.board_id | triggered_byスコープ |
| SELECT | * | subscribed_actions LIKE '%"action"%' | triggered_by_actionスコープ |

#### webhook_deliveries

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | webhook_id | 対象WebhookのID | 外部キー |
| INSERT | event_id | トリガーイベントのID | 外部キー |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ActiveJob::DeserializationError | Eventレコードが削除済み | ジョブを破棄（discard_on） |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | デフォルト |
| リトライ間隔 | デフォルト |
| リトライ対象エラー | DeserializationError以外 |

### 障害時対応

- ActiveJob::Continuableにより、チェックポイントから再開可能
- DeserializationErrorの場合は自動的にジョブが破棄される

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | Webhook単位 |
| コミットタイミング | 各Delivery作成時 |
| ロールバック条件 | Delivery作成失敗時 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | イベントあたり数件のWebhook |
| 目標処理時間 | 数秒以内 |
| メモリ使用量上限 | find_eachでバッチ処理のため抑制 |

## 排他制御

同一Eventに対する複数ジョブ実行は想定しない。継続可能ジョブとして単一処理。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 開始ログ | ジョブ開始時 | Active Jobデフォルト |
| 進捗ログ | 各Webhook処理後 | 継続可能ジョブのチェックポイント |
| 終了ログ | ジョブ終了時 | Active Jobデフォルト |
| エラーログ | エラー発生時 | Active Jobデフォルト |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| キュー滞留 | 設定依存 | 運用チーム |

## 備考

- キューは`webhooks`を使用
- ActiveJob::Continuableで継続可能なジョブとして実装
- アカウントがキャンセル済みの場合はWebhookをトリガーしない
- 購読可能なアクション：card_assigned, card_closed, card_postponed, card_auto_postponed, card_board_changed, card_published, card_reopened, card_sent_back_to_triage, card_triaged, card_unassigned, comment_created
- 実際のHTTP配信はWebhook::DeliveryJobで実行される
- Slack、Basecamp Campfire、Campfireへの連携に対応
