# 機能設計書 4-グループ削除

## 概要

本ドキュメントは、Etherpad APIにおける「グループ削除」機能の設計仕様を記載する。

### 本機能の処理概要

指定されたグループと、そのグループに属するすべてのパッドおよび関連セッションを完全に削除する機能である。カスケード削除により、グループに紐づくすべてのリソースが一括で削除される。

**業務上の目的・背景**：
プロジェクト終了やチーム解散時に、グループとその関連リソースをまとめて削除する必要がある。本機能により、グループ単位でのクリーンアップが可能になり、ストレージの解放とデータ管理の簡素化が実現できる。孤立したパッドやセッションを残さずに完全な削除が行える。

**機能の利用シーン**：
- プロジェクト終了時のクリーンアップ
- テスト用グループの削除
- 不要になったグループの整理
- データ保持ポリシーに基づく削除

**主要な処理内容**：
1. グループの存在確認
2. グループ内の全パッドを並列で削除
3. グループに関連する全セッションを並列で削除
4. group2sessionsレコードの削除
5. グローバルなグループ一覧からエントリを削除
6. グループに紐づくマッピングレコードを削除
7. グループ本体レコードの削除

**関連システム・外部連携**：
- ueberDB2データベースによるデータ削除
- PadManager（パッド削除時）
- SessionManager（セッション削除時）

**権限による制御**：
APIキーまたはOAuth2トークンによる認証が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 画面からの直接操作はなく、API経由でのみ利用される |

## 機能種別

CRUD操作（Delete）- カスケード削除

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| groupID | string | Yes | 削除対象のグループID | 存在するグループIDであること |
| apikey | string | Yes（APIキー認証時） | API認証キー | 設定ファイルのAPIキーと一致すること |
| authorization | string | Yes（OAuth2認証時） | Bearerトークン | 有効なJWTトークンであること |

### 入力データソース

HTTP DELETEリクエスト（`/api/2/groups`）のボディから取得。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| code | number | 処理結果コード（0: 成功） |
| message | string | 処理結果メッセージ（"ok"） |
| data | null | 削除処理のため戻り値なし |

### 出力先

HTTPレスポンス（JSON形式）

## 処理フロー

### 処理シーケンス

```
1. API認証
   └─ APIキーまたはOAuth2トークンを検証
2. グループ存在確認
   └─ db.get(`group:${groupID}`)
   └─ 存在しなければエラー返却
3. 全パッド削除（並列）
   └─ group.padsの各パッドに対してpad.remove()を実行
4. 全セッション削除（並列）
   └─ group2sessions:{groupID}から全セッションIDを取得
   └─ 各セッションに対してsessionManager.deleteSession()を実行
5. 関連レコード削除（並列）
   └─ db.remove(`group2sessions:${groupID}`)
   └─ db.setSub('groups', [groupID], undefined) // 一覧から削除
   └─ group.mappingsの各マッパーに対してmapper2group:{mapper}を削除
6. グループレコード削除
   └─ db.remove(`group:${groupID}`)
7. レスポンス返却
```

### フローチャート

```mermaid
flowchart TD
    A[DELETE /api/2/groups] --> B{認証検証}
    B -->|失敗| C[401 Unauthorized]
    B -->|成功| D["db.get group:groupID"]
    D --> E{グループ存在?}
    E -->|No| F[400 groupID does not exist]
    E -->|Yes| G[Promise.all: 全パッド削除]
    G --> H[Promise.all: 全セッション削除]
    H --> I["Promise.all:
    - group2sessions削除
    - groups一覧更新
    - mapper2group削除"]
    I --> J["db.remove group:groupID"]
    J --> K["返却 {data: null}"]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | カスケード削除 | グループ削除時に関連パッドも全削除 | 常に |
| BR-002 | セッション削除 | グループ削除時に関連セッションも全削除 | 常に |
| BR-003 | マッピング削除 | グループ削除時に関連マッパーも削除 | マッピングが存在する場合 |
| BR-004 | 削除順序 | パッド・セッション削除後にグループ本体を削除 | 常に |

### 計算ロジック

なし

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| グループ取得 | group:{groupID} | SELECT | 削除対象の確認 |
| パッド削除 | pad:{padID} 他 | DELETE | 関連パッドの削除 |
| セッション取得 | group2sessions:{groupID} | SELECT | セッションID取得 |
| セッション削除 | 複数テーブル | DELETE | 関連セッションの削除 |
| セッション関連削除 | group2sessions:{groupID} | DELETE | セッション関連レコード削除 |
| グループ一覧更新 | groups | UPDATE | グループ一覧から除外 |
| マッピング削除 | mapper2group:{mapper} | DELETE | マッパー関連削除 |
| グループ削除 | group:{groupID} | DELETE | グループ本体削除 |

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

#### group:{groupID}

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | - | 全体 | 存在確認とpads/mappings取得 |
| DELETE | - | 全体 | レコード削除 |

#### groups

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | [groupID] | undefined | プロパティ削除 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | パラメータエラー | groupIDが存在しない | 正しいgroupIDを指定 |
| 4 | 認証エラー | APIキーが無効または未指定 | 正しいAPIキーを指定 |
| 2 | 内部エラー | データベース操作失敗 | サーバーログを確認 |

### リトライ仕様

データベース操作失敗時のリトライはueberDB2層で処理される。

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

完全なトランザクション管理は行われない。削除処理は以下の順序で実行される：

1. パッド削除（並列）
2. セッション削除（並列）
3. 関連レコード削除（並列）
4. グループ本体削除

途中で失敗した場合、部分的な削除状態になる可能性がある。

## パフォーマンス要件

- レスポンス時間: パッド数・セッション数に依存（数秒かかる場合あり）
- 並列処理により複数リソースを効率的に削除

## セキュリティ考慮事項

- APIキーまたはOAuth2トークンによる認証が必須
- 削除操作は不可逆のため、呼び出し元での確認が推奨される
- 監査ログ機能はコアには含まれていない

## 備考

- 削除操作は非同期的に実行され、完了を待つ
- 大量のパッドを含むグループの削除は時間がかかる可能性がある

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

削除対象となるデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | GroupManager.ts | `src/node/db/GroupManager.ts` | group構造（pads, mappings）とgroup2sessions構造 |

**読解のコツ**: グループは複数のデータ構造と関連している：`group:{groupID}`（本体）、`groups`（一覧）、`group2sessions:{groupID}`（セッション関連）、`mapper2group:{mapper}`（マッピング逆引き）。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RestAPI.ts | `src/node/handler/RestAPI.ts` | DELETE /groups のルーティング |
| 2-2 | APIHandler.ts | `src/node/handler/APIHandler.ts` | deleteGroupパラメータ定義 |

**主要処理フロー**:
1. **363-379行目（RestAPI.ts）**: DELETE /groups のルーティング定義
2. **38行目（APIHandler.ts）**: `deleteGroup: ['groupID']` パラメータ定義

#### Step 3: コアロジックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | API.ts | `src/node/db/API.ts` | deleteGroup関数のエクスポート |
| 3-2 | GroupManager.ts | `src/node/db/GroupManager.ts` | deleteGroup関数の実装 |

**主要処理フロー**:
- **47行目（API.ts）**: `exports.deleteGroup = groupManager.deleteGroup;`
- **45-78行目（GroupManager.ts）**: deleteGroup関数の実装
  - **46-52行目**: グループ存在確認
  - **55-58行目**: 全パッド削除（Promise.all）
  - **62-65行目**: 全セッション削除（Promise.all）
  - **67-74行目**: 関連レコード削除（Promise.all）
  - **77行目**: グループ本体削除

#### Step 4: 関連処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Pad.ts | `src/node/db/Pad.ts` | pad.remove()の実装 |
| 4-2 | SessionManager.ts | `src/node/db/SessionManager.ts` | sessionManager.deleteSession()の実装 |

### プログラム呼び出し階層図

```
DELETE /api/2/groups (RestAPI.ts)
    │
    ├─ APIHandler.handle() (APIHandler.ts:161)
    │      │
    │      ├─ 認証検証 (APIHandler.ts:175-200)
    │      │
    │      └─ api.deleteGroup(groupID) (API.ts:47)
    │              │
    │              └─ groupManager.deleteGroup() (GroupManager.ts:45)
    │                      │
    │                      ├─ db.get(`group:${groupID}`) [存在確認]
    │                      │
    │                      ├─ Promise.all: padManager.getPad() → pad.remove()
    │                      │      └─ Pad.remove() (Pad.ts:557)
    │                      │
    │                      ├─ Promise.all: sessionManager.deleteSession()
    │                      │
    │                      └─ Promise.all:
    │                              ├─ db.remove(`group2sessions:${groupID}`)
    │                              ├─ db.setSub('groups', [groupID], undefined)
    │                              └─ db.remove(`mapper2group:${m}`)
    │                      │
    │                      └─ db.remove(`group:${groupID}`)
    │
    └─ Response: {code: 0, message: "ok", data: null}
```

### データフロー図

```
[入力]               [処理]                              [出力]

HTTP DELETE     ─────▶ RestAPI.ts
/api/2/groups          ルーティング
                           │
groupID         ─────▶ APIHandler.ts
apikey/token           認証・パラメータ抽出
                           │
                       GroupManager.ts
                       │
                       ├─ db.get(group:xxx) [存在確認]
                       │
                       ├─ [並列] pad.remove() × N
                       │
                       ├─ [並列] sessionManager.deleteSession() × M
                       │
                       ├─ [並列] 関連レコード削除
                       │
                       └─ db.remove(group:xxx)
                           │
                           ▼
                       {data: null} ─────▶ JSON Response
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| RestAPI.ts | `src/node/handler/RestAPI.ts` | ソース | APIルーティング定義 |
| APIHandler.ts | `src/node/handler/APIHandler.ts` | ソース | API認証・パラメータ処理 |
| API.ts | `src/node/db/API.ts` | ソース | API関数エクスポート |
| GroupManager.ts | `src/node/db/GroupManager.ts` | ソース | グループ管理コアロジック |
| Pad.ts | `src/node/db/Pad.ts` | ソース | パッド削除処理 |
| SessionManager.ts | `src/node/db/SessionManager.ts` | ソース | セッション削除処理 |
| PadManager.ts | `src/node/db/PadManager.ts` | ソース | パッド取得処理 |
| DB.ts | `src/node/db/DB.ts` | ソース | データベースアクセス層 |
