Skip to content

feat: add on-demand checkpoint/restore API for external orchestrators - #65

Merged
MRyutaro merged 3 commits into
mainfrom
feat/on-demand-checkpoint-api
Jun 17, 2026
Merged

MRyutaro merged 3 commits into
mainfrom
feat/on-demand-checkpoint-api

Conversation

@MRyutaro

Copy link
Copy Markdown
Owner

概要

カーネルの起動/停止時だけだったチェックポイント保存/復元を、外部オーケストレーターから任意タイミングで発火できるようにする。発火は外部からの明示指示のみで、ノートブックのエンドユーザーには透過(マジックコマンド不要・user_ns/%who を汚さない)。

動機

別途構築する外部オーケストレーションシステムが、稼働中の特定カーネルの状態を任意のタイミングでスナップショット/復元したい、というユースケースに対応する。

アーキテクチャ

外部オーケストレーター
   │  HTTP POST /elastic_kernel/checkpoint  {kernel_id}
   ▼
Jupyter Server 拡張 (serverextension.py)   ← 同一ホストでカーネルと同居
   │  control チャネルに custom message (elastic_checkpoint_request)
   ▼
カーネル (kernel.py)  control_handlers → メイン io_loop に marshal → _save_checkpoint()
   ▼
   reply (ok / elapsed / vss数) を HTTP レスポンスで返す
  • control チャネル採用: ユーザーのセル実行キューに並ばず即処理でき、user_ns にコードを走らせないため透過。
  • 実処理はメイン io_loop へ marshal し、走行中セルとの user_ns 競合を回避(一貫したスナップショット)。

変更点

  • elastic_kernel/kernel.py: 保存/復元ロジックを _save_checkpoint / _restore_checkpoint に共通化(do_shutdown / __init__ からも再利用)。control チャネルに elastic_checkpoint_request / elastic_restore_request ハンドラを登録。_run_on_main_loop でメインループへ marshal。
  • elastic_kernel/serverextension.py(新規): Jupyter Server 拡張。POST /elastic_kernel/checkpoint・/restore を提供し、kernel_id 指定でカーネルの control チャネルへ橋渡し、reply を JSON で中継。kernel.py からは jupyter_server を import しない(カーネルプロセスは非依存)。
  • elastic_kernel/command.py: elastic-kernel install --server で拡張を有効化(toggle_server_extension_python)。jupyter_server 未導入なら extras を案内。
  • pyproject.toml: optional-dependencies に server = ["jupyter_server"] を追加。

切り分け(インストール)

REST API はオプトイン。常時 ON の jupyter_server_config.d JSON は同梱せず、有効化はコマンド経由:

コマンド 効果
elastic-kernel install カーネルspecのみ(REST API は OFF)
elastic-kernel install --server 加えてサーバー拡張を有効化(REST API ON)

OFF に戻す: jupyter server extension disable elastic_kernel.serverextension

使い方(外部オーケストレーター側)

# kernel_id は /api/kernels や /api/sessions から取得
curl -X POST -H "Authorization: token $TOK" -H "Content-Type: application/json" \
  -d '{"kernel_id":"<ID>"}' http://127.0.0.1:8888/elastic_kernel/checkpoint
# -> {"ok": true, "elapsed_seconds": ..., "vss_to_migrate": N, ...}

レスポンス: 成功 200 ok:true / 不可 409(plain_kernel_mode・no_checkpoint_file・exception)/ kernel_id 不正 404・欠落 400・無認証 403・タイムアウト 504。

同一ホストにオーケストレーターがいる場合は、サーバー拡張なしで jupyter_client から control チャネルへ直接 elastic_checkpoint_request を送る運用も可能(control ハンドラは常に有効)。

テスト

  • ユニット (11件追加, tests/test_checkpoint_control.py): _save_checkpoint / _restore_checkpoint(成功・plain-kernel・例外・ファイル無し)、control ハンドラの reply 送信、サーバー拡張の登録。全 79 passed / 16 skipped。
  • E2E (手動検証済み):
    • control 経路: 実カーネルを jupyter_client で起動 → セル実行 → control に elastic_checkpoint_request 送信 → ok:true・checkpoint.pickle 書き込み・restore も成功。
    • HTTP 全経路: 実 jupyter server 起動 → セッション作成 → POST /elastic_kernel/checkpoint で 200 ok:true・ファイル書き込み確認、/restore も成功、ネガティブ(400/404/403)も期待通り。
  • black / isort / flake8 / mypy 全て clean。

補足(スコープ外の既存バグ)

E2E 中、JPY_SESSION_NAME 未設定で API 起動した場合に __setup_file_path がロガー設定前に self.logger を参照してクラッシュする既存バグを確認(通常の JupyterLab 利用では JPY_SESSION_NAME が設定されるため踏まない)。本 PR のスコープ外として別途対応を推奨。

🤖 Generated with Claude Code

カーネル起動/停止時だけでなく、外部オーケストレーターから任意タイミングで
チェックポイントの保存/復元を発火できるようにする。発火は明示指示のみで、
ノートブックユーザーには透過(マジック不要・user_ns を汚さない)。

- kernel.py: 保存/復元ロジックを _save_checkpoint / _restore_checkpoint に共通化
  (do_shutdown / __init__ からも再利用)。control チャネルにカスタムメッセージ
  ハンドラ (elastic_checkpoint_request / elastic_restore_request) を登録。実処理は
  メイン io_loop へ marshal して走行中セルとの user_ns 競合を回避。
- serverextension.py: Jupyter Server 拡張。POST /elastic_kernel/checkpoint・/restore
  を提供し、kernel_id 指定でカーネルの control チャネルへ橋渡し、reply を JSON で中継。
- command.py: `elastic-kernel install --server` で拡張を有効化
  (toggle_server_extension_python)。
- pyproject.toml: optional-dependencies に server extra (jupyter_server) を追加。
- tests: 保存/復元・control ハンドラ・拡張登録のユニットテストを追加。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@MRyutaro

Copy link
Copy Markdown
Owner Author

その機能用のドキュメントをどこかに書いておいてほしいです.
README.mdから追えるようにしておいてほしい.

機能の使い方を docs/CHECKPOINT_API.md にまとめ、README.md / README.ja.md の
ドキュメントセクションからリンクして辿れるようにする。有効化方法・REST
エンドポイント・レスポンス・curl 例・control チャネル直送の代替手段を記載。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@MRyutaro

Copy link
Copy Markdown
Owner Author

ドキュメントを追加しました 📝(commit 3239260)

  • docs/CHECKPOINT_API.md(新規)に機能の使い方をまとめました: 有効化方法(elastic-kernel install --server / [server] extra)、REST エンドポイント(POST /elastic_kernel/checkpoint・/restore)、リクエスト/レスポンス仕様、curl 例、kernel_id の調べ方、サーバー拡張を使わない control チャネル直送の代替手段。
  • README.md / README.ja.md の「Documentation / ドキュメント」セクションから辿れるようにリンクを追加しました(両 README 同期済み)。

Comment thread elastic_kernel/kernel.py
…aling)

レビュー指摘を受け、_run_on_main_loop が何をしているのかを具体化。control スレッドと
メイン shell io_loop の住み分け、なぜ user_ns を直接触ると競合するのか、add_callback と
call_soon_threadsafe による橋渡しの手順をステップで説明。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@MRyutaro
MRyutaro merged commit 8c0baba into main Jun 17, 2026
7 checks passed
@MRyutaro
MRyutaro deleted the feat/on-demand-checkpoint-api branch June 17, 2026 06:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant