# バッチ設計書 12-log_entry.cleanup

## 概要

本ドキュメントは、Shopwareプラットフォームにおけるログエントリクリーンアップバッチの設計仕様を定義します。システムログテーブルに蓄積された古いログエントリを定期的に削除し、データベースのパフォーマンスとストレージを最適化します。

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

**業務上の目的・背景**：Shopwareシステムは運用中に多数のログエントリを生成します。エラーログ、警告ログ、情報ログなどが継続的に蓄積されると、データベースのストレージを圧迫し、クエリパフォーマンスに悪影響を及ぼします。また、古いログデータは運用上の価値が低下するため、一定期間経過後に自動削除することでシステムの健全性を維持します。これはGDPRなどのデータ保持ポリシーへの対応としても重要です。

**バッチの実行タイミング**：日次（86400秒間隔）でスケジュール実行されます。深夜帯などのシステム負荷が低い時間帯に実行することが推奨されます。

**主要な処理内容**：
1. システム設定からログエントリの保持期間（秒）を取得（`core.logging.entryLifetimeSeconds`）
2. システム設定から最大エントリ数を取得（`core.logging.entryLimit`）
3. 保持期間が-1でない場合、指定期間より古いログエントリを削除
4. 最大エントリ数が-1でない場合、制限を超える古いエントリを削除

**前後の処理との関連**：前提となるバッチは特にありません。ログ出力を行う全てのシステムコンポーネントの後続処理として位置づけられます。webhook_event_log.cleanupなど他のクリーンアップタスクと同様のデータ保守目的を持ちます。

**影響範囲**：log_entryテーブルに対してDELETE操作を実行します。削除されたログデータは復元できないため、必要に応じて外部ログシステムへのエクスポートを事前に行うことを推奨します。

## バッチ種別

データクレンジング

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 日次 |
| 実行時刻 | スケジュールタスクランナーに依存 |
| 実行曜日 | 毎日 |
| 実行日 | - |
| トリガー | cron（スケジュールタスク） |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| core.logging.entryLifetimeSeconds | -1以外の値が設定されている場合、期間ベースの削除を実行 |
| core.logging.entryLimit | -1以外の値が設定されている場合、件数ベースの削除を実行 |

### 実行可否判定

バッチは常に実行されますが、両設定が-1の場合は実質的に何も削除しません。少なくとも一方の設定が有効な場合にのみ削除処理が実行されます。

## 入力仕様

### 入力パラメータ

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

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| system_config | DB | ログ保持設定（entryLifetimeSeconds, entryLimit） |
| log_entry | DB | 削除対象のログエントリ |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| log_entry | DB | 削除操作（DELETE） |

### 出力ファイル仕様

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

## 処理フロー

### 処理シーケンス

```
1. 設定値取得
   └─ systemConfigServiceからentryLifetimeSecondsを取得
2. 設定値取得
   └─ systemConfigServiceからentryLimitを取得
3. 期間ベース削除
   └─ entryLifetimeSeconds != -1 の場合
   └─ 現在時刻から指定秒数前より古いエントリを削除
4. 件数ベース削除
   └─ entryLimit != -1 の場合
   └─ 最新N件を残して古いエントリを削除
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[設定値取得]
    B --> C{entryLifetimeSeconds != -1?}
    C -->|Yes| D[期間ベース削除実行]
    C -->|No| E{entryLimit != -1?}
    D --> E
    E -->|Yes| F[件数ベース削除実行]
    E -->|No| G[バッチ終了]
    F --> G
```

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

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

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 設定取得 | system_config | SELECT | ログ保持設定の取得 |
| 期間ベース削除 | log_entry | DELETE | 指定期間より古いエントリを削除 |
| 件数ベース削除 | log_entry | DELETE | 制限を超える古いエントリを削除 |

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

#### log_entry

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| DELETE | 全カラム | created_at < :before | 期間ベース削除 |
| DELETE | 全カラム | 最新N件以外 | 件数ベース削除（サブクエリ使用） |

#### 期間ベース削除SQL

```sql
DELETE FROM `log_entry` WHERE `created_at` < :before
```

#### 件数ベース削除SQL

```sql
DELETE ld FROM `log_entry` ld
LEFT JOIN (
    SELECT id
    FROM `log_entry`
    ORDER BY `created_at` DESC
    LIMIT :maxEntries
) ls ON ld.ID = ls.ID
WHERE ls.ID IS NULL
```

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| DB接続エラー | システムエラー | データベース接続失敗 | 接続設定を確認、再試行 |
| SQLエラー | システムエラー | DELETE文実行失敗 | ログを確認、手動対応 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 失敗時再スケジュール有効 |
| リトライ間隔 | 次回スケジュール実行時 |
| リトライ対象エラー | 全般的なエラー |

### 障害時対応

1. エラーログを確認し原因を特定
2. データベース接続を確認
3. 手動でDELETEクエリを実行（必要に応じて）
4. system_config設定を確認

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

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

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 数千〜数百万件（運用状況による） |
| 目標処理時間 | 数分以内 |
| メモリ使用量上限 | 通常のPHP制限に準拠 |

## 排他制御

特別な排他制御は実装されていません。DELETE操作はデータベースレベルで行ロックを取得します。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 開始ログ | タスク開始時 | タスク開始通知 |
| 終了ログ | タスク終了時 | 処理完了通知 |
| エラーログ | エラー発生時 | エラー詳細、スタックトレース |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| 処理時間 | 600秒 | システム管理者 |
| エラー件数 | 1件以上 | システム管理者 |

## 備考

- entryLifetimeSecondsとentryLimitの両方が-1に設定されている場合、クリーンアップは実行されません
- 大量のログエントリが存在する場合、削除処理に時間がかかる可能性があります
- 件数ベース削除はサブクエリを使用するため、大規模データでは注意が必要です
- ログデータの長期保存が必要な場合は、外部ログ管理システム（ELK Stack等）へのエクスポートを検討してください
