# 機能設計書 9-ウィンドウ処理

## 概要

本ドキュメントは、Apache Flinkのウィンドウ処理機能について詳細に記載する。ウィンドウ処理は時間ベース、カウントベース、セッションベースのウィンドウ処理を提供し、ストリームデータの有限範囲での集計を実現する。

### 本機能の処理概要

ウィンドウ処理は、無限のストリームデータを有限の「ウィンドウ」に分割し、各ウィンドウ内でデータを集約する機能である。WindowAssignerはストリームの各要素を0個以上のウィンドウに割り当て、Triggerがウィンドウの発火タイミングを制御する。TumblingWindows（タンブリング）、SlidingWindows（スライディング）、SessionWindows（セッション）、GlobalWindows（グローバル）など複数のウィンドウ種別をサポートする。

**業務上の目的・背景**：ストリーム処理において、「過去1時間の売上合計」「5分ごとのアクセス数」などの時間範囲での集計は非常に一般的な要件である。ウィンドウ処理は、このような有限範囲での集計を宣言的に記述できるAPIを提供する。イベント時間（Event Time）と処理時間（Processing Time）の両方に対応し、遅延データの処理（Allowed Lateness）やサイドアウトプットによる遅延データの別処理もサポートする。

**機能の利用シーン**：
- 時間単位の集計（1時間ごとの売上、1日ごとのアクセス数）
- スライディング集計（過去1時間を5分ごとに更新）
- セッション分析（ユーザーセッションごとの行動集計）
- カウントベースの集計（100件ごとのバッチ処理）

**主要な処理内容**：
1. TumblingEventTimeWindows/TumblingProcessingTimeWindows：固定長の重複しないウィンドウ
2. SlidingEventTimeWindows/SlidingProcessingTimeWindows：固定長の重複するウィンドウ
3. EventTimeSessionWindows/ProcessingTimeSessionWindows：アクティビティベースの動的ウィンドウ
4. GlobalWindows：全要素を1つのウィンドウに集約
5. Trigger：ウィンドウの発火条件

**関連システム・外部連携**：WindowOperatorとして実装され、タイマーサービス、ステートバックエンドと連携する。Watermarkと連動してイベント時間ウィンドウの完了を検知する。

**権限による制御**：ウィンドウ処理自体には権限制御は存在しない。

## 関連画面

本機能はバックエンドのデータ処理機能であり、直接関連する画面は存在しない。

## 機能種別

集計処理 / 時系列処理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| size | Duration | Yes | ウィンドウサイズ | > 0 |
| slide | Duration | Slidingのみ | スライド間隔 | > 0 |
| offset | Duration | No | ウィンドウオフセット | abs(offset) < size |
| gap | Duration | Sessionのみ | セッションギャップ | > 0 |

### 入力データソース

- KeyedStreamからのウィンドウ化
- DataStreamからの全ウィンドウ化（非推奨）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| WindowedStream | WindowedStream | ウィンドウ化されたストリーム |
| 集計結果 | DataStream<R> | reduce/aggregate/apply後の結果 |

### 出力先

- 下流オペレーター

## 処理フロー

### 処理シーケンス

```
1. ウィンドウ指定
   └─ keyBy().window(WindowAssigner)でウィンドウ化
2. 要素割り当て
   └─ assignWindows()で要素をウィンドウに割り当て
3. トリガー評価
   └─ Triggerで発火条件を評価
4. ウィンドウ関数実行
   └─ reduce/aggregate/applyでウィンドウ内要素を処理
5. 結果出力
   └─ 集計結果を下流に出力
```

### フローチャート

```mermaid
flowchart TD
    A[KeyedStream] --> B[window指定]
    B --> C[WindowedStream]
    C --> D{要素到着}
    D --> E[assignWindows]
    E --> F[ウィンドウに追加]
    F --> G{Trigger評価}
    G -->|発火| H[WindowFunction実行]
    G -->|待機| D
    H --> I[結果出力]
    I --> D
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | オフセット制約 | abs(offset) < size | Tumbling/Sliding |
| BR-002 | イベント時間ウィンドウ | Watermarkでウィンドウ完了を判定 | isEventTime() == true |
| BR-003 | 処理時間ウィンドウ | システム時刻でウィンドウ完了を判定 | isEventTime() == false |

### 計算ロジック

**ウィンドウ開始時刻計算（Tumbling）**：
```
start = timestamp - ((timestamp - offset) % size)
end = start + size
```

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

本機能は直接データベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | RuntimeException | タイムスタンプがLong.MIN_VALUE | assignTimestampsAndWatermarks()を設定 |
| - | IllegalArgumentException | abs(offset) >= size | パラメータを修正 |

### リトライ仕様

チェックポイントが有効な場合、障害時は最後のチェックポイントから再実行。

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

ウィンドウ処理自体にはトランザクション機能はない。チェックポイントと連携してExactly-once保証。

## パフォーマンス要件

- ウィンドウステートはステートバックエンドに保持
- 大量のウィンドウはメモリ消費に注意

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

特になし。

## 備考

WindowAssignerは@PublicEvolvingアノテーションが付与されている。

---

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

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

### 推奨読解順序

#### Step 1: 基本クラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | WindowAssigner.java | `flink-runtime/src/main/java/org/apache/flink/streaming/api/windowing/assigners/WindowAssigner.java` | ウィンドウ割り当ての抽象クラス |

**読解のコツ**:
- **30-37行目**: JavaDocでWindowAssignerの役割を理解
- **43行目**: @PublicEvolvingアノテーションと抽象クラス定義
- **53-54行目**: assignWindows()抽象メソッド
- **65行目**: getDefaultTrigger()抽象メソッド
- **71行目**: getWindowSerializer()抽象メソッド
- **77行目**: isEventTime()抽象メソッド

#### Step 2: Tumblingウィンドウを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | TumblingEventTimeWindows.java | `flink-runtime/src/main/java/org/apache/flink/streaming/api/windowing/assigners/TumblingEventTimeWindows.java` | タンブリングウィンドウ実装 |

**主要処理フロー**:
- **46行目**: WindowAssigner<Object, TimeWindow>を継承
- **49-52行目**: size, globalOffset, staggerOffset フィールド
- **57-66行目**: コンストラクタでのパラメータ検証
- **68-86行目**: assignWindows()の実装
- **89-91行目**: getDefaultTrigger()でEventTimeTriggerを返却
- **105-107行目**: of(Duration)ファクトリメソッド

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

```
KeyedStream
    │
    └─ window(WindowAssigner)
           │
           └─ WindowedStream
                  │
                  ├─ assignWindows(element, timestamp, context)
                  │       └─ TimeWindow生成
                  │
                  ├─ Trigger.onElement() / onProcessingTime() / onEventTime()
                  │
                  └─ reduce() / aggregate() / apply()
                         └─ WindowFunction実行
                                └─ 結果出力
```

### データフロー図

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

KeyedStream<T, K> ─▶ window(Assigner) ───▶ WindowedStream
     │                      │                     │
     │                      ▼                     │
     │            assignWindows()                 │
     │                      │                     │
     │                      ▼                     │
     │            Trigger評価                     │
     │                      │                     │
     │                      ▼                     │
     └──────────▶ WindowFunction ─────────▶ DataStream<R>
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| WindowAssigner.java | `flink-runtime/src/main/java/org/apache/flink/streaming/api/windowing/assigners/WindowAssigner.java` | ソース | 抽象ウィンドウ割り当て |
| TumblingEventTimeWindows.java | `flink-runtime/src/main/java/org/apache/flink/streaming/api/windowing/assigners/TumblingEventTimeWindows.java` | ソース | タンブリングウィンドウ |
| SlidingEventTimeWindows.java | `flink-runtime/src/main/java/org/apache/flink/streaming/api/windowing/assigners/SlidingEventTimeWindows.java` | ソース | スライディングウィンドウ |
| EventTimeSessionWindows.java | `flink-streaming-java/src/main/java/org/apache/flink/streaming/api/windowing/assigners/EventTimeSessionWindows.java` | ソース | セッションウィンドウ |
| GlobalWindows.java | `flink-runtime/src/main/java/org/apache/flink/streaming/api/windowing/assigners/GlobalWindows.java` | ソース | グローバルウィンドウ |
| TimeWindow.java | `flink-runtime/src/main/java/org/apache/flink/streaming/api/windowing/windows/TimeWindow.java` | ソース | 時間ウィンドウ |
| Trigger.java | `flink-runtime/src/main/java/org/apache/flink/streaming/api/windowing/triggers/Trigger.java` | ソース | トリガー基底 |
| EventTimeTrigger.java | `flink-runtime/src/main/java/org/apache/flink/streaming/api/windowing/triggers/EventTimeTrigger.java` | ソース | イベント時間トリガー |
| WindowedStream.java | `flink-streaming-java/src/main/java/org/apache/flink/streaming/api/datastream/WindowedStream.java` | ソース | ウィンドウ化ストリーム |
