# 画面設計書 3-All Stages（全ステージ一覧）

## 概要

本ドキュメントは、Apache Spark Web UIの「All Stages（全ステージ一覧）」画面の設計書である。全ステージの進捗状況をActive/Pending/Complete/Skipped/Failedに分類して表示し、FAIRスケジューラ使用時にはPool情報も表示する。ステージのKill操作も可能。

### 本画面の処理概要

**業務上の目的・背景**：Sparkアプリケーション全体のステージ実行状況を一覧で監視するための画面である。ジョブは複数のステージに分割されて実行されるため、ジョブ単位では把握しにくい個々のステージレベルの進捗を確認する際に利用する。FAIRスケジューラ使用時には、スケジューリングプールの情報を確認し、リソース配分の妥当性を検証する用途でも使用される。

**画面へのアクセス方法**：SparkアプリケーションWeb UIのナビゲーションバーから「Stages」タブを選択してアクセスする。

**主要な操作・処理内容**：
1. ステージ数のサマリー表示（Active/Pending/Complete/Skipped/Failedの各件数）
2. FAIRスケジューラ使用時のPool一覧テーブル表示
3. Active Stages テーブルの表示（Kill操作可能）
4. Pending Stages テーブルの表示
5. Completed Stages テーブルの表示
6. Skipped Stages テーブルの表示
7. Failed Stages テーブルの表示
8. Active Stageに対するKill操作

**画面遷移**：
- この画面からの遷移先：Stage Detail（ステージ詳細）画面（ステージID選択時）、Pool Detail（プール詳細）画面（プール名選択時、FAIRスケジューラ時）
- この画面への遷移元：全画面からのナビゲーションバー経由

**権限による表示制御**：Kill操作はActive Stagesのみで有効。killEnabledかつセキュリティマネージャの権限チェックを通過したユーザーのみ操作可能。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | Spark Web UI | 主機能 | 全ステージをActive/Pending/Complete/Skipped/Failedに分類してテーブル表示する主処理 |
| 4 | タスクスケジューラ | 主機能 | 各ステージのタスク割り当て状況・進捗情報をスケジューラから取得して表示 |
| 3 | DAGスケジューラ | 補助機能 | FAIRスケジューラ使用時のプール情報（SchedulingMode）を取得して表示 |
| 95 | KVStore | API連携 | AppStatusStore経由でステージ一覧・アプリケーションサマリーを非同期取得 |

## 画面種別

一覧

## URL/ルーティング

- パス: `/stages/`
- クラス: `AllStagesPage` (WebUIPage(""))
- タブ: `StagesTab` (SparkUITab(parent, "stages"))

## 入出力項目

| 項目名 | 入出力 | 型 | 説明 |
|--------|--------|------|------|
| activeStage.page | 入力（URLパラメータ） | Int | Active Stagesテーブルのページ番号 |
| activeStage.sort | 入力（URLパラメータ） | String | Active Stagesテーブルのソートカラム名 |
| activeStage.desc | 入力（URLパラメータ） | Boolean | Active Stagesテーブルのソート順 |
| activeStage.pageSize | 入力（URLパラメータ） | Int | Active Stagesテーブルの1ページあたり表示件数 |
| completedStage.page | 入力（URLパラメータ） | Int | Completed Stagesテーブルのページ番号 |
| failedStage.page | 入力（URLパラメータ） | Int | Failed Stagesテーブルのページ番号 |
| pendingStage.page | 入力（URLパラメータ） | Int | Pending Stagesテーブルのページ番号 |
| skippedStage.page | 入力（URLパラメータ） | Int | Skipped Stagesテーブルのページ番号 |

## 表示項目

### サマリーセクション

| 項目名 | データソース | 説明 |
|--------|-------------|------|
| Active Stages | stages.count(_.status == ACTIVE) | アクティブなステージ数（リンク付き） |
| Pending Stages | stages.count(_.status == PENDING) | 保留中のステージ数 |
| Completed Stages | stages.count(_.status == COMPLETE) | 完了したステージ数（GCで削除された場合の注記付き） |
| Skipped Stages | stages.count(_.status == SKIPPED) | スキップされたステージ数 |
| Failed Stages | stages.count(_.status == FAILED) | 失敗したステージ数 |

### Pool一覧テーブル（FAIRスケジューラ時のみ）

PoolTableクラスにより表示される。SparkContextのgetAllPoolsから取得したスケジューリングプール情報を表示。

### ステージテーブル（各ステータス共通、StageTableBase）

StageTableBaseクラスにより生成される。FAIRスケジューラ使用時はプール情報カラムも追加される。

## イベント仕様

### 1-ステージID選択

ステージテーブルのステージIDリンクをクリックすると、Stage Detail（ステージ詳細）画面に遷移する。

### 2-プール名選択（FAIRスケジューラ時）

Pool一覧テーブルのプール名リンクをクリックすると、Pool Detail（プール詳細）画面に遷移する。

### 3-ステージKill操作

Active Stagesテーブルに表示される「(kill)」リンクをクリックすると、確認後にステージをキャンセルする。StagesTab.handleKillRequestが処理を担当し、SparkContext.cancelStageを呼び出す。

### 4-テーブル折りたたみ

各ステータスのステージテーブルセクションは折りたたみ可能。ヘッダーのクリックで表示/非表示を切り替える。

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| ページ表示 | KVStore (AppStatusStore) | SELECT | ステージ一覧・プール情報・アプリケーションサマリーの読み取り |
| Kill操作 | なし（RPC経由） | - | SparkContext.cancelStageによりDAGSchedulerにキャンセルリクエスト送信 |

### テーブル別更新項目詳細

本画面はデータの読み取り専用である。Kill操作はRPC経由で処理される。

## メッセージ仕様

| 種別 | メッセージ | 表示条件 |
|------|----------|----------|
| 情報 | "{numCompletedStages}, only showing {size}" | 完了ステージの表示数が実際のnumCompletedStagesと異なる場合 |

## 例外処理

特記すべき例外処理は画面レベルでは行われない。StagesTabのhandleKillRequestにおいてステージの状態チェック（ACTIVEまたはPENDING時のみKill実行）が行われる。

## 備考

- FAIRスケジューラの判定はlive UI（SparkContextが利用可能な場合）のみで行われる
- Pool情報はSparkContext.getAllPoolsから取得され、PoolData（AppStatusStore）と突合される
- Completed Stagesの件数表示は、GCで古いステージが削除された場合にnumCompletedStagesとの差異を注記する
- Failed Stagesはreverseで逆順（新しい順）に表示される（84-86行目）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | api.scala | `core/src/main/scala/org/apache/spark/status/api/v1/api.scala` | StageData, StageStatusの定義。ACTIVE/PENDING/COMPLETE/SKIPPED/FAILEDの5状態 |
| 1-2 | AppStatusStore.scala | `core/src/main/scala/org/apache/spark/status/AppStatusStore.scala` | stageList(), pool(), appSummary()のAPI |

**読解のコツ**: StageStatusはenumでACTIVE, PENDING, COMPLETE, SKIPPED, FAILEDの5値を取る。stageList(null)は全ステータスのステージを返す。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | AllStagesPage.scala | `core/src/main/scala/org/apache/spark/ui/jobs/AllStagesPage.scala` | renderメソッド（34行目）が主処理 |

**主要処理フロー**:
1. **36-40行目**: FAIRスケジューラ用のプール情報を取得。sc.getAllPoolsでSchedulableオブジェクト一覧を取得し、store.pool()でPoolDataと突合
2. **43-44行目**: 5つのStageStatusを定義
3. **46行目**: `parent.store.stageList(null)` で全ステージを取得
4. **47行目**: `parent.store.appSummary()` でアプリケーションサマリーを取得
5. **49-50行目**: 各ステータスに対してsummaryAndTableForStatusを呼び出し、サマリーとテーブルを生成
6. **59-72行目**: FAIRスケジューラの場合、Pool一覧テーブルを生成
7. **74行目**: summary + poolsDescription + tablesを結合
8. **76行目**: UIUtils.headerSparkPageでページをラップ

#### Step 3: ステータス別テーブル生成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | AllStagesPage.scala | `core/src/main/scala/org/apache/spark/ui/jobs/AllStagesPage.scala` | summaryAndTableForStatus（79行目）がステータス別にステージをフィルタし、StageTableBaseを生成 |

**主要処理フロー**:
- **84-88行目**: ステータスでフィルタ。FAILEDの場合はreverse（新しい順）
- **93行目**: killEnabledはACTIVEステータスかつparent.killEnabledの場合のみtrue
- **97-98行目**: StageTableBaseを生成
- **100-101行目**: サマリー（件数表示）とテーブルHTMLのタプルを返す

#### Step 4: Kill処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | StagesTab.scala | `core/src/main/scala/org/apache/spark/ui/jobs/StagesTab.scala` | handleKillRequest（53行目）がKillリクエストを処理。ACTIVEまたはPENDING状態のステージのみキャンセル可能 |

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

```
AllStagesPage.render(request)
    |
    +-- sc.getAllPools                       ... 全プール取得（FAIR時）
    +-- store.pool(poolName)                ... プールデータ取得
    +-- new PoolTable()                     ... プールテーブル生成
    |
    +-- store.stageList(null)               ... 全ステージ取得
    +-- store.appSummary()                  ... サマリー取得
    |
    +-- summaryAndTableForStatus()          ... ステータス別処理（5回）
    |     +-- stages.filter(_.status == status)
    |     +-- new StageTableBase()          ... テーブル生成
    |
    +-- UIUtils.headerSparkPage()           ... ページラップ

StagesTab.handleKillRequest(request)
    +-- store.lastStageAttempt(id)          ... ステージ状態確認
    +-- sc.cancelStage(id, reason)          ... ステージキャンセル
```

### データフロー図

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

HttpServletRequest ---> AllStagesPage.render()
                            |
KVStore              --> stageList(null)            --> Active/Pending/Complete/Skipped/Failed分類
                     --> appSummary()               --> 件数サマリー
SparkContext         --> getAllPools                 --> Pool一覧（FAIR時）
KVStore              --> pool(name)                 --> PoolData
                            |
                            v
                        HTML(Seq[Node])             --> ブラウザ表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| AllStagesPage.scala | `core/src/main/scala/org/apache/spark/ui/jobs/AllStagesPage.scala` | ソース | 画面のメインページクラス |
| StagesTab.scala | `core/src/main/scala/org/apache/spark/ui/jobs/StagesTab.scala` | ソース | Stagesタブ定義。Kill操作ハンドラ |
| StageTableBase.scala | `core/src/main/scala/org/apache/spark/ui/jobs/StageTableBase.scala` | ソース | ステージテーブル基底クラス |
| PoolTable.scala | `core/src/main/scala/org/apache/spark/ui/jobs/PoolTable.scala` | ソース | プール一覧テーブル |
| AppStatusStore.scala | `core/src/main/scala/org/apache/spark/status/AppStatusStore.scala` | ソース | データアクセス層 |
| api.scala | `core/src/main/scala/org/apache/spark/status/api/v1/api.scala` | ソース | データモデル定義 |
