# 機能設計書 31-保存済みリビジョン数取得

## 概要

本ドキュメントは、Etherpadの保存済みリビジョン数取得機能（getSavedRevisionsCount）の設計仕様を記載する。

### 本機能の処理概要

本機能は、指定されたパッドに保存されたリビジョン（スナップショット）の総数を取得するAPI機能である。

**業務上の目的・背景**：パッドの編集履歴において、重要な節目となるリビジョンは「保存済みリビジョン」として明示的にマークされる。この機能は、パッドにいくつの保存済みリビジョンが存在するかを把握することで、履歴管理の状況を確認したり、タイムスライダー機能での表示制御に利用される。特に長期間運用されるパッドでは、重要な変更点を追跡するために保存済みリビジョンの数を確認することが重要となる。

**機能の利用シーン**：管理画面からパッドの履歴状態を確認する場合、タイムスライダーで保存済みリビジョンのマーカーを表示する場合、APIを通じてパッドの履歴情報を取得するアプリケーションから利用される場合など。

**主要な処理内容**：
1. パッドIDの検証（存在確認、形式チェック）
2. パッドオブジェクトの取得
3. 保存済みリビジョン配列の長さを取得
4. 結果をJSON形式で返却

**関連システム・外部連携**：REST API経由でHTTPリクエストを受け付け、JSON形式でレスポンスを返す。データベース（ueberDB2）からパッド情報を取得する。

**権限による制御**：APIキー認証またはSSO認証により、API呼び出しの認可を行う。認証されていないリクエストは拒否される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | API経由 | 主機能 | REST API呼び出しで保存済みリビジョン数を取得 |

## 機能種別

データ取得（SELECT操作）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| padID | string | Yes | 対象パッドのID | 文字列型であること、パッドが存在すること |

### 入力データソース

REST API GETリクエストのクエリパラメータとしてpadIDを受け取る。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| code | integer | 結果コード（0: 成功） |
| message | string | 結果メッセージ（"ok"） |
| data.savedRevisions | integer | 保存済みリビジョンの数 |

### 出力先

HTTPレスポンスとしてJSON形式で返却

## 処理フロー

### 処理シーケンス

```
1. APIリクエスト受信
   └─ GET /api/2/savedRevisions/revisionsCount?padID=xxx
2. 認証・認可チェック
   └─ APIキーまたはSSOトークンの検証
3. パラメータ検証
   └─ padIDが文字列であることを確認
4. パッド存在確認
   └─ padManager.doesPadExistsを呼び出し
5. パッドオブジェクト取得
   └─ padManager.getPadを呼び出し
6. 保存済みリビジョン数取得
   └─ pad.getSavedRevisionsNumber()を呼び出し
7. レスポンス生成・返却
   └─ {savedRevisions: count}形式で返却
```

### フローチャート

```mermaid
flowchart TD
    A[APIリクエスト受信] --> B{認証チェック}
    B -->|失敗| C[401 Unauthorized]
    B -->|成功| D{padID検証}
    D -->|不正| E[400 Bad Request]
    D -->|正常| F{パッド存在確認}
    F -->|存在しない| G[padID does not exist]
    F -->|存在する| H[パッドオブジェクト取得]
    H --> I[保存済みリビジョン数取得]
    I --> J[JSONレスポンス返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-31-01 | パッド存在必須 | 指定されたパッドIDが存在しない場合はエラー | 常時 |
| BR-31-02 | 認証必須 | APIキーまたはSSOによる認証が必要 | 常時 |

### 計算ロジック

保存済みリビジョン数は、PadオブジェクトのsavedRevisions配列のlengthプロパティを返却する。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| パッド情報取得 | pad:{padID} | SELECT | パッドのメタ情報を取得 |

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

#### pad:{padID}

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | savedRevisions | キー: pad:{padID} | 保存済みリビジョン配列を含むパッドデータ |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | apierror | padIDが文字列でない | 正しい形式のpadIDを指定 |
| 1 | apierror | パッドが存在しない | 存在するパッドIDを指定 |
| 4 | 認証エラー | APIキーが無効 | 正しいAPIキーを使用 |

### リトライ仕様

リトライは不要（冪等な読み取り操作のため）

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

読み取り専用操作のため、トランザクション管理は不要。

## パフォーマンス要件

- レスポンス時間: 100ms以内（通常条件下）
- パッド情報はメモリキャッシュされるため、高速なアクセスが可能

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

- APIキー認証またはSSO認証が必須
- パッドIDのバリデーションにより不正なアクセスを防止
- 読み取り専用操作のためデータ改ざんリスクなし

## 備考

API Version 1.2.11で追加された機能。

---

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

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

### 推奨読解順序

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

まず、Padオブジェクトの構造と保存済みリビジョンの管理方法を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Pad.ts | `src/node/db/Pad.ts` | savedRevisions配列の定義（49行目）とgetSavedRevisionsNumber()メソッド（77-79行目） |

**読解のコツ**: TypeScriptのクラス定義を確認し、savedRevisionsプロパティがany[]型の配列として定義されていることを理解する。

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

REST APIのエンドポイント定義を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RestAPI.ts | `src/node/handler/RestAPI.ts` | GET /savedRevisions/revisionsCountのマッピング定義（1158-1172行目） |

**主要処理フロー**:
1. **1158-1172行目**: エンドポイント定義とgetSavedRevisionsCount関数へのマッピング
2. **1434-1526行目**: リクエスト処理とAPIハンドラー呼び出し

#### Step 3: API関数の実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | API.ts | `src/node/db/API.ts` | getSavedRevisionsCount関数の実装（424-428行目） |

**主要処理フロー**:
- **424-428行目**: パッド取得とgetSavedRevisionsNumber()呼び出し

#### Step 4: Padクラスの実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | Pad.ts | `src/node/db/Pad.ts` | getSavedRevisionsNumber()メソッドの実装（77-79行目） |

**主要処理フロー**:
- **77-79行目**: savedRevisions配列のlengthを返却

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

```
RestAPI.expressCreateServer
    │
    ├─ app.use('/api/2', ...)
    │      └─ apiHandler.handle('1.2.11', 'getSavedRevisionsCount', fields)
    │              └─ API.getSavedRevisionsCount(padID)
    │                      ├─ getPadSafe(padID, true)
    │                      │      └─ padManager.getPad(padID)
    │                      └─ pad.getSavedRevisionsNumber()
    │                              └─ this.savedRevisions.length
    │
    └─ res.json(response)
```

### データフロー図

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

padID ───────────▶ getPadSafe() ───────────▶ Padオブジェクト
                           │
                           ▼
                 getSavedRevisionsNumber()
                           │
                           ▼
                 savedRevisions.length ───▶ {savedRevisions: number}
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| API.ts | `src/node/db/API.ts` | ソース | API関数の実装 |
| Pad.ts | `src/node/db/Pad.ts` | ソース | Padクラスの定義 |
| RestAPI.ts | `src/node/handler/RestAPI.ts` | ソース | REST APIエンドポイントの定義 |
| APIHandler.ts | `src/node/handler/APIHandler.ts` | ソース | API呼び出しのハンドリング |
| PadManager.ts | `src/node/db/PadManager.ts` | ソース | パッドの管理 |
