# バッチ設計書 90-DependencyProxy::ImageTtlGroupPolicyWorker

## 概要

本ドキュメントは、依存プロキシのイメージTTLグループポリシーを適用するバッチ処理「DependencyProxy::ImageTtlGroupPolicyWorker」の設計仕様を定義するものである。

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

このバッチは、依存プロキシ（Dependency Proxy）のグループごとに設定されたTTL（Time To Live）ポリシーに基づいて、期限切れのBlobとManifestを検出し、削除対象としてマークするCronジョブである。

**業務上の目的・背景**：GitLabの依存プロキシ機能では、Dockerイメージのキャッシュにストレージを使用する。グループ管理者は、キャッシュの有効期限（TTL）ポリシーを設定することで、古いキャッシュデータを自動的に削除し、ストレージを効率的に管理できる。このバッチは、各グループのTTLポリシーを確認し、最終読み取り時刻がTTLを超過したBlobとManifestを期限切れとしてマークする。

**バッチの実行タイミング**：Cronジョブとして定期的に実行される。

**主要な処理内容**：
1. 有効なImageTtlGroupPolicyを全て取得
2. 各ポリシーに対して、グループの依存プロキシBlobとManifestを確認
3. TTL期限を超過し、まだアクティブ状態のBlobを特定
4. TTL期限を超過し、まだアクティブ状態のManifestを特定
5. expire_artifactsメソッドで期限切れとしてマーク
6. 各種カウントをログに出力

**前後の処理との関連**：本バッチがBlobとManifestをpending_destruction状態にマークし、CleanupDependencyProxyWorker（No.89）がクリーンアップワーカーをエンキューする。

**影響範囲**：dependency_proxy_blobs、dependency_proxy_manifests、dependency_proxy_image_ttl_group_policiesテーブル。

## バッチ種別

データクレンジング（期限切れマーキング）

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 定期実行（Cron） |
| 実行時刻 | 設定により異なる |
| 実行曜日 | 毎日 |
| 実行日 | 毎日 |
| トリガー | cron |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| ポリシー存在 | 有効なImageTtlGroupPolicyが存在すること |
| feature_category | virtual_registry機能が有効であること |

### 実行可否判定

有効なポリシーが存在しない場合は何も処理せずに終了する。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| なし | - | - | - | パラメータなしで実行 |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| DependencyProxy::ImageTtlGroupPolicy.enabled | DB | 有効なTTLポリシー |
| DependencyProxy::Blob | DB | グループの依存プロキシBlob |
| DependencyProxy::Manifest | DB | グループの依存プロキシManifest |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| dependency_proxy_blobs | DB | ステータスをpending_destructionに更新 |
| dependency_proxy_manifests | DB | ステータスをpending_destructionに更新 |
| Sidekiqログ | Metadata | 各種カウント情報 |

### 出力ファイル仕様

ファイル出力なし。

## 処理フロー

### 処理シーケンス

```
1. ワーカー起動
   └─ Sidekiqによりジョブがキューから取得される
2. 有効ポリシー取得
   └─ ImageTtlGroupPolicy.enabled で全ポリシー取得
3. 各ポリシー処理ループ
   ├─ グループの dependency_proxy_blobs を取得
   │   └─ active かつ TTL期限超過（read_before）のもの
   ├─ グループの dependency_proxy_manifests を取得
   │   └─ active かつ TTL期限超過（read_before）のもの
   ├─ expire_artifacts でBlobをマーク
   └─ expire_artifacts でManifestをマーク
4. ログ出力
   └─ 各種カウント情報をメタデータとして出力
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[ImageTtlGroupPolicy.enabled取得]
    B --> C{ポリシー存在?}
    C -->|No| D[ログ出力]
    C -->|Yes| E[各ポリシーを処理]
    E --> F[qualified_blobs取得]
    F --> G[group.blobs.active.read_before TTL]
    G --> H[qualified_manifests取得]
    H --> I[group.manifests.active.read_before TTL]
    I --> J[expire_artifacts Blobs]
    J --> K[expire_artifacts Manifests]
    K --> L{次のポリシー?}
    L -->|Yes| E
    L -->|No| D
    D --> M[バッチ終了]
```

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

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

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ポリシー取得 | dependency_proxy_image_ttl_group_policies | SELECT | 有効なポリシーを取得 |
| Blob取得 | dependency_proxy_blobs | SELECT | TTL超過のactiveなBlobを取得 |
| Manifest取得 | dependency_proxy_manifests | SELECT | TTL超過のactiveなManifestを取得 |
| Blobマーク | dependency_proxy_blobs | UPDATE | pending_destructionにマーク |
| Manifestマーク | dependency_proxy_manifests | UPDATE | pending_destructionにマーク |
| カウント取得 | 各テーブル | SELECT COUNT | ログ用カウント取得 |

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

#### dependency_proxy_image_ttl_group_policies

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | enabled = true | 有効なポリシーのみ |

#### dependency_proxy_blobs

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | status = active, read_at < policy.ttl | グループ単位で取得 |
| UPDATE | status | pending_destruction | expire_artifacts経由 |

#### dependency_proxy_manifests

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | * | status = active, read_at < policy.ttl | グループ単位で取得 |
| UPDATE | status | pending_destruction | expire_artifacts経由 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | DBエラー | データベース接続失敗 | 自動リトライ |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | Sidekiqデフォルト |
| リトライ間隔 | Sidekiqデフォルト（指数バックオフ） |
| リトライ対象エラー | 一般的な例外 |

### 障害時対応

idempotent!は設定されていないが、再実行しても既に期限切れのデータを再度マークするだけで安全。

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | expire_artifacts内部 |
| コミットタイミング | 各expire_artifacts呼び出し後 |
| ロールバック条件 | 更新失敗時 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | ポリシー数 x 期限切れアーティファクト数 |
| 目標処理時間 | ポリシー数に依存 |
| メモリ使用量上限 | ポリシー数に依存 |

## 排他制御

特別な排他制御なし。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| メタデータ | 処理完了時 | expired_dependency_proxy_blob_count |
| メタデータ | 処理完了時 | expired_dependency_proxy_manifest_count |
| メタデータ | 処理完了時 | processing_dependency_proxy_blob_count |
| メタデータ | 処理完了時 | processing_dependency_proxy_manifest_count |
| メタデータ | 処理完了時 | error_dependency_proxy_blob_count |
| メタデータ | 処理完了時 | error_dependency_proxy_manifest_count |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| expired_count | 急激な増加 | 運用チーム |
| error_count | 0以上 | 運用チーム |

## 備考

- feature_category: :virtual_registry
- data_consistency: :sticky
- idempotent: false（rubocop:disable Scalability/IdempotentWorker）
- DependencyProxy::Expireableモジュールをinclude
- expire_artifactsメソッドで期限切れマーキングを実行
- policy.ttl でTTL値を取得し、read_beforeスコープで期限切れを判定
- 各種ステータスカウント（pending_destruction, processing, error）をログ出力
