# 画面設計書 42-アプリケーション詳細

## 概要

本ドキュメントは、Apache Flink Web Dashboard におけるアプリケーション詳細画面の設計を定義する。

### 本画面の処理概要

この画面は、選択されたFlinkアプリケーションの詳細情報を表示するコンテナ画面であり、アプリケーションのステータス情報、基本メタデータ、およびタブナビゲーションを提供する。配下の子画面（概要タブなど）を表示するための親フレームとして機能する。

**業務上の目的・背景**：アプリケーションレベルでのモニタリングは、複数のジョブをグループ化して管理するFlinkアプリケーションモードにおいて重要である。この画面により、アプリケーション全体の状態を一目で把握し、問題が発生した際には迅速にキャンセル操作を行ったり、関連するJobManagerログへアクセスしたりすることができる。

**画面へのアクセス方法**：実行中アプリケーション一覧または完了済みアプリケーション一覧から、対象アプリケーションの行をクリックすることでアクセスする。URLは `/application/running/:id` または `/application/completed/:id` の形式となる。

**主要な操作・処理内容**：
1. アプリケーション詳細情報のREST API経由での取得と表示
2. アプリケーションID、状態、開始時刻、終了時刻、実行時間の表示
3. ジョブ状態の集計バッジ表示
4. アプリケーションキャンセル操作（実行中のみ、web-cancel機能有効時）
5. JobManagerログへのリンク表示（History Serverモード以外）
6. タブナビゲーション（Overview等）による子画面への遷移

**画面遷移**：
- 遷移元：実行中アプリケーション一覧、完了済みアプリケーション一覧
- 遷移先：アプリケーション概要（Overviewタブ）、JobManagerログ

**権限による表示制御**：
- **アプリケーションキャンセルボタン**：`web-cancel`機能が有効で、かつアプリケーション状態がRUNNINGまたはCREATEDの場合のみ表示
- **JobManagerログリンク**：`web-history`機能が無効（通常モード）の場合のみ表示

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 32 | REST API | 主機能 | アプリケーション詳細情報の取得（/applications/:applicationid API） |
| 23 | ジョブ管理 | 補助機能 | アプリケーションのキャンセル操作、ジョブ一覧表示 |

## 画面種別

詳細（コンテナ）

## URL/ルーティング

- 実行中アプリケーション: `/application/running/:id`
- 完了済みアプリケーション: `/application/completed/:id`
- ルート定義: `RUNNING_APPLICATION_ROUTES` / `COMPLETED_APPLICATION_ROUES` -> `ApplicationDetailComponent`

## 入出力項目

### 入力項目（URL パラメータ）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | string | アプリケーションID（URL パスパラメータ） |

### 出力項目（API レスポンス）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | string | アプリケーションID |
| name | string | アプリケーション名 |
| status | string | アプリケーション状態 |
| start-time | number | 開始時刻（UNIX時間ミリ秒） |
| end-time | number | 終了時刻（UNIX時間ミリ秒、未終了時は-1） |
| duration | number | 実行時間（ミリ秒） |
| timestamps | TimestampsStatus | 各状態への遷移時刻 |
| jobs | JobsItem[] | 所属ジョブ一覧 |
| status-counts | JobStatus | ジョブ状態の集計 |

## 表示項目

### ヘッダー情報（nz-descriptions）

| 項目名 | 表示名 | データ型 | 説明 |
|--------|--------|----------|------|
| id | Application ID | string | アプリケーションの一意識別子 |
| status | Application State | string | アプリケーション状態バッジとジョブ状態バッジを表示 |
| actions | Actions | - | JobManagerログへのリンク（History Server以外） |
| start-time | Start Time | number | 開始時刻（yyyy-MM-dd HH:mm:ss.SSS形式） |
| end-time | End Time | number | 終了時刻（yyyy-MM-dd HH:mm:ss.SSS形式、-1より大きい場合のみ表示） |
| duration | Duration | number | 実行時間（humanizeDurationパイプで変換） |

### 操作エリア（extraTpl）

| 項目名 | 表示条件 | 説明 |
|--------|----------|------|
| Cancel Application | webCancelEnabled && (status === 'RUNNING' \|\| status === 'CREATED') | キャンセル確認ダイアログ付きリンク |
| statusTips | キャンセル操作後 | 「Cancelling...」等のステータスメッセージ |

### タブナビゲーション

| タブ名 | パス | 説明 |
|--------|------|------|
| Overview | overview | アプリケーション概要画面へ |

## イベント仕様

### 1-画面初期化（ngOnInit）

StatusServiceの`refresh$`をサブスクライブし、アプリケーション詳細を定期的に取得する。

**処理フロー**:
1. `statusService.refresh$`の購読開始
2. `applicationService.loadApplication(id)`を呼び出し
3. レスポンスを`applicationLocalService.setApplicationDetail()`で保存
4. `isLoading`をfalseに設定

### 2-アプリケーションキャンセル（cancelApplication）

確認ダイアログで「Yes」を選択した場合、アプリケーションをキャンセルする。

**処理フロー**:
1. `nz-popconfirm`で確認ダイアログを表示
2. 「Yes」選択で`cancelApplication()`メソッドを呼び出し
3. `applicationService.cancelApplication(id)`でAPIを呼び出し
4. `statusTips`に'Cancelling...'を設定

### 3-タブ遷移

ナビゲーションコンポーネントでタブをクリックすると、対応する子ルートへ遷移する。

**処理フロー**:
1. `flink-navigation`コンポーネントでタブをクリック
2. `router-outlet`で対応する子コンポーネントが表示される

### 4-JobManagerログへの遷移

「Job Manager Log」リンクをクリックすると、JobManagerログ画面へ遷移する。

**処理フロー**:
1. `[routerLink]="['/job-manager', 'logs']"`で遷移
2. クエリパラメータは保持される

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示・リフレッシュ | - | SELECT | REST API経由でアプリケーション詳細情報を取得 |
| キャンセル操作 | - | UPDATE | REST API経由でアプリケーションのキャンセルリクエストを送信 |

### API呼び出し詳細

#### アプリケーション詳細取得
- エンドポイント: `GET /applications/:applicationid`
- レスポンス加工:
  - `status-counts`の計算（各ジョブのstateを集計）
  - ジョブの`tasks`キーを大文字に変換
  - ジョブの`completed`フラグを設定

#### アプリケーションキャンセル
- エンドポイント: `POST /applications/:applicationid/cancel`
- リクエストボディ: 空オブジェクト `{}`

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|----------|
| M-01 | 確認 | Cancel Application? | キャンセルリンククリック時（popconfirm） |
| M-02 | 情報 | Cancelling... | キャンセル操作実行後 |
| M-03 | エラー | Application failed during initialization | API取得エラー時 |

## 例外処理

| 例外条件 | 表示内容 | 処理 |
|----------|---------|------|
| API通信エラー | 「Application failed during initialization」警告アラート | `isError`フラグをtrueに設定、`nz-alert`でエラー表示 |
| ローディング中 | スケルトンローダー表示 | `isLoading`がtrueの間、`nz-skeleton`を表示 |

## 備考

- 本画面は`ApplicationLocalService`を使用して、アプリケーション詳細データを子コンポーネント（アプリケーション概要など）と共有する
- 実行中アプリケーションの場合、`RunningApplicationGuard`がルートガードとして設定されている
- タブナビゲーションのデフォルト構成は`APPLICATION_MODULE_DEFAULT_CONFIG`で定義されており、カスタマイズ可能
- History Serverモード（`web-history`機能有効時）では、JobManagerログへのリンクは表示されない

---

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

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

### 推奨読解順序

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

まず、APIレスポンスとして受け取るデータ構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | application-detail.ts | `flink-runtime-web/web-dashboard/src/app/interfaces/application-detail.ts` | ApplicationDetailインターフェースの定義を確認。id, name, status, start-time, end-time, duration, timestamps, jobs, status-countsの構造を理解する |
| 1-2 | job-overview.ts | `flink-runtime-web/web-dashboard/src/app/interfaces/job-overview.ts` | JobsItemインターフェースを確認。アプリケーションに紐づくジョブの構造を理解する |

**読解のコツ**: ApplicationDetailはJobsItem[]を含むネスト構造になっている。ジョブ単位の詳細情報もこのAPIで一括取得される。

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

処理の起点となるルーティングとコンポーネントを特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | routes.ts (running) | `flink-runtime-web/web-dashboard/src/app/pages/application/modules/running-application/routes.ts` | RUNNING_APPLICATION_ROUTESで`ApplicationDetailComponent`がマッピングされていることを確認。`RunningApplicationGuard`が設定されている |
| 2-2 | routes.ts (completed) | `flink-runtime-web/web-dashboard/src/app/pages/application/modules/completed-application/routes.ts` | COMPLETED_APPLICATION_ROUESで`ApplicationDetailComponent`がマッピングされていることを確認。ガードなし |
| 2-3 | application-detail.component.ts | `flink-runtime-web/web-dashboard/src/app/pages/application/application-detail/application-detail.component.ts` | ngOnInitでの初期化処理、statusService.refresh$の購読、applicationService.loadApplication()の呼び出しを理解する |

**主要処理フロー**:
1. **行53-75**: ngOnInitでstatusService.refresh$を購読
2. **行58**: activatedRoute.snapshot.params['id']でURLからアプリケーションIDを取得
3. **行60**: applicationLocalService.setApplicationDetail()でデータを子コンポーネントと共有

#### Step 3: ステータス表示コンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | application-status.component.ts | `flink-runtime-web/web-dashboard/src/app/pages/application/application-detail/status/application-status.component.ts` | ステータス表示ロジック、キャンセル処理、ナビゲーション設定を理解する |
| 3-2 | application-status.component.html | `flink-runtime-web/web-dashboard/src/app/pages/application/application-detail/status/application-status.component.html` | nz-descriptionsによる情報表示、キャンセルボタンの条件付き表示、タブナビゲーションの配置を確認 |

**主要処理フロー**:
- **行68-69**: webCancelEnabled、isHistoryServerフラグの設定
- **行83-98**: ngOnInitでapplicationLocalService.applicationDetailChanges()を購読
- **行106-110**: cancelApplication()でキャンセルAPIを呼び出し

#### Step 4: サービス層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | application.service.ts | `flink-runtime-web/web-dashboard/src/app/services/application.service.ts` | loadApplication()とcancelApplication()メソッドを理解する |
| 4-2 | application-local.service.ts | `flink-runtime-web/web-dashboard/src/app/pages/application/application-local.service.ts` | ReplaySubjectを使ったデータ共有の仕組みを理解する |

**主要処理フロー**:
- **application.service.ts 行61-94**: loadApplication()でAPI呼び出しとレスポンス加工
- **application.service.ts 行40-42**: cancelApplication()でキャンセルAPI呼び出し
- **application-local.service.ts 行27-35**: ReplaySubjectによるデータ共有

#### Step 5: 設定を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | application.config.ts | `flink-runtime-web/web-dashboard/src/app/pages/application/application.config.ts` | APPLICATION_MODULE_DEFAULT_CONFIGでタブナビゲーション設定を確認 |

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

```
ApplicationDetailComponent (親コンテナ)
    │
    ├─ ngOnInit()
    │      └─ StatusService.refresh$
    │              └─ ApplicationService.loadApplication(id)
    │                      ├─ HttpClient.get('/applications/:id')
    │                      └─ ApplicationLocalService.setApplicationDetail()
    │
    └─ [テンプレート]
           │
           ├─ ApplicationStatusComponent (ヘッダー情報)
           │      │
           │      ├─ ApplicationLocalService.applicationDetailChanges()
           │      │      └─ 詳細データの購読・表示
           │      │
           │      ├─ cancelApplication()
           │      │      └─ ApplicationService.cancelApplication(id)
           │      │              └─ HttpClient.post('/applications/:id/cancel')
           │      │
           │      └─ NavigationComponent (タブ)
           │
           └─ <router-outlet> (子ルート)
                  └─ ApplicationOverviewComponent など
```

### データフロー図

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

URL params (:id)  ─────────▶ ApplicationDetailComponent          ┌────────────────────┐
                             │                                    │ ApplicationDetail  │
StatusService.refresh$       │                                    │ ・id               │
    (定期リフレッシュ)        ▼                                    │ ・name             │
                        ApplicationService                        │ ・status           │
                        .loadApplication(id)                      │ ・start-time       │
                             │                                    │ ・end-time         │
                             ▼                                    │ ・duration         │
GET /applications/:id  ◀─── HttpClient.get()                     │ ・jobs[]           │
    (REST API)               │                                    │ ・status-counts    │
                             ▼                                    └────────────────────┘
                        map(data => ...)                                   │
                        ・status-counts計算                                 │
                        ・tasks正規化                                       ▼
                             │                              ┌────────────────────────┐
                             ▼                              │ ApplicationLocalService │
                   ApplicationLocalService                  │ (ReplaySubject)        │
                   .setApplicationDetail()                  └────────────────────────┘
                             │                                       │
              ┌──────────────┼──────────────┐                        │
              ▼              ▼              ▼                        ▼
    ApplicationStatus   Navigation   ApplicationOverview    ┌──────────────────┐
    Component          Component    Component (子ルート)    │ nz-descriptions  │
                                                            │ (ヘッダー表示)   │
                                                            └──────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| application-detail.component.ts | `flink-runtime-web/web-dashboard/src/app/pages/application/application-detail/application-detail.component.ts` | ソース | メインコンテナコンポーネント |
| application-detail.component.html | `flink-runtime-web/web-dashboard/src/app/pages/application/application-detail/application-detail.component.html` | テンプレート | 画面テンプレート |
| application-status.component.ts | `flink-runtime-web/web-dashboard/src/app/pages/application/application-detail/status/application-status.component.ts` | ソース | ステータス表示コンポーネント |
| application-status.component.html | `flink-runtime-web/web-dashboard/src/app/pages/application/application-detail/status/application-status.component.html` | テンプレート | ステータス表示テンプレート |
| application.service.ts | `flink-runtime-web/web-dashboard/src/app/services/application.service.ts` | ソース | アプリケーションAPI呼び出しサービス |
| application-local.service.ts | `flink-runtime-web/web-dashboard/src/app/pages/application/application-local.service.ts` | ソース | コンポーネント間データ共有サービス |
| application-detail.ts | `flink-runtime-web/web-dashboard/src/app/interfaces/application-detail.ts` | ソース | データ型定義（インターフェース） |
| application.config.ts | `flink-runtime-web/web-dashboard/src/app/pages/application/application.config.ts` | ソース | モジュール設定 |
| routes.ts (running) | `flink-runtime-web/web-dashboard/src/app/pages/application/modules/running-application/routes.ts` | ソース | 実行中アプリケーションルーティング |
| routes.ts (completed) | `flink-runtime-web/web-dashboard/src/app/pages/application/modules/completed-application/routes.ts` | ソース | 完了済みアプリケーションルーティング |
