# バッチ設計書 24-pyspark

## 概要

本ドキュメントは、PySpark対話シェルを起動するクライアントスクリプト `bin/pyspark` の設計を記述する。本スクリプトはPython環境を設定した上でspark-submitを経由し、PySpark REPLをユーザーに提供する。

### 本バッチの処理概要

pysparkは、Python言語でSparkをインタラクティブに操作するための対話シェルを起動するスクリプトである。Python実行環境の設定、JAVA_HOMEの検出（未設定時のJDKインストール提案を含む）、PYTHONPATHの構築、Spark Connectモードの自動判定、そしてspark-submit経由でのPySpark REPL起動という一連の処理を行う。

**業務上の目的・背景**：Pythonを主要言語とするデータサイエンティストやMLエンジニアが、Sparkクラスタ上でPythonコードをインタラクティブに実行するための環境を提供する。IPython/Jupyter Notebookとの連携もサポートしており、データ分析ワークフローの中核的なツールとして機能する。

**バッチの実行タイミング**：ユーザーがPythonベースのSpark対話環境を必要とする際に手動で実行する。

**主要な処理内容**：
1. SPARK_HOMEの検出とspark-env.shの読み込み
2. 廃止済み環境変数（IPYTHON, IPYTHON_OPTS）の検出とエラー報告
3. Python実行環境の設定（PYSPARK_PYTHON, PYSPARK_DRIVER_PYTHON）
4. JAVA_HOMEの検出（未設定時はJDK 17のインストールを対話的に提案）
5. PYTHONPATHの設定（PySparkモジュールとpy4jライブラリ）
6. PYTHONSTARTUPの設定（shell.pyを自動読み込み）
7. SPARK_CONNECT_MODEの自動判定
8. spark-submitでpyspark-shell-mainを起動

**前後の処理との関連**：find-spark-homeおよびload-spark-env.shが前提。内部でspark-submitを呼び出す。PYSPARK_DRIVER_PYTHONでIPythonやJupyter Notebookを指定可能。

**影響範囲**：PYTHONPATH、PYTHONSTARTUP、PYSPARK_PYTHON等の環境変数を設定する。spark-submitを介してSparkクラスタに接続する。JAVA_HOME未設定時はJDKのインストールを行う可能性がある。

## バッチ種別

クライアント実行（Python対話型シェル起動）

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時 |
| 実行時刻 | 任意 |
| 実行曜日 | 該当なし |
| 実行日 | 該当なし |
| トリガー | 手動 |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| SPARK_HOME | 設定済み、またはfind-spark-homeで検出可能であること |
| Python3 | python3コマンドが利用可能であること（またはPYSPARK_PYTHONで指定） |
| Javaランタイム | JAVA_HOMEが設定済み、javaがPATHにあること、またはJDKインストールを許可 |
| IPYTHON/IPYTHON_OPTSが未設定 | Spark 2.0+で廃止されたオプションが設定されていないこと |

### 実行可否判定

1. IPYTHON または IPYTHON_OPTS が設定されている場合、エラーメッセージを出力してexit 1
2. JAVA_HOMEが未設定かつjavaコマンドが見つからない場合、JDK 17のインストールを対話的に提案。拒否された場合はexit 1
3. SPARK_CONNECT_MODEの判定が不正値の場合、警告を出力しSPARK_CONNECT_MODEをunset

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| options | String[] | No | なし | spark-submitに渡すオプション |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| find-spark-home | シェルスクリプト | SPARK_HOMEの検出 |
| load-spark-env.sh | シェルスクリプト | Spark環境変数の読み込み |
| spark-submit | シェルスクリプト | アプリケーション投入の基盤 |
| pyspark/shell.py | Pythonスクリプト | PySpark REPL初期化スクリプト |
| py4j-0.10.9.9-src.zip | Pythonライブラリ | Java-Python通信ライブラリ |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| 標準出力 | テキスト | Python REPLのプロンプトと実行結果 |
| 標準エラー出力 | テキスト | エラーメッセージ・ログ |

### 出力ファイル仕様

本スクリプトはファイル出力を行わない（JDKインストール時は一時ディレクトリにインストールされる）。

## 処理フロー

### 処理シーケンス

```
1. SPARK_HOME検出
   └─ SPARK_HOMEが未設定の場合、find-spark-homeをsource
2. spark-env.sh読み込み
   └─ load-spark-env.shをsource
3. 廃止済みオプション検証
   └─ IPYTHONまたはIPYTHON_OPTSが設定されている場合、エラー終了
4. Python実行環境設定
   └─ PYSPARK_PYTHON: デフォルトpython3
   └─ PYSPARK_DRIVER_PYTHON: デフォルトPYSPARK_PYTHONと同値
5. JAVA_HOME検出
   └─ JAVA_HOME設定済み → RUNNER設定
   └─ javaコマンド存在 → RUNNER設定
   └─ どちらもなし → JDK 17インストール提案（対話式Y/N）
6. PYTHONPATH設定
   └─ ${SPARK_HOME}/python/ を追加
   └─ ${SPARK_HOME}/python/lib/py4j-0.10.9.9-src.zip を追加
7. PYTHONSTARTUP設定
   └─ 既存のPYTHONSTARTUPをOLD_PYTHONSTARTUPに退避
   └─ pyspark/shell.pyを設定
8. SPARK_CONNECT_MODE判定
   └─ pyspark.util.spark_connect_mode()をPythonで実行して判定
   └─ 0でも1でもない場合は警告してunset
9. テスト環境分岐
   └─ SPARK_TESTINGが設定されている場合、Python直接実行（-m オプション）
10. spark-submit実行
    └─ exec spark-submit pyspark-shell-main --name "PySparkShell"
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[SPARK_HOME検出]
    B --> C[load-spark-env.sh読み込み]
    C --> D{IPYTHON/IPYTHON_OPTS設定?}
    D -->|Yes| E[エラー終了 exit 1]
    D -->|No| F[Python実行環境設定]
    F --> G{JAVA_HOME設定済み?}
    G -->|Yes| H[RUNNER設定]
    G -->|No| I{javaコマンド存在?}
    I -->|Yes| H
    I -->|No| J{JDKインストール許可?}
    J -->|Yes| K[JDK 17インストール]
    J -->|No| L[エラー終了 exit 1]
    K --> H
    H --> M[PYTHONPATH設定]
    M --> N[PYTHONSTARTUP設定]
    N --> O[SPARK_CONNECT_MODE判定]
    O --> P{SPARK_TESTING?}
    P -->|Yes| Q[Python直接実行]
    P -->|No| R[exec spark-submit pyspark-shell-main]
    R --> S[バッチ終了]
    Q --> S
```

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

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

本スクリプト自体はデータベース操作を行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | 廃止オプションエラー | IPYTHONまたはIPYTHON_OPTSが設定されている | 環境変数をunsetし、PYSPARK_DRIVER_PYTHONを使用する |
| 1 | 環境エラー | JAVA_HOMEが未設定かつjavaが見つからずJDKインストールを拒否 | JAVA_HOMEを設定するかJDK 17以降をインストール |
| 非ゼロ | spark-submitエラー | spark-submitの実行に失敗した場合 | Java環境やクラスパスを確認 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし（対話型のためリトライ機構なし） |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし |

### 障害時対応

1. 廃止オプションエラー：`unset IPYTHON IPYTHON_OPTS` を実行し、代わりに `PYSPARK_DRIVER_PYTHON=ipython` を設定する
2. Java未検出エラー：JDKをインストールしJAVA_HOMEを設定する
3. SPARK_CONNECT_MODE判定エラー：pysparkパッケージのインストール状態を確認する

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | 該当なし |
| コミットタイミング | 該当なし |
| ロールバック条件 | 該当なし |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 対話型のため該当なし |
| 目標処理時間 | 起動時間は数秒〜十数秒。操作時間はユーザーに依存 |
| メモリ使用量上限 | spark-submitのデフォルト設定に依存 |

## 排他制御

排他制御なし。複数のpysparkインスタンスを同時に実行可能。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| Sparkログ | セッション中 | Sparkフレームワークのログ |
| JDKインストールログ | JDKインストール時 | インストール先パスの情報 |
| 警告ログ | SPARK_CONNECT_MODE不正時 | 環境変数の不正値に関する警告 |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| 終了コード | 非ゼロ | 呼び出し元に伝播 |

## 備考

- PYSPARK_DRIVER_PYTHONにipythonを設定することで、IPython環境での起動が可能
- PYSPARK_DRIVER_PYTHON_OPTSに'notebook'を設定することで、Jupyter Notebook環境として起動可能
- JAVA_HOME未設定時のJDK自動インストール機能は、pip install経由でinstall-jdkパッケージを使用する
- py4j-0.10.9.9-src.zipがPYTHONPATHに追加され、Java-Python間の通信を実現する
- SPARK_TESTING環境変数が設定されている場合、spark-submitを介さずPythonモジュールとして直接実行される
- OLD_PYTHONSTARTUPに既存のPYTHONSTARTUPが退避され、pyspark/shell.pyがPYTHONSTARTUPとして設定される
- Spark 2.0以降でIPYTHONとIPYTHON_OPTSは廃止されており、設定されていると明示的にエラーとなる
