# 機能設計書 2-KeySelector

## 概要

本ドキュメントは、Apache FlinkのKeySelector機能について詳細に記載する。KeySelectorはデータストリームをキーで分割するためのセレクタ機能を提供し、keyBy操作の基盤となる重要なコンポーネントである。

### 本機能の処理概要

KeySelectorは、データ要素から決定論的なキーを抽出するためのユーザー定義関数インターフェースである。このインターフェースを実装することで、reduce、reduceGroup、join、coGroup等のキーベース操作において、どのフィールドまたは計算値でデータをグルーピングするかを指定できる。

**業務上の目的・背景**：ストリーム処理やバッチ処理において、同一キーを持つデータを同じパーティションに集約することは、集計処理、ウィンドウ処理、状態管理の基本となる。KeySelectorは、POJOやTupleなどの複雑なデータ型から柔軟にキーを抽出する仕組みを提供し、型安全なキー抽出を実現する。同一オブジェクトに対して複数回呼び出した場合、常に同じキーを返す決定論的な動作が保証される必要がある。

**機能の利用シーン**：
- keyBy()操作でのストリーム分割
- ウィンドウ処理前のキー付きストリーム生成
- Join操作でのキー指定
- Reduce/Aggregate操作でのグルーピング

**主要な処理内容**：
1. 入力要素からキー値を抽出
2. 抽出したキーに基づいてパーティショニングを実行
3. 同一キーを持つ要素を同一パーティションに集約

**関連システム・外部連携**：KeySelectorはDataStream APIのkeyBy()メソッド、KeyedStream、WindowedStreamと密接に連携する。内部的にはKeyGroupRangeAssignmentによりキーグループへのマッピングが行われる。

**権限による制御**：KeySelector自体には権限制御は存在しない。

## 関連画面

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

## 機能種別

データ変換 / パーティショニング

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| value | IN（ジェネリック型） | Yes | キーを抽出する対象のデータ要素 | null許容は実装に依存 |

### 入力データソース

- DataStreamの各要素
- 上流オペレーターからの変換済みデータ

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| key | KEY（ジェネリック型） | 抽出されたキー値 |

### 出力先

- パーティショナーへ渡されハッシュベースのパーティション割り当てに使用
- KeyedStreamの内部キー管理

## 処理フロー

### 処理シーケンス

```
1. keyBy()呼び出し
   └─ KeySelectorを引数として受け取り
2. KeyedStream生成
   └─ 入力DataStreamとKeySelectorを関連付け
3. パーティショニング実行
   └─ 各要素に対してgetKey()を呼び出しキーを取得
4. キーグループ割り当て
   └─ キーのハッシュ値に基づきパーティションを決定
```

### フローチャート

```mermaid
flowchart TD
    A[DataStream] --> B[keyBy呼び出し]
    B --> C[KeySelector指定]
    C --> D[KeyedStream生成]
    D --> E{各要素処理}
    E --> F[getKey実行]
    F --> G[キー値取得]
    G --> H[ハッシュ計算]
    H --> I[パーティション割り当て]
    I --> E
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | 決定論性 | 同一オブジェクトに対して複数回呼び出した場合、同じキーを返す必要がある | 常時 |
| BR-002 | シリアライズ | KeySelectorはSerializableを実装する必要がある | 常時 |
| BR-003 | ラムダ対応 | @FunctionalInterfaceとしてラムダ式で実装可能 | Java 8以降 |

### 計算ロジック

```
getKey(IN value) -> KEY
```
入力要素からキーを抽出する単純な関数。キーの決定ロジックはユーザー実装に依存。

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

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

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Exception | getKey()内で例外発生 | タスク失敗、リカバリ処理実行 |
| - | NullPointerException | nullキーが禁止されている操作で発生 | キー抽出ロジックでnullチェック |

### リトライ仕様

Flinkのチェックポイント機構と連携し、障害時は最後のチェックポイントから再開。

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

KeySelector自体にはトランザクション機能はない。

## パフォーマンス要件

- getKey()は各要素に対して呼び出されるため、軽量な実装が求められる
- キーのハッシュ計算が均等に分散されるキー設計が推奨される

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

- KeySelectorはシリアライズされてTaskManagerに転送される

## 備考

KeySelectorはFunctionインターフェースを継承しており、Function APIのエコシステムの一部として機能する。

---

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

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

### 推奨読解順序

#### Step 1: インターフェース定義を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | KeySelector.java | `flink-core-api/src/main/java/org/apache/flink/api/java/functions/KeySelector.java` | KeySelectorインターフェースの定義、getKey()メソッドの契約 |

**読解のコツ**:
- **27-34行目**: JavaDocでの決定論性要件の説明
- **37-38行目**: @FunctionalInterfaceアノテーションとFunction継承の確認
- **41-68行目**: getKey()メソッドのJavaDocとシグネチャ

#### Step 2: 使用例を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | DataStream.java | `flink-runtime/src/main/java/org/apache/flink/streaming/api/datastream/DataStream.java` | keyBy()メソッドでのKeySelector使用パターン |

**主要処理フロー**:
- keyBy(KeySelector)メソッドがKeySelectorを受け取りKeyedStreamを生成

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

```
DataStream
    │
    └─ keyBy(KeySelector<T, K>)
           │
           ├─ KeyedStream<T, K>生成
           │       │
           │       └─ KeySelector.getKey(T) -> K
           │
           └─ KeyGroupPartitioner
                   └─ キーのハッシュによるパーティション決定
```

### データフロー図

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

DataStream<T> ───▶ KeySelector.getKey(T) ───▶ KeyedStream<T, K>
     │                     │                         │
     │                     └─ キー抽出               │
     │                                               │
     └─ 要素T                                        └─ キーKでパーティション
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| KeySelector.java | `flink-core-api/src/main/java/org/apache/flink/api/java/functions/KeySelector.java` | ソース | キー抽出インターフェース定義 |
| DataStream.java | `flink-runtime/src/main/java/org/apache/flink/streaming/api/datastream/DataStream.java` | ソース | keyBy()メソッドの提供 |
| KeyedStream.java | `flink-runtime/src/main/java/org/apache/flink/streaming/api/datastream/KeyedStream.java` | ソース | キー付きストリームの実装 |
| KeySelectorUtil.java | `flink-streaming-java/src/main/java/org/apache/flink/streaming/util/keys/KeySelectorUtil.java` | ソース | KeySelectorユーティリティ |
