# バッチ設計書 11-PushNotificationJob

## 概要

本ドキュメントは、プッシュ通知送信ジョブ（PushNotificationJob）の設計仕様を記載したものです。

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

PushNotificationJobは、ユーザーへのプッシュ通知をWebブラウザやモバイルデバイスに配信する非同期ジョブです。

**業務上の目的・背景**：ユーザーがアプリケーションを開いていない状態でも、カードのコメント、アサイン、メンションなどの重要なイベントをリアルタイムに知らせることで、チームのコラボレーションを促進し、対応の遅延を防止します。

**バッチの実行タイミング**：通知（Notification）のソースが変更されたタイミングで自動的にトリガーされます。PushNotifiable concernのafter_save_commitコールバックにより、source_idが変更されるとジョブがキューに投入されます。

**主要な処理内容**：
1. 通知オブジェクトを受け取り、NotificationPusherに処理を委譲
2. NotificationPusherがプッシュ条件（ユーザーのサブスクリプション有無、アクティブ状態等）を判定
3. 通知ソースの種別（Event/Mention等）に応じたペイロードを構築
4. Web Pushプールを通じてユーザーのデバイスに配信

**前後の処理との関連**：NotifyRecipientsJobが通知レコードを作成した後、その通知のsource_idが設定されることでこのジョブが起動します。

**影響範囲**：ユーザーのブラウザ/デバイスへのプッシュ通知配信。外部のWeb Push APIを利用します。

## バッチ種別

通知配信

## 実行スケジュール

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

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Notificationレコードが存在すること | source_idが設定済みの通知レコードが必要 |
| ユーザーがプッシュサブスクリプションを持つこと | push_subscriptionsが1件以上存在 |
| 通知作成者がシステムユーザーでないこと | creator.system?がfalse |
| ユーザーがアクティブであること | user.active?がtrue |
| アカウントがアクティブであること | account.active?がtrue |

### 実行可否判定

NotificationPusher#should_push?メソッドで以下の条件をすべて満たす場合のみプッシュを実行：
- ユーザーにプッシュサブスクリプションが存在
- 通知作成者がシステムユーザーでない
- ユーザーがアクティブ状態
- アカウントがアクティブ状態

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| notification | Notification | Yes | - | プッシュ対象の通知オブジェクト |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| notifications | DB | 通知情報 |
| push_subscriptions | DB | ユーザーのプッシュ購読情報 |
| events | DB | イベント情報（source_type="Event"の場合） |
| mentions | DB | メンション情報（source_type="Mention"の場合） |
| cards | DB | カード情報 |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| Web Push API | HTTP | ブラウザ/デバイスへのプッシュ通知 |

### 出力ファイル仕様

ファイル出力なし（Web Push APIへの配信のみ）

## 処理フロー

### 処理シーケンス

```
1. Notificationオブジェクトを受け取り
   └─ ActiveJob::DeserializationErrorの場合はジョブを破棄
2. NotificationPusher初期化
   └─ 通知オブジェクトをセット
3. プッシュ条件判定（should_push?）
   └─ 条件を満たさない場合は処理終了
4. ペイロード構築（build_payload）
   └─ source_typeに応じて異なるペイロードを生成
5. ユーザーのpush_subscriptionsを取得
   └─ 全サブスクリプションに対して配信
6. Web Pushプールにキューイング
   └─ 非同期でプッシュ配信
```

### フローチャート

```mermaid
flowchart TD
    A[ジョブ開始] --> B{デシリアライズ成功?}
    B -->|失敗| C[ジョブ破棄]
    B -->|成功| D[NotificationPusher初期化]
    D --> E{プッシュ条件判定}
    E -->|条件不満足| F[処理終了]
    E -->|条件満足| G{source_type判定}
    G -->|Event| H[Eventペイロード構築]
    G -->|Mention| I[Mentionペイロード構築]
    G -->|その他| J[デフォルトペイロード構築]
    H --> K[push_subscriptions取得]
    I --> K
    J --> K
    K --> L[Web Pushプールにキューイング]
    L --> M[ジョブ終了]
```

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

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

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 通知取得 | notifications | SELECT | 通知情報の取得 |
| ユーザー取得 | users | SELECT | 通知対象ユーザー情報取得 |
| サブスクリプション取得 | push_subscriptions | SELECT | プッシュ購読情報取得 |
| ソース取得 | events/mentions | SELECT | 通知ソース情報取得 |
| カード取得 | cards | SELECT | カード情報取得 |

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

#### notifications

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | id = 指定ID | ジョブパラメータ |

#### push_subscriptions

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | user_id = notification.user_id | 全サブスクリプション取得 |

## エラー処理

### エラーケース一覧

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

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | デフォルト（フレームワーク設定に依存） |
| リトライ間隔 | デフォルト |
| リトライ対象エラー | DeserializationError以外のエラー |

### 障害時対応

- DeserializationErrorの場合は自動的にジョブが破棄される
- その他のエラーはデフォルトのリトライ処理に従う
- Web Push配信の失敗はweb_push_poolで処理される

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

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

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 1通知/ジョブ |
| 目標処理時間 | 数秒以内 |
| メモリ使用量上限 | 特に制限なし |

## 排他制御

同一通知に対する同時実行の制御は特になし。Web Pushプールが配信を管理する。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 開始ログ | ジョブ開始時 | Active Jobデフォルト |
| 終了ログ | ジョブ終了時 | Active Jobデフォルト |
| エラーログ | エラー発生時 | Active Jobデフォルト |

## 監視・アラート

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

## 備考

- Web Push配信はRails.configuration.x.web_push_poolを利用
- ペイロードにはtitle、body、pathが含まれる
- イベントのアクション種別（comment_created、card_assigned等）に応じてペイロード内容が変わる
