# バッチ設計書 10-check_for_migrations

## 概要

本ドキュメントは、InvenTreeシステムにおけるcheck_for_migrationsバッチ処理の設計仕様を定義します。このバッチは、データベースマイグレーションが必要かどうかを確認し、auto_update設定が有効な場合は自動的にマイグレーションを実行する機能を提供します。

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

**業務上の目的・背景**：InvenTreeはDjangoフレームワークを使用しており、システムのアップデートに伴ってデータベーススキーマの変更（マイグレーション）が必要になることがあります。マイグレーションを適時に実行しないと、アプリケーションが正常に動作しない可能性があります。本バッチは、未適用のマイグレーションを検出し、自動更新が有効な場合はメンテナンスモードに移行してマイグレーションを実行します。これにより、システム管理者は手動でのマイグレーション実行の手間を省き、システムを最新の状態に維持できます。

**バッチの実行タイミング**：日次で自動実行されます。Django-Qスケジューラにより、毎日1回実行されます。

**主要な処理内容**：
1. マイグレーション実行中またはバックアップ中でないことを確認
2. プラグインレジストリのリロード（reload_registry=Trueの場合）
3. 未適用のマイグレーション計画を取得
4. 未適用マイグレーション数をグローバル設定に保存
5. auto_update設定が有効かつマイグレーションがある場合：
   - メンテナンスモードを有効化
   - `migrate`コマンドを実行
   - メンテナンスモードを無効化
   - プラグインレジストリをリロード

**前後の処理との関連**：このバッチは`run_backup`バッチの後に実行されることが推奨されます。マイグレーション前にバックアップを取得しておくことで、問題発生時のリカバリが可能になります。`check_for_updates`バッチでアップデートが検出された後、実際のマイグレーションは本バッチで実行されます。

**影響範囲**：データベーススキーマ全体に影響を与える可能性があります。マイグレーション中はメンテナンスモードとなり、ユーザーはシステムにアクセスできなくなります。

## バッチ種別

システムメンテナンス / データベース管理

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 日次 |
| 実行時刻 | Django-Qスケジューラ依存 |
| 実行曜日 | 毎日 |
| 実行日 | 毎日 |
| トリガー | Django-Qスケジューラ（DAILY） |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Django-Qワーカー起動 | バックグラウンドワーカープロセスが稼働していること |
| データベース接続 | データベースへの接続が確立されていること |
| マイグレーション未実行中 | 他のマイグレーションプロセスが実行中でないこと |
| バックアップ未実行中 | バックアッププロセスが実行中でないこと |

### 実行可否判定

- `isRunningMigrations()`がFalseであること
- `isRunningBackup()`がFalseであること
- 上記いずれかがTrueの場合はFalseを返して終了

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| force | bool | No | False | Trueの場合、auto_update設定に関係なく強制実行 |
| reload_registry | bool | No | True | Trueの場合、処理前後でプラグインレジストリをリロード |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| MigrationExecutor | Django内部 | 未適用マイグレーション情報 |
| InvenTreeGlobalSetting | DB | INVENTREE_AUTO_UPDATE設定 |
| 環境設定 | config | auto_update設定 |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| InvenTreeGlobalSetting | DB | _PENDING_MIGRATIONS（未適用マイグレーション数） |
| データベーススキーマ | SQL | マイグレーション実行時にスキーマ変更 |
| ログ | テキスト | 処理状況をstructlogで出力 |

### 出力ファイル仕様

ファイル出力はありません。

## 処理フロー

### 処理シーケンス

```
1. 実行可否確認
   └─ isRunningMigrations()およびisRunningBackup()をチェック
   └─ いずれかがTrueの場合はFalseを返して終了
2. 内部関数定義
   └─ set_pending_migrations()関数を定義
3. プラグインレジストリのリロード（reload_registry=Trueの場合）
   └─ registry.check_reload()を呼び出し
4. マイグレーション計画の取得
   └─ MigrationExecutorでマイグレーション計画を取得
5. 未適用マイグレーションの確認
   └─ マイグレーションがない場合は_PENDING_MIGRATIONS=0を設定してTrue返却
6. auto_update確認（force=Falseの場合）
   └─ INVENTREE_AUTO_UPDATE設定を確認
   └─ 無効の場合はログ出力してFalse返却
7. メンテナンスモードでマイグレーション実行
   └─ メンテナンスモードを有効化
   └─ migrateコマンドを実行（interactive=False）
   └─ 成功時は_PENDING_MIGRATIONS=0を設定
   └─ メンテナンスモードを無効化
8. プラグインレジストリの完全リロード（reload_registry=Trueの場合）
   └─ registry.reload_plugins()を呼び出し
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B{マイグレーション/バックアップ実行中?}
    B -->|Yes| C[False返却で終了]
    B -->|No| D[ログ出力: チェック開始]
    D --> E{reload_registry=True?}
    E -->|Yes| F[プラグインレジストリリロード]
    E -->|No| G
    F --> G[マイグレーション計画取得]
    G --> H{未適用マイグレーションあり?}
    H -->|No| I[_PENDING_MIGRATIONS=0設定]
    I --> J[True返却で終了]
    H -->|Yes| K[_PENDING_MIGRATIONS=n設定]
    K --> L{force=True または auto_update有効?}
    L -->|No| M[ログ出力: auto_update無効]
    M --> N[False返却で終了]
    L -->|Yes| O[マイグレーションログ出力]
    O --> P[メンテナンスモード有効化]
    P --> Q[migrateコマンド実行]
    Q --> R{成功?}
    R -->|No| S[エラーログ出力]
    R -->|Yes| T[_PENDING_MIGRATIONS=0設定]
    T --> U[完了ログ出力]
    S --> V[メンテナンスモード確認・解除]
    U --> V
    V --> W{reload_registry=True?}
    W -->|Yes| X[プラグインレジストリ完全リロード]
    W -->|No| Y[True返却で終了]
    X --> Y
    C --> Z[処理終了]
    J --> Z
    N --> Z
    Y --> Z
```

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

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

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 設定取得 | InvenTreeGlobalSetting | SELECT | auto_update設定を取得 |
| マイグレーション数設定 | InvenTreeGlobalSetting | UPDATE | _PENDING_MIGRATIONS値を更新 |
| スキーマ変更 | 全テーブル | ALTER等 | マイグレーションによるスキーマ変更 |

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

#### InvenTreeGlobalSetting

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | value | key='INVENTREE_AUTO_UPDATE' | 環境設定と組み合わせて確認 |
| UPDATE | value | key='_PENDING_MIGRATIONS' | 0またはマイグレーション数 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | NotSupportedError | SQLite使用時の特定操作 | 警告ログ出力、SQLite以外のDBでは再raise |
| - | Exception | マイグレーション実行中の一般エラー | エラーログ出力（スタックトレース含む） |
| - | Exception | _PENDING_MIGRATIONS設定失敗 | エラーログ出力 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（明示的リトライなし） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

### 障害時対応

- マイグレーションエラー発生時：エラーログを確認し、手動で`python manage.py migrate`を実行
- メンテナンスモード解除されない場合：手動でメンテナンスモードを解除
- データベース不整合：バックアップから復元後、マイグレーションを再実行

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | 各マイグレーション操作ごと（Djangoが管理） |
| コミットタイミング | 各マイグレーション完了時 |
| ロールバック条件 | マイグレーション失敗時（部分的にロールバック） |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | マイグレーション数依存（通常数件〜数十件） |
| 目標処理時間 | マイグレーション内容に依存（数秒〜数分） |
| メモリ使用量上限 | マイグレーション内容に依存 |

## 排他制御

- 同時実行：isRunningMigrations()チェックにより他のマイグレーションとの同時実行を防止
- メンテナンスモード：マイグレーション中はシステム全体をメンテナンスモードに移行
- ロック仕様：`maintenance_mode_on()`コンテキストマネージャを使用

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 情報ログ | チェック開始時 | 'Checking for pending database migrations' |
| 情報ログ | マイグレーション数確認時 | 'There are %s pending migrations' |
| 情報ログ | auto_update無効時 | 'Auto-update is disabled - skipping migrations' |
| 情報ログ | 各マイグレーション | '- %s' (マイグレーション名) |
| 情報ログ | マイグレーション開始時 | 'Starting migration process...' |
| 情報ログ | マイグレーション完了時 | 'Completed %s migrations' |
| 警告ログ | メンテナンスモード解除されない場合 | 'Maintenance mode was not disabled - forcing it now' |
| 情報ログ | 手動解除時 | 'Manually released maintenance mode' |
| エラーログ | マイグレーションエラー時 | 'Error during migrations: %s' |
| エラーログ | 設定保存失敗時 | 'Could not clear _PENDING_MIGRATIONS flag' |
| トレースログ | 処理開始時 | OpenTelemetryスパン 'check_for_migrations' |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| 未適用マイグレーション数 | 1以上 | システム管理者 |
| マイグレーション失敗 | 1回以上 | システム管理者 |
| メンテナンスモード長時間 | 10分以上 | システム管理者 |
| 処理時間 | 30分以上 | システム管理者 |

## 備考

- 設定`INVENTREE_AUTO_UPDATE`または環境設定`auto_update`でマイグレーション自動実行の有効/無効を制御
- `force=True`パラメータは手動実行や緊急時のマイグレーション強制実行に使用
- メンテナンスモード中はユーザーからのアクセスがブロックされる
- SQLite使用時はNotSupportedErrorが発生する可能性があるが、ログ出力のみで処理継続
- マイグレーション完了後、プラグインレジストリの完全リロードが実行される（新しいモデル状態を反映）
- `get_maintenance_mode()`でメンテナンスモードが解除されたか確認し、必要に応じて手動解除
- 戻り値：マイグレーションが最新の場合True、それ以外はFalse
- `@tracer.start_as_current_span('check_for_migrations')`デコレータにより、OpenTelemetryによる分散トレーシングに対応
- 実装ファイル: `src/backend/InvenTree/InvenTree/tasks.py`
