# バッチ設計書 33-db:prepare

## 概要

本ドキュメントは、Railsフレームワークが提供するデータベース準備用Rakeタスク `db:prepare` の設計仕様について記載する。

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

`db:prepare` タスクは、データベースの状態を自動的に判断し、データベースが存在しない場合はセットアップ（setup）を実行し、既に存在する場合はマイグレーション（migrate）を実行するインテリジェントなRakeタスクである。

**業務上の目的・背景**：CI/CDパイプラインや自動デプロイメント環境において、データベースの現在の状態を意識することなく、適切な初期化・更新処理を自動的に選択実行するために設計されている。開発者やデプロイスクリプトが明示的に「setup or migrate」を判断する必要がなくなり、運用の簡素化と自動化を実現する。

**バッチの実行タイミング**：主にCI/CDパイプラインやデプロイメントスクリプトで自動実行される。手動実行も可能：
- CI/CDパイプラインでのテスト環境準備
- 本番デプロイメント時のデータベース更新
- 開発環境の自動セットアップ

**主要な処理内容**：
1. 現在の環境の各データベース設定をループ処理
2. 各データベースについて、初期化が必要かどうかを判定
3. データベースが存在しない場合：データベース作成とスキーマロードを実行
4. データベースが存在する場合：保留中のマイグレーションを実行
5. 新規作成されたデータベースでシード設定がある場合、シードデータをロード
6. マイグレーション実行後、スキーマダンプを実行（設定による）

**前後の処理との関連**：
- 関連タスク：`db:setup`（データベースが存在しない場合に内部的に呼ばれる処理と同等）
- 関連タスク：`db:migrate`（データベースが存在する場合に内部的に呼ばれる）
- 設定依存：`ActiveRecord.dump_schema_after_migration` でスキーマダンプの有無を制御

**影響範囲**：データベースの状態に応じて、新規作成またはマイグレーションによるスキーマ更新が行われる。development環境で実行した場合、test環境のデータベースも同時に処理される（DATABASE_URLが設定されていない場合）。

## バッチ種別

データベース管理 / 環境準備・自動判定

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時（デプロイ時、CI実行時） |
| 実行時刻 | 任意 |
| 実行曜日 | 任意 |
| 実行日 | 任意 |
| トリガー | 手動/自動（bin/rails db:prepare） |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| データベース設定 | config/database.yml が正しく設定されていること |
| スキーマファイル | db/schema.rb または db/structure.sql が存在すること（新規セットアップ時） |
| マイグレーションファイル | db/migrate ディレクトリにマイグレーションが存在すること（更新時） |

### 実行可否判定

- スキーマファイルとデータベースの両方が存在しない場合、マイグレーションを実行
- schema_migrations テーブルの存在でデータベース初期化済みかを判定
- 各データベース設定の `seeds?` フラグでシードデータ投入の要否を判定

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| RAILS_ENV | 環境変数 | No | development | 対象環境を指定 |
| VERSION | 環境変数 | No | なし | 特定のマイグレーションバージョンを指定 |
| VERBOSE | 環境変数 | No | true | 処理の詳細出力を制御 |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| config/database.yml | YAML | データベース接続設定 |
| db/schema.rb | Ruby | スキーマ定義ファイル（Ruby形式） |
| db/structure.sql | SQL | スキーマ定義ファイル（SQL形式） |
| db/migrate/*.rb | Ruby | マイグレーションファイル |
| db/seeds.rb | Ruby | シードデータ定義ファイル |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| データベース | DB | セットアップまたはマイグレーションされたデータベース |
| db/schema.rb | Ruby | 更新されたスキーマファイル（設定による） |
| 標準出力 | テキスト | 処理結果メッセージ |

### 出力ファイル仕様

| 項目 | 内容 |
|-----|------|
| ファイル名 | db/schema.rb または db/structure.sql |
| 出力先 | db/ ディレクトリ |
| 文字コード | UTF-8 |
| 出力条件 | ActiveRecord.dump_schema_after_migration が true の場合 |

## 処理フロー

### 処理シーケンス

```
1. load_config
   └─ Railsアプリケーションとデータベース設定をロード
2. 各データベース設定に対してループ処理
   └─ initialize_database を呼び出し
3. initialize_database の内部処理
   └─ 3.1 with_temporary_pool でDB接続を確立
   └─ 3.2 schema_migration.table_exists? でDB初期化済みか判定
   └─ 3.3 NoDatabaseError の場合、create でDB作成
   └─ 3.4 未初期化の場合、スキーマファイルがあれば load_schema
4. 各環境に対してマイグレーション実行
   └─ 4.1 db_configs_with_versions で保留中のマイグレーションを取得
   └─ 4.2 各バージョンのマイグレーションを実行
5. スキーマダンプ（設定による）
   └─ ActiveRecord.dump_schema_after_migration が true の場合実行
6. シードデータのロード
   └─ 新規作成されたDBで seeds? が true の場合実行
```

### フローチャート

```mermaid
flowchart TD
    A[db:prepare 開始] --> B[設定ロード]
    B --> C[各DB設定をループ]
    C --> D{schema_migrations存在?}
    D -->|存在しない| E{NoDatabaseError?}
    E -->|Yes| F[データベース作成]
    F --> G{スキーマファイル存在?}
    E -->|No| G
    G -->|Yes| H[スキーマロード]
    G -->|No| I[スキップ]
    D -->|存在する| J[初期化済み]
    H --> K[seed フラグ確認]
    I --> L[マイグレーション実行]
    J --> L
    K --> L
    L --> M{dump_schema_after_migration?}
    M -->|Yes| N[スキーマダンプ]
    M -->|No| O[スキップ]
    N --> P{seed必要?}
    O --> P
    P -->|Yes| Q[シードデータロード]
    P -->|No| R[db:prepare 完了]
    Q --> R
```

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

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

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| initialize_database | - | CREATE DATABASE | 必要に応じてDB作成 |
| load_schema | 全テーブル | CREATE TABLE | スキーマに基づきテーブル作成 |
| migrate | schema_migrations | INSERT | マイグレーションバージョンを記録 |
| migrate | 対象テーブル | ALTER/CREATE/DROP | マイグレーション内容による |
| load_seed | シード対象テーブル | INSERT/UPDATE | 初期データを投入 |

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

#### schema_migrations

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | version | - | 初期化済み判定に使用 |
| INSERT | version | マイグレーションバージョン | マイグレーション実行時に記録 |

#### ar_internal_metadata

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT/UPDATE | key, value | environment, schema_sha1 | スキーマロード後に更新 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | NoDatabaseError | データベースが存在しない | 内部でDB作成を実行（正常フロー） |
| - | MigrationError | マイグレーション実行中のエラー | マイグレーションファイルを確認 |
| - | ConnectionError | データベース接続失敗 | database.yml設定を確認 |
| - | スキーマファイルエラー | スキーマファイルが破損 | db:migrateで再生成 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | NoDatabaseError時に1回（内部で自動リトライ） |
| リトライ間隔 | 即時 |
| リトライ対象エラー | NoDatabaseError（DB作成後に再試行） |

### 障害時対応

1. エラーメッセージを確認し、原因を特定
2. データベースサーバーの稼働状態を確認
3. database.yml の設定を確認
4. マイグレーションファイルの整合性を確認
5. 必要に応じてスキーマファイルを再生成

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | マイグレーション単位 |
| コミットタイミング | 各マイグレーション完了時 |
| ロールバック条件 | マイグレーション失敗時 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | データベース設定数 × マイグレーション数 |
| 目標処理時間 | マイグレーション内容・数量に依存 |
| メモリ使用量上限 | 特に制限なし |

## 排他制御

- 同時実行は非推奨（特にマイグレーション実行時）
- マイグレーション中は advisory lock でロックを取得
- スキーマダンプ時はファイル書き込みロックを取得

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 開始ログ | タスク開始時 | 処理対象環境・DB |
| 進捗ログ | 処理中 | "Created database", マイグレーション名 等 |
| 終了ログ | 各処理終了時 | 完了メッセージ |
| エラーログ | エラー発生時 | エラー詳細メッセージ |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| 処理時間 | プロジェクトに応じて設定 | 運用チーム |
| エラー件数 | 1件以上 | 運用チーム |
| マイグレーション失敗 | 1件以上 | 開発者・運用チーム |

## 備考

- `db:prepare` はCI/CDパイプラインでの使用に最適化されている
- データベースの状態を自動判定するため、手動での状態確認が不要
- マルチデータベース構成にも対応しており、すべてのデータベースを順次処理
- `prepare_all` メソッドは内部的に `initialize_database` と `migrate` を組み合わせて実行
- 新規作成されたデータベースでのみシードデータがロードされる（既存DBの場合はスキップ）
- スキーマダンプは `ActiveRecord.dump_schema_after_migration` 設定に従う
