# 画面設計書 43-アプリケーション概要

## 概要

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

### 本画面の処理概要

この画面は、選択されたFlinkアプリケーションに所属するジョブの一覧を表示する。実行中ジョブと完了済みジョブを別々のリストで表示し、各ジョブの詳細画面への遷移機能を提供する。アプリケーション詳細画面のOverviewタブとして機能する。

**業務上の目的・背景**：Flinkアプリケーションは複数のジョブを包含する上位概念であり、本画面はアプリケーション内の全ジョブの状態を俯瞰的に把握するために使用される。ストリーミングパイプラインの運用では、特定のアプリケーション内でどのジョブが正常に動作しているか、どのジョブが失敗または完了しているかを迅速に確認することが重要である。

**画面へのアクセス方法**：アプリケーション詳細画面の「Overview」タブをクリックするか、URLで直接 `/application/running/:id/overview` または `/application/completed/:id/overview` にアクセスする。アプリケーション詳細画面を開いた際のデフォルト表示画面でもある。

**主要な操作・処理内容**：
1. アプリケーションに所属するジョブ一覧の取得と表示
2. 実行中ジョブ（Running Job List）と完了済みジョブ（Completed Job List）の分離表示
3. 各ジョブのJob Name、Start Time、Duration、End Time、Tasks、Statusの表示
4. ジョブ行クリックによるジョブ詳細画面への遷移

**画面遷移**：
- 遷移元：アプリケーション詳細画面（タブナビゲーション）
- 遷移先：ジョブ詳細画面（`/job/running/:jid` または `/job/completed/:jid`）

**権限による表示制御**：本画面には特別な権限制御は実装されていない。全ユーザーが同一の内容を閲覧できる。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 32 | REST API | 主機能 | アプリケーション概要情報の取得・表示 |
| 23 | ジョブ管理 | 補助機能 | アプリケーションに属するジョブの状態統計表示 |

## 画面種別

一覧（詳細画面内タブ）

## URL/ルーティング

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

## 入出力項目

### 入力項目

本画面は`ApplicationLocalService`を通じて親コンポーネント（アプリケーション詳細）からデータを受け取る。直接の入力項目は存在しない。

### 出力項目（表示データ）

| 項目名 | 型 | 説明 |
|--------|-----|------|
| jobs | JobsItem[] | アプリケーションに所属するジョブ一覧 |

## 表示項目

### Running Job List（実行中ジョブ一覧）

| 項目名 | 表示名 | データ型 | ソート | 説明 |
|--------|--------|----------|--------|------|
| name | Job Name | string | 可（文字列比較） | ジョブ名（幅40%） |
| start-time | Start Time | number | 可（数値比較） | 開始時刻（yyyy-MM-dd HH:mm:ss.SSS形式で表示） |
| duration | Duration | number | 可（数値比較） | 実行時間（humanizeDurationパイプで変換） |
| end-time | End Time | number | 可（数値比較） | 終了時刻（yyyy-MM-dd HH:mm:ss.SSS形式で表示） |
| tasks | Tasks | TaskStatus | 不可 | タスク状態バッジ（各ステータスの件数表示） |
| state | Status | string | 可（文字列比較） | ジョブ状態バッジ（RUNNING, CREATED等） |

### Completed Job List（完了済みジョブ一覧）

Running Job Listと同一のカラム構成。フィルタ条件としてcompletedフラグがtrueのジョブのみを表示する。

## イベント仕様

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

ApplicationLocalServiceからアプリケーション詳細データを購読し、ジョブ一覧を抽出する。

**処理フロー**:
1. `applicationLocalService.applicationDetailChanges()`を購読
2. `map(data => data.jobs)`でジョブ配列を抽出
3. `shareReplay()`でObservableを共有化
4. `jobData$`として`flink-job-list`コンポーネントに渡す

### 2-ジョブ行クリック（実行中ジョブ）

ユーザーが実行中ジョブ一覧のジョブ行をクリックすると、該当ジョブの詳細画面へ遷移する。

**処理フロー**:
1. `flink-job-list`コンポーネントの`(navigate)`イベントが発火
2. `navigateToJob(['job', 'running', $event.jid])`が呼び出される
3. `Router.navigate()` により `/job/running/:jid` へ遷移
4. ジョブ詳細画面が表示される

### 3-ジョブ行クリック（完了済みジョブ）

ユーザーが完了済みジョブ一覧のジョブ行をクリックすると、該当ジョブの詳細画面へ遷移する。

**処理フロー**:
1. `flink-job-list`コンポーネントの`(navigate)`イベントが発火
2. `navigateToJob(['job', 'completed', $event.jid])`が呼び出される
3. `Router.navigate()` により `/job/completed/:jid` へ遷移
4. ジョブ詳細画面が表示される

### 4-INITIALIZINGステータスのジョブクリック

ジョブがINITIALIZING状態の場合、遷移せずにメッセージを表示する。

**処理フロー**:
1. ジョブ行クリック
2. `job.state === 'INITIALIZING'`を判定
3. `nzMessageService.info()`でメッセージを表示
4. 画面遷移は行わない

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

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

本画面はREAD ONLYであり、データベースの更新は行わない。

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| 画面表示 | - | SELECT | ApplicationLocalServiceからキャッシュされたデータを取得（API直接呼び出しなし） |

## メッセージ仕様

| メッセージID | 種別 | メッセージ内容 | 表示条件 |
|-------------|------|--------------|----------|
| M-01 | 情報 | Job detail page is not available while it is in state INITIALIZING. | INITIALIZINGステータスのジョブをクリック時 |

## 例外処理

| 例外条件 | 表示内容 | 処理 |
|----------|---------|------|
| ジョブが0件 | 空のテーブル | テーブル本体のみ表示（エラーメッセージなし） |
| データ取得前 | スケルトンローダー | JobListComponent内のisLoadingによるローディング表示 |

## 備考

- 本画面は`flink-job-list`コンポーネントを2つ使用して、実行中ジョブと完了済みジョブを分離表示している
- ジョブデータは親コンポーネント（アプリケーション詳細）が取得したApplicationDetailの`jobs`配列を使用する
- `shareReplay({ bufferSize: 1, refCount: true })`により、複数の`flink-job-list`コンポーネントが同一のObservableを効率的に共有する
- ジョブの`completed`フラグは、アプリケーションサービスのloadApplication()内で設定される（stateがFINISHED/FAILED/CANCELEDの場合にtrue）

---

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

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

### 推奨読解順序

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

まず、表示するジョブデータの構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | job-overview.ts | `flink-runtime-web/web-dashboard/src/app/interfaces/job-overview.ts` | JobsItem、TaskStatusインターフェースの定義を確認。jid, name, state, start-time, end-time, duration, tasks, completedの構造を理解する |
| 1-2 | application-detail.ts | `flink-runtime-web/web-dashboard/src/app/interfaces/application-detail.ts` | ApplicationDetailインターフェースの`jobs: JobsItem[]`プロパティを確認 |

**読解のコツ**: JobsItemインターフェースはジョブ一覧画面（No.3, No.4）と共通で使用されている。タスク状態（TaskStatus）にはPENDINGが含まれており、これはapplication.service.ts内で`pending-operators`から設定される。

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

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | routes.ts | `flink-runtime-web/web-dashboard/src/app/pages/application/overview/routes.ts` | APPLICATION_OVERVIEW_ROUTESで`ApplicationOverviewComponent`がマッピングされていることを確認 |
| 2-2 | application-overview.component.ts | `flink-runtime-web/web-dashboard/src/app/pages/application/overview/application-overview.component.ts` | ngOnInitでのデータ取得フロー、navigateToJob()メソッドを理解する |

**主要処理フロー**:
1. **行42-47**: ngOnInitでapplicationLocalService.applicationDetailChanges()を購読
2. **行45**: map(data => data.jobs)でジョブ配列を抽出
3. **行46**: shareReplay()でObservableを複数コンポーネントで共有
4. **行55-57**: navigateToJob()でRouter.navigate()を呼び出し

#### Step 3: テンプレートと子コンポーネントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | application-overview.component.html | `flink-runtime-web/web-dashboard/src/app/pages/application/overview/application-overview.component.html` | `flink-job-list`コンポーネントの使用方法、`[completed]`プロパティによるフィルタリング、`(navigate)`イベントハンドリングを確認 |
| 3-2 | job-list.component.ts | `flink-runtime-web/web-dashboard/src/app/components/job-list/job-list.component.ts` | @Inputプロパティ（jobData$, completed, title）、ソート関数の定義、navigateToJob()でのINITIALIZING判定を理解する |
| 3-3 | job-list.component.html | `flink-runtime-web/web-dashboard/src/app/components/job-list/job-list.component.html` | テーブル構造、表示項目、クリックイベントのバインディングを確認 |

**主要処理フロー**:
- **job-list.component.ts 行79-85**: navigateToJob()でINITIALIZING判定を行い、該当時はメッセージを表示
- **job-list.component.ts 行101-105**: jobData$を購読し、completedフラグでフィルタリング

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | application-local.service.ts | `flink-runtime-web/web-dashboard/src/app/pages/application/application-local.service.ts` | ReplaySubjectによるデータ共有の仕組みを理解する。applicationDetailChanges()で購読開始 |
| 4-2 | application.service.ts | `flink-runtime-web/web-dashboard/src/app/services/application.service.ts` | loadApplication()内でジョブのcompletedフラグ設定、tasksの正規化処理を確認 |

**主要処理フロー**:
- **application.service.ts 行78-88**: ジョブごとにtasksを大文字キーに変換、PENDINGを設定、completedフラグを設定

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

```
ApplicationOverviewComponent
    │
    ├─ ngOnInit()
    │      └─ ApplicationLocalService.applicationDetailChanges()
    │              └─ map(data => data.jobs)
    │                      └─ shareReplay()
    │                              └─ jobData$ (Observable<JobsItem[]>)
    │
    └─ [テンプレート]
           │
           ├─ JobListComponent [Running Job List]
           │      │
           │      ├─ @Input() jobData$: Observable<JobsItem[]>
           │      ├─ @Input() completed = false
           │      ├─ filter(item => item.completed === false)
           │      │
           │      └─ navigateToJob()
           │              ├─ [state !== 'INITIALIZING']
           │              │      └─ @Output() navigate.emit(job)
           │              │              └─ ApplicationOverviewComponent.navigateToJob()
           │              │                      └─ Router.navigate(['job', 'running', jid])
           │              │
           │              └─ [state === 'INITIALIZING']
           │                     └─ NzMessageService.info()
           │
           └─ JobListComponent [Completed Job List]
                  │
                  ├─ @Input() jobData$: Observable<JobsItem[]>
                  ├─ @Input() completed = true
                  ├─ filter(item => item.completed === true)
                  │
                  └─ navigateToJob()
                          └─ @Output() navigate.emit(job)
                                  └─ ApplicationOverviewComponent.navigateToJob()
                                          └─ Router.navigate(['job', 'completed', jid])
```

### データフロー図

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

ApplicationDetailComponent     ApplicationLocalService
(親コンポーネント)              (ReplaySubject)
        │                             │
        │ setApplicationDetail()      │
        ▼                             ▼
ApplicationDetail  ─────────▶ applicationDetail$              ┌────────────────┐
  ├─ id                              │                        │   JobsItem     │
  ├─ name                            │                        │   ・jid        │
  ├─ status                          │                        │   ・name       │
  └─ jobs[]  ◀─────────────────────────┘                        │   ・state      │
        │                                                      │   ・start-time │
        │ map(data => data.jobs)                               │   ・end-time   │
        ▼                                                      │   ・duration   │
ApplicationOverviewComponent                                   │   ・tasks      │
   jobData$ (Observable)                                       │   ・completed  │
        │                                                      └────────────────┘
        │ shareReplay()                                              │
        │                                                            │
   ┌────┴────┐                                                       ▼
   ▼         ▼                                               ┌──────────────────┐
JobListComponent     JobListComponent                        │  flink-job-list  │
[Running]            [Completed]                             │  (テーブル表示)   │
   │                      │                                  └──────────────────┘
   │ filter               │ filter
   │ (completed=false)    │ (completed=true)
   ▼                      ▼
実行中ジョブ表示      完了済みジョブ表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| application-overview.component.ts | `flink-runtime-web/web-dashboard/src/app/pages/application/overview/application-overview.component.ts` | ソース | メインコンポーネント |
| application-overview.component.html | `flink-runtime-web/web-dashboard/src/app/pages/application/overview/application-overview.component.html` | テンプレート | 画面テンプレート |
| routes.ts | `flink-runtime-web/web-dashboard/src/app/pages/application/overview/routes.ts` | ソース | ルーティング定義 |
| job-list.component.ts | `flink-runtime-web/web-dashboard/src/app/components/job-list/job-list.component.ts` | ソース | ジョブ一覧表示コンポーネント |
| job-list.component.html | `flink-runtime-web/web-dashboard/src/app/components/job-list/job-list.component.html` | テンプレート | ジョブ一覧テーブルのテンプレート |
| application-local.service.ts | `flink-runtime-web/web-dashboard/src/app/pages/application/application-local.service.ts` | ソース | コンポーネント間データ共有サービス |
| application.service.ts | `flink-runtime-web/web-dashboard/src/app/services/application.service.ts` | ソース | アプリケーションAPI呼び出しサービス（ジョブデータ加工） |
| job-overview.ts | `flink-runtime-web/web-dashboard/src/app/interfaces/job-overview.ts` | ソース | ジョブデータ型定義（インターフェース） |
| application-detail.ts | `flink-runtime-web/web-dashboard/src/app/interfaces/application-detail.ts` | ソース | アプリケーション詳細データ型定義 |
