# バッチ設計書 15-Account::DataImportJob

## 概要

本ドキュメントは、アカウントデータインポートジョブ（Account::DataImportJob）の設計仕様を記載したものです。

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

Account::DataImportJobは、エクスポートされたデータをアカウントにインポートする非同期ジョブです。ActiveJob::Continuableを使用した継続可能なジョブとして実装されており、大量データの安全なインポートを実現します。

**業務上の目的・背景**：他のシステムやアカウントからのデータ移行、バックアップデータの復元など、大量のデータを新しいアカウントにインポートする必要があります。処理が長時間に及ぶ可能性があるため、継続可能なジョブとして実装し、中断からの復旧を可能にしています。

**バッチの実行タイミング**：ユーザーがインポート用のZIPファイルをアップロードした後、Account::Import#process_laterメソッドによりジョブがキューに投入されます。

**主要な処理内容**：
1. checkステップ：インポートデータの整合性チェック
2. processステップ：データのインポート処理
3. インポート完了後の後処理（ボードアクセス設定、カード数整合、ストレージ整合）
4. 完了/失敗メールの送信

**前後の処理との関連**：DataExportJobでエクスポートされたZIPファイルをインポートします。インポート完了後はImportMailerで完了通知が送信されます。

**影響範囲**：アカウントに関連する全てのテーブルへのデータ挿入、ストレージの更新。

## バッチ種別

データ連携

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時（ユーザー要求時） |
| 実行時刻 | - |
| 実行曜日 | - |
| 実行日 | - |
| トリガー | Account::Import#process_later呼び出し |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Account::Importレコードが存在 | status: pendingの状態 |
| ZIPファイルが添付済み | import.fileが存在 |
| ZIPファイルが有効 | フォーマットが正しいこと |

### 実行可否判定

Account::Importレコードがデシリアライズ可能で、ZIPファイルが有効な場合に実行。
以下のエラーではジョブを破棄：
- Account::DataTransfer::RecordSet::IntegrityError
- ZipFile::InvalidFileError

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| import | Account::Import | Yes | - | インポート対象のレコード |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| account_imports | DB | インポート設定情報 |
| ZIPファイル | Active Storage | インポートデータを含むZIP |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| accounts | DB | アカウント情報更新 |
| boards | DB | ボードデータ挿入 |
| cards | DB | カードデータ挿入 |
| その他関連テーブル | DB | インポートデータに応じて |

### 出力ファイル仕様

ファイル出力なし

## 処理フロー

### 処理シーケンス

```
1. Importオブジェクトを受け取り
   └─ 不正なファイルの場合はジョブを破棄
2. checkステップ実行
   └─ ステータスをprocessingに更新
   └─ ZIPファイル読み込み
   └─ 各レコードセットの整合性チェック
   └─ コールバックで進捗を報告
3. processステップ実行
   └─ ステータスをprocessingに更新
   └─ ZIPファイル読み込み
   └─ 各レコードセットのインポート
   └─ コールバックで進捗を報告
4. 後処理
   └─ インポーターをall_accessボードに追加
   └─ カード数の整合性確認
   └─ ストレージの整合性確認と実体化
5. 完了処理
   └─ ステータスをcompletedに更新
   └─ 完了メール送信
6. エラー発生時
   └─ ステータスをfailedに更新
   └─ 失敗理由を記録
   └─ 失敗メール送信
```

### フローチャート

```mermaid
flowchart TD
    A[ジョブ開始] --> B{デシリアライズ成功?}
    B -->|失敗| C[ジョブ破棄]
    B -->|成功| D[checkステップ開始]
    D --> E[ステータスをprocessingに更新]
    E --> F[ZIPファイル読み込み]
    F --> G[各レコードセットをチェック]
    G --> H{チェック成功?}
    H -->|失敗 - conflict| I[mark_as_failed conflict]
    H -->|失敗 - invalid| J[mark_as_failed invalid_export]
    H -->|成功| K[processステップ開始]
    K --> L[各レコードセットをインポート]
    L --> M{インポート成功?}
    M -->|失敗| N[mark_as_failed]
    M -->|成功| O[後処理実行]
    O --> P[mark_completed]
    P --> Q[完了メール送信]
    Q --> R[ジョブ終了]
    I --> S[失敗メール送信]
    J --> S
    N --> S
    S --> R
```

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

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

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| インポート取得 | account_imports | SELECT | インポート情報取得 |
| ステータス更新 | account_imports | UPDATE | processing/completed/failed |
| データインポート | 各種テーブル | INSERT | ZIPファイル内のデータ |
| ボードアクセス | board_accesses | INSERT | インポーターへのアクセス付与 |
| カード数更新 | accounts | UPDATE | cards_countの整合 |
| ストレージ更新 | accounts/boards | UPDATE | storage関連の整合 |

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

#### account_imports

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | status | processing | 処理開始時 |
| UPDATE | status | completed | 処理完了時 |
| UPDATE | completed_at | Time.current | 完了時刻 |
| UPDATE | status | failed | エラー発生時 |
| UPDATE | failure_reason | conflict/invalid_export | 失敗理由 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | IntegrityError | データ整合性エラー | ジョブ破棄、failed_due_to_invalid_export |
| - | InvalidFileError | ZIPファイル不正 | ジョブ破棄、failed_due_to_invalid_export |
| - | ConflictError | データ競合 | ステータスをfailed、failed_due_to_conflict |
| - | StandardError | その他エラー | ステータスをfailed |

### リトライ仕様

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

### 障害時対応

- IntegrityError/InvalidFileErrorはジョブを破棄（discard_on）
- ConflictErrorはfailed_due_to_conflictで記録
- その他のエラーはfailedで記録
- 失敗時はImportMailer.failedで通知
- 7日後にfailedのインポートはcleanupで削除

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | レコードセット単位 |
| コミットタイミング | 各レコードセット処理後 |
| ロールバック条件 | エラー発生時 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | インポートデータ量に依存 |
| 目標処理時間 | データ量に依存（数分〜数時間） |
| メモリ使用量上限 | 継続可能ジョブで分散処理 |

## 排他制御

同一Importに対する複数ジョブ実行は想定しない。ステータスで状態管理。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 開始ログ | ジョブ開始時 | Active Jobデフォルト |
| 進捗ログ | 各ステップのコールバック | レコードセット名、ファイル名 |
| 終了ログ | ジョブ終了時 | Active Jobデフォルト |
| エラーログ | エラー発生時 | エラー種別、失敗理由 |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| 処理時間 | 設定依存 | 運用チーム |
| エラー件数 | 設定依存 | 運用チーム |

## 備考

- キューは`backend`を使用
- ActiveJob::Continuableで継続可能なジョブとして実装
- checkステップとprocessステップの2段階で処理
- failure_reasonはconflictとinvalid_exportの2種類
- 完了したインポートは24時間後、失敗したインポートは7日後にcleanupで削除
- インポーターはall_accessボードに自動追加される
- Account::DataTransfer::Manifestでレコードセットを管理
