# 通知設計書 127-project_or_group_emails

## 概要

本ドキュメントは、GitLabにおける「通知レート制限通知」メールの設計を記載します。プロジェクトまたはグループからの通知がレート制限によって一時停止された場合に、ユーザーに通知されるメールです。

### 本通知の処理概要

本通知は、GitLabの通知機能でレート制限が適用され、特定のプロジェクトまたはグループからの通知が一時的に停止された場合に、影響を受けるユーザーに警告を送信する機能です。

**業務上の目的・背景**：GitLabは大量の通知メールを生成する可能性があり、スパム防止やメールサーバーの負荷軽減のためにレート制限が設けられています。例えば、大量のIssueが一度に作成されたり、大量のMerge Requestが更新された場合、通知数が急増します。本通知は、ユーザーに「通知が一時停止されていること」を知らせ、通知設定の見直しを促すことで、重要な通知を見逃さないようにします。

**通知の送信タイミング**：Notifyメーラーの`check_rate_limit`アクションで、レート制限が初めて適用された際（まだ通知を受け取っていない場合）に非同期で送信されます。

**通知の受信者**：レート制限の対象となったユーザーの、該当プロジェクト/グループに設定された通知用メールアドレスに送信されます。

**通知内容の概要**：通知がレート制限により一時停止されていること、および通知設定の見直しを促すメッセージが含まれます。

**期待されるアクション**：受信者は、通知設定を見直し、必要に応じて通知の対象を絞り込むか、不要な通知を無効化することで、重要な通知を確実に受け取れるようにします。

## 通知種別

メール（Email）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（`deliver_later`） |
| 優先度 | 中 |
| リトライ | Sidekiqのデフォルトリトライに依存 |

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

`@recipient.notification_email_for(rate_limit_scope)`により、対象プロジェクト/グループに設定されたユーザーの通知用メールアドレスに送信されます。

## 通知テンプレート

### メール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | `Gitlab.config.gitlab.email_from` |
| 送信元名称 | `Gitlab.config.gitlab.email_display_name` |
| 件名 | `{プロジェクト/グループ名} \| Notifications temporarily disabled` |
| 形式 | HTML/テキスト（マルチパート） |

### 本文テンプレート

**HTML版:**
```html
<p>Notifications for {プロジェクト/グループ名} are rate-limited due to the high volume of notifications sent.</p>
<p>To avoid future interruption to notifications for {プロジェクト/グループ名}, update your notification preferences.</p>
```

**テキスト版:**
```
Notifications for {プロジェクト/グループ名} are rate-limited due to the high volume of notifications sent.

To avoid future interruption to notifications for {プロジェクト/グループ名}, update your notification preferences.
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | - | 本通知には添付ファイルはありません |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| @project_or_group | レート制限対象のプロジェクトまたはグループ | Project/Groupモデル | Yes |
| @project_or_group.name | プロジェクト/グループ名 | projects.name/namespaces.name | Yes |
| @project_or_group.full_name | プロジェクト/グループのフルパス | 計算値 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| after_actionコールバック | Notify#check_rate_limit | throttled?がtrueかつalready_notifiedがfalse | 通知レート制限が初めて適用された |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| rate_limit_scopeがnil | プロジェクト/グループが特定できない場合 |
| @recipientがnil | 受信者が特定できない場合 |
| already_notified | 既にレート制限通知を送信済みの場合 |
| throttled?がfalse | レート制限が適用されていない場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[Notify メーラーでメール送信試行] --> B[after_action: check_rate_limit]
    B --> C{rate_limit_scope存在?}
    C -->|No| D[処理終了]
    C -->|Yes| E{@recipient存在?}
    E -->|No| F[処理終了]
    E -->|Yes| G{既に通知済み? peek: true}
    G --> H{throttled?}
    H -->|No| I[処理終了]
    H -->|Yes| J[message.perform_deliveries = false で元通知停止]
    J --> K{already_notified?}
    K -->|Yes| L[処理終了]
    K -->|No| M[ログ記録]
    M --> N[RateLimiterMailer.project_or_group_emails.deliver_later]
    N --> O[終了]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| projects | プロジェクト情報 | name, full_name |
| namespaces | グループ情報 | name, full_name |
| users | ユーザー情報 | notification_email |
| notification_settings | 通知設定 | notification_email_for |

### テーブル別参照項目詳細

#### projects / namespaces

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| name | 件名・本文に表示 | レート制限対象 |
| full_name | 本文に表示 | レート制限対象 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| なし | - | メール送信のみで、DB更新は行わない |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 送信失敗 | SMTPサーバー接続エラー | Sidekiqリトライに依存 |
| 通知メールアドレス未設定 | ユーザーの通知メール設定がない | デフォルトメールアドレスにフォールバック |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | Sidekiqデフォルト（25回） |
| リトライ間隔 | 指数バックオフ |
| リトライ対象エラー | 一時的なネットワークエラー、SMTP接続エラー |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし（本通知自体にはレート制限なし） |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（レート制限適用時に即座にキューイング）

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

- プロジェクト/グループ名が含まれるため、機密性の高いプロジェクト名の漏洩に注意
- ユーザーの通知設定に基づいたメールアドレスに送信される
- レート制限の適用状況はログに記録される

## 備考

- レート制限は`Gitlab::ApplicationRateLimiter`を使用して管理される
- 件名は国際化対応（`_('Notifications temporarily disabled')`）
- `peek: true`オプションにより、レート制限カウンターを増加させずに状態を確認できる
- 元の通知は`message.perform_deliveries = false`で送信が停止される

---

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

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

### 推奨読解順序

#### Step 1: トリガーの実装を理解する

通知のトリガーとなるNotifyメーラーのレート制限チェックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | notify.rb | `app/mailers/notify.rb` | `check_rate_limit`メソッド、`throttled?`メソッド |

**主要処理フロー**:
1. **行45**: `after_action :check_rate_limit`でコールバック設定
2. **行283-305**: `check_rate_limit`メソッドの実装
3. **行286**: `already_notified = throttled?(peek: true)`で事前確認
4. **行288**: `throttled?`で制限適用判定
5. **行290**: `message.perform_deliveries = false`で元通知停止
6. **行292**: `already_notified`チェックで重複送信防止
7. **行301-304**: `RateLimiterMailer.project_or_group_emails.deliver_later`で送信

#### Step 2: メーラーの実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | rate_limiter_mailer.rb | `app/mailers/namespaces/rate_limiter_mailer.rb` | `project_or_group_emails`メソッド |

**主要処理フロー**:
1. **行9-18**: `project_or_group_emails`メソッドの定義
2. **行10**: `@project_or_group`インスタンス変数設定
3. **行12-15**: ヘッダー設定（to, subject）
4. **行17**: `mail_with_locale`でメール送信

#### Step 3: テンプレートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | project_or_group_emails.html.haml | `app/views/namespaces/rate_limiter_mailer/project_or_group_emails.html.haml` | HTML版 |
| 3-2 | project_or_group_emails.text.erb | `app/views/namespaces/rate_limiter_mailer/project_or_group_emails.text.erb` | テキスト版 |

**主要処理フロー（HTML版）**:
- **行1-2**: レート制限メッセージ
- **行4-5**: 通知設定見直しの案内

#### Step 4: テストから仕様を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | rate_limiter_mailer_spec.rb | `spec/mailers/namespaces/rate_limiter_mailer_spec.rb` | テストケース |

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

```
Notify (メーラー)
    │
    └─ after_action :check_rate_limit
           │
           ├─ rate_limit_scope（@project || @group）
           │
           ├─ throttled?(peek: true) で事前確認
           │
           ├─ throttled? でレート制限判定
           │      └─ Gitlab::ApplicationRateLimiter.throttled?
           │
           ├─ message.perform_deliveries = false
           │
           └─ Namespaces::RateLimiterMailer
                  .project_or_group_emails(rate_limit_scope, email)
                  .deliver_later
                         │
                         └─ mail_with_locale
                                └─ テンプレートレンダリング
                                       ├─ project_or_group_emails.html.haml
                                       └─ project_or_group_emails.text.erb
```

### データフロー図

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

Notifyメーラー
(通知送信試行)   ───▶  after_action: check_rate_limit
                              │
                              ▼
                        throttled?(peek: true)
                        (事前確認)
                              │
                              ▼
                        throttled?
                        (レート制限判定)
                              │
                              ▼
                        元通知の停止
                        (perform_deliveries = false)
                              │
                              ▼
                        RateLimiterMailer
                        .project_or_group_emails
                        .deliver_later    ───▶  Sidekiqキュー
                                                    │
                                                    ▼
                                               メール送信
                                               (影響ユーザー)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| notify.rb | `app/mailers/notify.rb` | ソース | Notifyメーラー（レート制限トリガー） |
| rate_limiter_mailer.rb | `app/mailers/namespaces/rate_limiter_mailer.rb` | ソース | RateLimiterメーラー |
| project_or_group_emails.html.haml | `app/views/namespaces/rate_limiter_mailer/project_or_group_emails.html.haml` | テンプレート | HTML版 |
| project_or_group_emails.text.erb | `app/views/namespaces/rate_limiter_mailer/project_or_group_emails.text.erb` | テンプレート | テキスト版 |
| rate_limiter_mailer_spec.rb | `spec/mailers/namespaces/rate_limiter_mailer_spec.rb` | テスト | メーラーのテスト |
| application_rate_limiter.rb | `lib/gitlab/application_rate_limiter.rb` | ソース | レート制限ロジック |
