# 通知設計書 112-bulk_import_complete

## 概要

本ドキュメントは、GitLabにおける一括インポート完了通知（bulk_import_complete）の設計仕様を記述する。

### 本通知の処理概要

一括インポート完了通知は、GitLab Direct Transfer（旧BulkImport）機能を使用してグループやプロジェクトの一括インポートが完了した際に、インポートを実行したユーザーに対して完了を知らせるメール通知を送信する。

**業務上の目的・背景**：GitLab間でのグループ・プロジェクト移行は大規模なデータ転送を伴い、長時間を要する可能性がある。ユーザーが処理完了を待つことなく他の作業に従事できるよう、インポート完了時に通知を送信することで、移行作業の効率化と適切なタイミングでの結果確認を可能にする。

**通知の送信タイミング**：BulkImportのステートマシンがfinished、failed、またはtimeout状態に遷移した時点で、コールバックにより非同期で送信される。

**通知の受信者**：インポートを開始したユーザー（bulk_import.user）に送信される。

**通知内容の概要**：インポート元のホスト名（認証情報マスク済み）、開始日、完了状態を通知する。インポート結果の確認ページへのリンクも含まれる。

**期待されるアクション**：受信者はインポート履歴ページにアクセスし、インポート結果（成功・失敗・タイムアウト）を確認する。必要に応じてエラーの対処や再インポートを行う。

## 通知種別

メール

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（deliver_later） |
| 優先度 | 通常 |
| リトライ | Sidekiqデフォルト設定に従う |

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

BulkImportレコードに関連付けられたユーザー（bulk_import.user）の通知用メールアドレス（notification_email_or_default）に送信される。

## 通知テンプレート

### メール通知の場合

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | GitLabインスタンス設定に従う |
| 送信元名称 | GitLab |
| 件名 | `Import from {hostname} completed` |
| 形式 | テキスト |

### 本文テンプレート

```
Import completed

The import you started on {start_date} from {hostname} has completed. You can now review your import results.

View import results: {history_url}
```

### 添付ファイル

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

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| @bulk_import | インポート情報 | BulkImport.find(bulk_import_id) | Yes |
| @hostname | インポート元ホスト名（マスク済み） | @bulk_import.configuration.safe_url | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 状態遷移コールバック | after_transition any => [:finished, :failed, :timeout] | 常に送信 | ステートマシンの遷移後コールバックで送信 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| canceled状態への遷移 | キャンセルされた場合は通知が送信されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[BulkImportステータス変更] --> B{状態遷移先}
    B -->|finished/failed/timeout| C[send_completion_notification呼び出し]
    B -->|canceled| D[通知なし]
    C --> E[run_after_commit]
    E --> F[Notify.bulk_import_complete.deliver_later]
    F --> G[メール送信キューイング]
    G --> H[終了]
    D --> H
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| bulk_imports | インポート情報取得 | |
| bulk_import_configurations | インポート元URL取得 | safe_url経由で認証情報マスク |
| users | 送信先ユーザー情報取得 | |

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

#### bulk_imports

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| id | インポート特定 | BulkImport.find(bulk_import_id) |
| user_id | 送信先ユーザー特定 | |
| created_at | インポート開始日表示 | |

#### bulk_import_configurations

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| url | インポート元URL | bulk_import.configuration.safe_url |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| なし | - | 本通知処理ではDB更新は行わない |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| BulkImport未存在 | BulkImport.findで見つからない | ActiveRecord::RecordNotFoundが発生 |
| ユーザー未存在 | User.findで見つからない | ActiveRecord::RecordNotFoundが発生 |
| メール送信失敗 | SMTPエラー等 | Sidekiqのリトライに委ねる |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | Sidekiqデフォルト設定 |
| リトライ間隔 | Sidekiqデフォルト設定 |
| リトライ対象エラー | メール送信に関連するエラー |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | システム設定に従う |
| 1日あたり上限 | システム設定に従う |

### 配信時間帯

制限なし（24時間送信可能）

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

- インポート元URLはsafe_urlを使用し、パスワード等の認証情報をマスク処理（`*****:*****@`形式）
- run_after_commitを使用し、トランザクション完了後にのみメール送信をキューイング

## 備考

- GitLab Direct Transfer機能はGitLab 14.0以降で利用可能
- finished、failed、timeoutのいずれの状態でも同じメール文面が送信される
- 詳細な結果確認はimport履歴ページで行う設計

---

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

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

### 推奨読解順序

#### Step 1: データ構造を理解する

まず、BulkImportモデルとその関連モデルの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | bulk_import.rb | `app/models/bulk_import.rb` | ステートマシン定義、send_completion_notification、user関連 |

**読解のコツ**: state_machineのafter_transitionコールバックに注目。状態遷移後にどのメソッドが呼ばれるかを追跡する。

#### Step 2: 状態遷移とコールバックを理解する

ステートマシンの遷移とコールバックの関係を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | bulk_import.rb | `app/models/bulk_import.rb` | 28-68行目のstate_machine定義 |

**主要処理フロー**:
1. **57-61行目**: after_transition any => [:finished, :failed, :timeout]でsend_completion_notificationが呼ばれる
2. **107-111行目**: send_completion_notificationでrun_after_commit経由でメール送信

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

メール本文生成ロジックを確認する。

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

**主要処理フロー**:
- **40-53行目**: BulkImportの取得、hostnameの取得、件名の組み立て、メール送信

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | bulk_import_complete.text.erb | `app/views/notify/bulk_import_complete.text.erb` | 本文テンプレート全体 |

**主要処理フロー**:
- **1-5行目**: シンプルなテンプレート。条件分岐なし。

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

```
BulkImport状態遷移（finish!/fail_op!/cleanup_stale!）
    │
    └─ after_transition callback
           │
           ├─ update_has_failures
           │
           └─ send_completion_notification
                  │
                  └─ run_after_commit
                         │
                         └─ Notify.bulk_import_complete.deliver_later
                                │
                                ├─ User.find
                                ├─ BulkImport.find
                                │      └─ configuration.safe_url
                                │
                                └─ email_with_layout
```

### データフロー図

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

BulkImport状態遷移 ──────────▶ ステートマシンコールバック
                                      │
                                      ▼
                               send_completion_notification
                                      │
                                      ▼
user_id ──────────────────────▶ Notify.bulk_import_complete ────────────▶ メール送信
bulk_import_id ───────────────┤
                              │
BulkImport ───────────────────┤
    │                         │
    ├─ user ──────────────────┤
    ├─ configuration ─────────┤
    │      └─ safe_url ───────┤
    └─ created_at ────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| bulk_import.rb | `app/models/bulk_import.rb` | ソース | BulkImportモデル、ステートマシン定義 |
| imports.rb | `app/mailers/emails/imports.rb` | ソース | メーラーのbulk_import_completeメソッド |
| bulk_import_complete.text.erb | `app/views/notify/bulk_import_complete.text.erb` | テンプレート | メール本文テンプレート |
| configuration.rb | `app/models/bulk_imports/configuration.rb` | ソース | インポート設定、safe_url提供 |
| imports_spec.rb | `spec/mailers/emails/imports_spec.rb` | テスト | メーラーのテスト仕様 |
