# バッチ設計書 15-app_delete

## 概要

本ドキュメントは、Shopwareプラットフォームにおけるアプリ削除カスケード処理バッチの設計仕様を定義します。削除マークが付けられたアプリに関連するACLロールとインテグレーションの完全削除（ハードデリート）を実行します。

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

**業務上の目的・背景**：Shopwareのアプリシステムでは、アプリを削除するとソフトデリート（論理削除）が適用され、関連データには`deleted_at`タイムスタンプが設定されます。これは誤削除からの復旧や、関連データの整合性を保つための設計です。しかし、一定期間経過後もこれらのデータを保持し続けると、データベースの肥大化やパフォーマンス低下を招きます。本バッチは削除から1日以上経過した関連データを完全に削除することで、データベースを健全な状態に保ちます。

**バッチの実行タイミング**：日次（86400秒間隔）でスケジュール実行されます。

**主要な処理内容**：
1. CLIコンテキストを作成
2. 削除閾値日時を計算（現在時刻 - 1日）
3. acl_roleテーブルから`deleted_at`が閾値より古いレコードを検索・削除
4. integrationテーブルから`deleted_at`が閾値より古いレコードを検索・削除

**前後の処理との関連**：前提として、アプリがAppLifecycleによって削除（ソフトデリート）されている必要があります。app_updateタスクとは逆の操作で、アプリライフサイクルの終了処理を担います。

**影響範囲**：acl_roleテーブルとintegrationテーブルに対してハードデリートを実行します。これらのテーブルに関連する外部キー制約により、カスケード削除が発生する可能性があります。

## バッチ種別

データクレンジング

## 実行スケジュール

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

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| ソフトデリート済みデータ | deleted_atが設定されたレコードが存在する |
| 削除から1日以上経過 | HARD_DELETE_AFTER_DAYS（1日）以上経過している |

### 実行可否判定

特別な実行条件チェックはありません。タスクは常に実行され、削除対象がない場合は何も処理しません。

## 入力仕様

### 入力パラメータ

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

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| acl_role | DB | 削除対象のACLロール（deleted_at設定済み） |
| integration | DB | 削除対象のインテグレーション（deleted_at設定済み） |

## 出力仕様

### 出力データ

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

### 出力ファイル仕様

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

## 処理フロー

### 処理シーケンス

```
1. コンテキスト作成
   └─ Context::createCLIContext()でCLIコンテキスト生成
2. 削除閾値日時計算
   └─ 現在時刻 - HARD_DELETE_AFTER_DAYS（1日）
3. 検索条件設定
   └─ deleted_at <= 閾値日時のRangeFilter作成
4. ACLロール削除
   └─ acl_roleテーブルから対象ID検索・削除
5. インテグレーション削除
   └─ integrationテーブルから対象ID検索・削除
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[CLIコンテキスト作成]
    B --> C[削除閾値日時計算]
    C --> D[RangeFilter作成]
    D --> E[ACLロールID検索]
    E --> F{対象あり?}
    F -->|Yes| G[ACLロール削除]
    F -->|No| H[インテグレーションID検索]
    G --> H
    H --> I{対象あり?}
    I -->|Yes| J[インテグレーション削除]
    I -->|No| K[バッチ終了]
    J --> K
```

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

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

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 削除対象検索 | acl_role | SELECT | deleted_at条件でID検索 |
| ACLロール削除 | acl_role | DELETE | ハードデリート実行 |
| 削除対象検索 | integration | SELECT | deleted_at条件でID検索 |
| インテグレーション削除 | integration | DELETE | ハードデリート実行 |

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

#### acl_role

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id | deleted_at <= :timeExpired | ID一覧取得 |
| DELETE | 全カラム | id IN (:ids) | ハードデリート |

#### integration

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id | deleted_at <= :timeExpired | ID一覧取得 |
| DELETE | 全カラム | id IN (:ids) | ハードデリート |

#### 検索条件

```php
$criteria = new Criteria();
$criteria->addFilter(new RangeFilter('deletedAt', [
    RangeFilter::LTE => $timeExpired,
]));
```

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| DB接続エラー | システムエラー | データベース接続失敗 | 接続設定を確認、再試行 |
| 外部キー制約エラー | データエラー | 関連データが残存 | 関連データの確認・削除 |

### リトライ仕様

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

### 障害時対応

1. エラーログを確認し原因を特定
2. 外部キー制約エラーの場合、関連テーブルを確認
3. 手動でDELETEクエリを実行（必要に応じて）

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | リポジトリのdelete操作単位 |
| コミットタイミング | delete呼び出し完了時 |
| ロールバック条件 | DELETE文失敗時 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 数件〜数百件（アプリ削除頻度による） |
| 目標処理時間 | 数秒〜数十秒 |
| メモリ使用量上限 | 通常のPHP制限に準拠 |

## 排他制御

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

## ログ出力

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

## 監視・アラート

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

## 備考

- HARD_DELETE_AFTER_DAYS定数は1日に設定されています
- アプリ削除から1日以上経過したACLロールとインテグレーションのみが削除対象となります
- EntityRepositoryのdeleteメソッドを使用しているため、DAL（Data Abstraction Layer）のイベントが発火されます
- 削除対象が存在しない場合、deleteメソッドは呼び出されません
- 内部使用タスク（@internal）として定義されています
