# バッチ設計書 7-check_for_updates

## 概要

本ドキュメントは、InvenTreeシステムにおけるcheck_for_updatesバッチ処理の設計仕様を定義します。このバッチは、InvenTreeの新しいバージョンがリリースされているかをGitHub APIを通じて確認し、利用可能なアップデートがある場合にスーパーユーザーに通知する機能を提供します。

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

**業務上の目的・背景**：InvenTreeはオープンソースの在庫管理システムとして継続的に開発が進められており、セキュリティパッチ、バグ修正、新機能が定期的にリリースされます。システム管理者が最新バージョンを把握し、適時にアップデートを実施できるようにすることは、セキュリティと機能性の維持に重要です。本バッチは、GitHub APIを通じて最新リリース情報を取得し、現在のバージョンと比較して、アップデートが必要な場合にスーパーユーザーにUI通知を送信します。

**バッチの実行タイミング**：日次でスケジュールされますが、実際の外部API呼び出しは設定可能な間隔（デフォルト7日）で実行されます。これにより、GitHub APIのレート制限を考慮しつつ適切な頻度でチェックを行います。

**主要な処理内容**：
1. チェック間隔設定`INVENTREE_UPDATE_CHECK_INTERVAL`に基づき実行可否を判定
2. GitHub API（https://api.github.com/repos/inventree/inventree/releases/latest）から最新リリース情報を取得
3. レスポンスからバージョン番号（tag_name）を解析
4. 最新バージョンをグローバル設定に保存
5. 現在のバージョンが最新でない場合、スーパーユーザーにUI通知を送信

**前後の処理との関連**：このバッチは独立して動作しますが、通知結果は`delete_old_notifications`バッチによって一定期間後に削除されます。また、`check_for_migrations`バッチと連携して、アップデート実行時のマイグレーション処理につながります。

**影響範囲**：グローバル設定テーブル（_INVENTREE_LATEST_VERSION）と通知テーブルに影響します。外部サービス（GitHub API）への依存があります。

## バッチ種別

外部連携 / 通知配信

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 日次（スケジュール）/ 実際は7日間隔（デフォルト） |
| 実行時刻 | Django-Qスケジューラ依存 |
| 実行曜日 | 毎日（ホールドオフロジックで制御） |
| 実行日 | 毎日（ホールドオフロジックで制御） |
| トリガー | Django-Qスケジューラ（DAILY） + check_daily_holdoff |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Django-Qワーカー起動 | バックグラウンドワーカープロセスが稼働していること |
| データベース接続 | データベースへの接続が確立されていること |
| Appレジストリ準備完了 | Djangoアプリケーションレジストリが初期化されていること |
| インターネット接続 | GitHub APIへのHTTPS接続が可能であること |

### 実行可否判定

- Django-Qワーカープロセスが起動している場合、日次でスケジュール実行
- `check_daily_holdoff`関数により、設定間隔（デフォルト7日）以内に成功していれば実行をスキップ
- `AppRegistryNotReady`例外が発生した場合は処理をスキップしログ出力

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| なし | - | - | - | 入力パラメータは不要 |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| GitHub API | JSON/REST | https://api.github.com/repos/inventree/inventree/releases/latest |
| InvenTreeGlobalSetting | DB | INVENTREE_UPDATE_CHECK_INTERVAL設定 |
| InvenTreeGlobalSetting | DB | _check_for_updates_ATTEMPT, _check_for_updates_SUCCESS（ホールドオフ用） |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| InvenTreeGlobalSetting | DB | _INVENTREE_LATEST_VERSION（最新バージョン番号） |
| 通知テーブル | DB | スーパーユーザーへのアップデート通知 |
| ログ | テキスト | 処理状況をstructlogで出力 |

### 出力ファイル仕様

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

## 処理フロー

### 処理シーケンス

```
1. モジュールのインポート
   └─ 通知関連モジュールをインポート（失敗時は処理終了）
2. チェック間隔の検証
   └─ INVENTREE_UPDATE_CHECK_INTERVAL設定を取得（デフォルト7日）
   └─ check_daily_holdoffで実行可否を判定
3. GitHub API呼び出し
   └─ 最新リリース情報を取得
   └─ テスト環境ではGITHUB_TOKENで認証
4. レスポンス解析
   └─ HTTPステータスコードを確認（200以外はエラー）
   └─ tag_nameからバージョン番号を抽出（正規表現でX.Y.Z形式を解析）
5. 結果の保存
   └─ _INVENTREE_LATEST_VERSIONに最新バージョンを保存
   └─ タスク成功を記録
6. 通知判定・送信
   └─ isInvenTreeUpToDate()で現在バージョンと比較
   └─ 最新でない場合、スーパーユーザーにUI通知を送信
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B{Appレジストリ準備完了?}
    B -->|No| C[ログ出力して終了]
    B -->|Yes| D[チェック間隔設定を取得]
    D --> E{check_daily_holdoff通過?}
    E -->|No| F[スキップして終了]
    E -->|Yes| G[GitHub API呼び出し]
    G --> H{ステータス200?}
    H -->|No| I[エラー発生]
    H -->|Yes| J[tag_nameを抽出]
    J --> K{バージョン形式正しい?}
    K -->|No| L[警告ログ出力して終了]
    K -->|Yes| M[最新バージョンを保存]
    M --> N[タスク成功を記録]
    N --> O{最新バージョン?}
    O -->|Yes| P[バッチ終了]
    O -->|No| Q[スーパーユーザーに通知送信]
    Q --> P
    C --> R[処理終了]
    F --> R
    I --> R
    L --> R
    P --> R
```

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

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

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 設定取得 | InvenTreeGlobalSetting | SELECT | チェック間隔設定を取得 |
| ホールドオフ確認 | InvenTreeGlobalSetting | SELECT | 前回実行日時を確認 |
| ホールドオフ記録 | InvenTreeGlobalSetting | UPDATE | 実行試行日時を記録 |
| バージョン保存 | InvenTreeGlobalSetting | UPDATE | 最新バージョンを保存 |
| 成功記録 | InvenTreeGlobalSetting | UPDATE | タスク成功日時を記録 |
| 通知送信 | NotificationMessage等 | INSERT | アップデート通知を作成 |
| ユーザー取得 | auth_user | SELECT | スーパーユーザー一覧を取得 |

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

#### InvenTreeGlobalSetting

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | value | key='INVENTREE_UPDATE_CHECK_INTERVAL' | デフォルト7日 |
| SELECT | value | key='_check_for_updates_ATTEMPT' | 前回試行日時 |
| SELECT | value | key='_check_for_updates_SUCCESS' | 前回成功日時 |
| UPDATE | value | key='_check_for_updates_ATTEMPT' | 現在日時をISO形式で保存 |
| UPDATE | value | key='_INVENTREE_LATEST_VERSION' | 最新バージョンタグを保存 |
| UPDATE | value | key='_check_for_updates_SUCCESS' | 成功日時をISO形式で保存 |

#### auth_user

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | is_superuser=True | 通知対象ユーザーの取得 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | AppRegistryNotReady | Djangoアプリ初期化前に実行 | ログ出力後、処理をスキップ |
| - | ValueError | GitHub APIステータスが200以外 | 例外をraiseして処理終了 |
| - | ValueError | tag_nameがレスポンスに存在しない | 例外をraiseして処理終了 |
| - | - | バージョン形式が不正 | 警告ログ出力して処理終了（正常終了） |

### リトライ仕様

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

備考：check_daily_holdoffにより、失敗時は12時間以内の再試行を抑制

### 障害時対応

- AppRegistryNotReady発生時：次回スケジュール実行で自動復旧
- GitHub API接続エラー：12時間後に自動リトライ（ホールドオフロジック）
- バージョン形式エラー：ログを確認し、GitHub側のリリース情報を確認

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | 各UPDATE操作ごと |
| コミットタイミング | 各操作完了時に自動コミット |
| ロールバック条件 | 例外発生時（ただし明示的なロールバック処理なし） |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 1回のAPI呼び出し |
| 目標処理時間 | 10秒以内（ネットワーク遅延依存） |
| メモリ使用量上限 | 20MB以下 |

## 排他制御

- 同時実行：Django-Qスケジューラにより1日1回のみ実行
- ロック仕様：check_daily_holdoffにより12時間以内の重複実行を防止

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 情報ログ | チェック開始時 | 'Checking for InvenTree software updates' |
| 情報ログ | バージョン取得成功時 | "Latest InvenTree version: '%s'" |
| 警告ログ | バージョン形式不正時 | "Version '%s' did not match expected pattern" |
| 情報ログ | Appレジストリ未準備時 | "Could not perform 'check_for_updates' - App registry not ready" |
| トレースログ | 処理開始時 | OpenTelemetryスパン 'check_for_updates' |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| API接続失敗 | 連続3回以上 | システム管理者 |
| 処理時間 | 30秒以上 | システム管理者 |
| 新バージョン検出 | 検出時 | スーパーユーザー（UI通知） |

## 備考

- 設定`INVENTREE_UPDATE_CHECK_INTERVAL`はInvenTree管理画面から変更可能（デフォルト7日）
- テスト環境では環境変数`GITHUB_TOKEN`を使用してAPI認証を行う（レート制限対策）
- バージョン番号は正規表現`^.*(\d+)\.(\d+)\.(\d+).*$`で解析（セマンティックバージョニング対応）
- 通知はInvenTreeUINotificationsを使用してUI内に表示（メール通知ではない）
- `isInvenTreeUpToDate()`関数で現在のバージョンとの比較を実行
- `@tracer.start_as_current_span('check_for_updates')`デコレータにより、OpenTelemetryによる分散トレーシングに対応
- 実装ファイル: `src/backend/InvenTree/InvenTree/tasks.py`
