# 通知設計書 78-inactive_project_deletion_warning_email

## 概要

本ドキュメントは、非アクティブなプロジェクトが削除予定であることを警告するメール通知 `inactive_project_deletion_warning_email` の設計仕様を定義する。

### 本通知の処理概要

本通知は、一定期間アクティビティがないプロジェクトが自動削除の対象となった場合に、プロジェクトのオーナーおよびメンテナーに警告メールを送信する機能を提供する。

**業務上の目的・背景**：GitLabインスタンスの管理者は、ストレージ容量の管理やリソースの最適化のために、非アクティブなプロジェクトを自動削除する設定を有効にすることができる。この自動削除は、意図せずに重要なプロジェクトが削除されるリスクを伴うため、削除予定日の前に関係者に警告を送ることで、必要に応じてプロジェクトに対してアクティビティを行い、削除を回避する機会を提供する。

**通知の送信タイミング**：定期的に実行されるバックグラウンドジョブ（`InactiveProjectsDeletionNotificationWorker`）により、削除予定日が近づいたプロジェクトに対して送信される。

**通知の受信者**：プロジェクトのオーナーおよびメンテナー全員に送信される。招待中のメンバーは除外される。

**通知内容の概要**：プロジェクト名、削除予定日、削除を回避するためのアクションの例、アクティビティの確認方法を含む詳細な警告メールである。

**期待されるアクション**：受信者はプロジェクトが必要かどうかを判断し、必要な場合はIssue作成、Merge Request作成、コードプッシュ、ユーザー追加/削除などのアクティビティを行って削除を回避する。

## 通知種別

メール通知

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（deliver_later） |
| 優先度 | 高（削除警告のため） |
| リトライ | Sidekiqのデフォルトリトライ機構に従う（3回） |

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

プロジェクトのオーナーおよびメンテナー（招待中を除く）全員の通知用メールアドレスに送信される。メールアドレスは `user.notification_email_for(project.group)` メソッドで決定される。

## 通知テンプレート

### メール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | GitLabのデフォルト送信元アドレス |
| 送信元名称 | GitLab |
| 件名 | `[Project Name] Action required: Project {project_name} is scheduled to be deleted on {deletion_date} due to inactivity` |
| 形式 | HTML/テキスト |

### 本文テンプレート

```html
<p>
  Hi {username},
</p>

<p>
  Due to inactivity, the <a href="{project_url}">{project_name}</a> project is scheduled to be deleted on <b>{deletion_date}</b>. To unschedule the deletion of {project_name}, perform some activity on it. For example:
</p>

<ul>
  <li>Create or close an issue.</li>
  <li>Create, update, or delete a merge request.</li>
  <li>Push code to the repository.</li>
  <li>Add or remove a user.</li>
</ul>

<p>
  To ensure {project_name} is unscheduled for deletion, check that activity has been logged by GitLab. For example:
</p>

<ul>
  <li>Go to the <b>Activity</b> page for {project_name}.</li>
  <li>View the <code>last_activity_at</code> attribute for {project_name} using the Projects API.</li>
  <li>List the visible events for {project_name} using the Events API.</li>
</ul>

<p>
  This email supersedes any previous emails about scheduled deletion you may have received for {project_name}.
</p>
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| なし | - | - | 添付ファイルなし |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| @project | 対象プロジェクト | パラメータから取得 | Yes |
| @user | 受信者ユーザー | パラメータから取得 | Yes |
| @deletion_date | 削除予定日 | パラメータから取得 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| スケジュール | InactiveProjectsDeletionNotificationWorker | 削除予定日が近づいた場合 | Cronjobで定期実行 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 既に通知済み | DormantProjectsDeletionWarningTrackerで通知済みの場合はスキップ |
| プロジェクト不存在 | プロジェクトが既に削除されている場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[Cronjobによるワーカー起動] --> B{既に通知済み?}
    B -->|Yes| C[終了]
    B -->|No| D[プロジェクト取得]
    D --> E{プロジェクト存在?}
    E -->|No| F[エラーログ記録して終了]
    E -->|Yes| G[NotificationService.inactive_project_deletion_warning呼び出し]
    G --> H[オーナー・メンテナー取得]
    H --> I[各ユーザーにメール送信]
    I --> J[通知済みとしてマーク]
    J --> K[終了]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| projects | プロジェクト情報取得 | 名前、URL |
| users | ユーザー情報取得 | 通知先メールアドレス、名前 |
| members | メンバー情報取得 | オーナー・メンテナーの特定 |

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

#### projects

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| id | プロジェクト識別 | パラメータで指定されたproject_id |
| name | プロジェクト名表示 | メール本文・件名に使用 |
| http_url_to_repo | プロジェクトURL | リンク表示用 |
| namespace_id | グループ情報取得 | 通知メールアドレス決定用 |

#### users

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| id | ユーザー識別 | オーナー・メンテナーのuser_id |
| name | ユーザー名表示 | 挨拶文に使用 |
| notification_email | 通知先アドレス | - |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| なし | - | Redisで通知済みフラグを管理 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 送信失敗 | SMTPサーバー接続エラー | Sidekiqによるリトライ |
| プロジェクト不存在 | プロジェクトが削除されている | エラーログ記録、処理スキップ |
| 宛先不正 | ユーザーのメールアドレスが無効 | 該当ユーザーをスキップ |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 3回（sidekiq_options retry: 3） |
| リトライ間隔 | 指数バックオフ |
| リトライ対象エラー | 一時的なネットワークエラー等 |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | GitLabのデフォルト設定に従う |
| 1日あたり上限 | GitLabのデフォルト設定に従う |

### 配信時間帯

Cronjobのスケジュールに従う。通常は業務時間外に実行される。

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

- プロジェクト名とURLのみが含まれ、機密情報は含まれない
- 通知はプロジェクトのオーナーおよびメンテナーにのみ送信
- 削除予定日は管理者設定に基づいて計算される

## 備考

- この通知は、以前に送信された削除予定通知を上書き（supersede）する
- 通知済みフラグはDormantProjectsDeletionWarningTrackerで管理される（Redis）
- 非アクティブプロジェクトの自動削除は管理者が設定で有効にする必要がある

---

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

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

### 推奨読解順序

#### Step 1: ワーカーを理解する

処理の起点となるワーカークラスを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | inactive_projects_deletion_notification_worker.rb | `app/workers/projects/inactive_projects_deletion_notification_worker.rb` | ワーカーのperformメソッド |

**主要処理フロー**:
- **14行目**: 通知済みチェック（DormantProjectsDeletionWarningTracker）
- **17行目**: プロジェクト取得
- **19行目**: NotificationService呼び出し
- **21行目**: 通知済みマーク

#### Step 2: 通知サービスを理解する

通知の送信ロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | notification_service.rb | `app/services/notification_service.rb` | inactive_project_deletion_warningメソッド（729-733行目） |

**主要処理フロー**:
- **729-733行目**: オーナー・メンテナー取得、各ユーザーにメール送信

#### Step 3: メーラーを理解する

メール生成処理を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | projects.rb | `app/mailers/emails/projects.rb` | inactive_project_deletion_warning_emailメソッド（127-137行目） |

**主要処理フロー**:
- **127-137行目**: @project、@user、@deletion_dateを設定してemail_with_layoutで送信

#### Step 4: ビューテンプレートを理解する

メール本文のテンプレートを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | inactive_project_deletion_warning_email.html.haml | `app/views/notify/inactive_project_deletion_warning_email.html.haml` | HTML本文の構造 |

**テンプレート内容**:
- **1-6行目**: 挨拶と削除予定の説明
- **11-16行目**: 削除回避のためのアクション例
- **18-25行目**: アクティビティ確認方法
- **27-28行目**: 通知の上書きに関する注記

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

```
Cronjob
    │
    └─ InactiveProjectsDeletionNotificationWorker#perform
           │
           ├─ DormantProjectsDeletionWarningTracker#notified? チェック
           │
           ├─ Project.find(project_id)
           │
           ├─ NotificationService#inactive_project_deletion_warning
           │      │
           │      └─ owners_and_maintainers_without_invites(project)
           │             │
           │             └─ 各ユーザー
           │                    └─ Notify#inactive_project_deletion_warning_email
           │                           └─ email_with_layout
           │
           └─ DormantProjectsDeletionWarningTracker#mark_notified
```

### データフロー図

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

project_id ────────▶ InactiveProjectsDeletionNotificationWorker ──▶ メール送信
deletion_date              │
                           ├─ NotificationService
                           │      └─ inactive_project_deletion_warning
                           │             │
                           │             └─ 各オーナー・メンテナー
                           │                    └─ メール送信
                           │                           ├─ ユーザー名
                           │                           ├─ プロジェクト名
                           │                           ├─ 削除予定日
                           │                           └─ アクション例
                           │
                           └─ Redis (通知済みフラグ)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| inactive_projects_deletion_notification_worker.rb | `app/workers/projects/inactive_projects_deletion_notification_worker.rb` | ソース | バックグラウンドジョブ |
| notification_service.rb | `app/services/notification_service.rb` | ソース | 通知送信サービス |
| projects.rb | `app/mailers/emails/projects.rb` | ソース | メール生成メーラー |
| inactive_project_deletion_warning_email.html.haml | `app/views/notify/inactive_project_deletion_warning_email.html.haml` | テンプレート | HTML本文テンプレート |
| dormant_projects_deletion_warning_tracker.rb | `lib/gitlab/dormant_projects_deletion_warning_tracker.rb` | ソース | 通知済みフラグ管理 |
