91 lines
3.0 KiB
Markdown
91 lines
3.0 KiB
Markdown
# 非同期キャンセル設計
|
|
|
|
Workerの非同期キャンセル機構についての設計ドキュメント。
|
|
|
|
## 概要
|
|
|
|
`tokio_util::sync::CancellationToken`を用いて、別タスクからWorkerの実行を安全にキャンセルできる。
|
|
|
|
```rust
|
|
let worker = Arc::new(Mutex::new(Worker::new(client)));
|
|
|
|
// 実行タスク
|
|
let w = worker.clone();
|
|
let handle = tokio::spawn(async move {
|
|
w.lock().await.run("prompt").await
|
|
});
|
|
|
|
// キャンセル
|
|
worker.lock().await.cancel();
|
|
```
|
|
|
|
## キャンセルポイント
|
|
|
|
キャンセルは以下のタイミングでチェックされる:
|
|
|
|
1. **ターンループ先頭** — `is_cancelled()`で即座にチェック
|
|
2. **ストリーム開始前** — `client.stream()`呼び出し時
|
|
3. **ストリーム受信中** — `tokio::select!`で各イベント受信と並行監視
|
|
4. **ツール実行中** — `join_all()`と並行監視
|
|
|
|
## キャンセル時の処理フロー
|
|
|
|
```
|
|
キャンセル検知
|
|
↓
|
|
timeline.abort_current_block() // 進行中ブロックの終端処理
|
|
↓
|
|
run_on_abort_hooks("Cancelled") // on_abort フック呼び出し
|
|
↓
|
|
Err(WorkerError::Cancelled) // エラー返却
|
|
```
|
|
|
|
## API
|
|
|
|
| メソッド | 説明 |
|
|
| ---------------------- | --------------------------------------------------------- |
|
|
| `cancel()` | キャンセルをトリガー |
|
|
| `is_cancelled()` | キャンセル状態を確認 |
|
|
| `cancellation_token()` | トークンへの参照を取得(`clone()`してタスク間で共有可能) |
|
|
|
|
## on_abort フック
|
|
|
|
`Hook::on_abort(&self, reason: &str)`がキャンセル時に呼ばれる。
|
|
クリーンアップ処理やログ記録に使用できる。
|
|
|
|
```rust
|
|
async fn on_abort(&self, reason: &str) -> Result<(), HookError> {
|
|
log::info!("Aborted: {}", reason);
|
|
Ok(())
|
|
}
|
|
```
|
|
|
|
呼び出しタイミング:
|
|
|
|
- `WorkerError::Cancelled` — reason: `"Cancelled"`
|
|
- `ControlFlow::Abort(reason)` — reason: フックが指定した理由
|
|
|
|
---
|
|
|
|
## 既知の問題
|
|
|
|
### 1. キャンセルトークンの再利用不可
|
|
|
|
`CancellationToken`は一度キャンセルされると永続的にキャンセル状態になる。
|
|
同じWorkerインスタンスで再度`run()`を呼ぶと即座に`Cancelled`エラーになる。
|
|
|
|
**対応案:**
|
|
|
|
- `run()`開始時に新しいトークンを生成する
|
|
- `reset_cancellation()`メソッドを提供する
|
|
|
|
### 2. Sync バウンドの追加(破壊的変更)
|
|
|
|
`tokio::select!`使用のため、Handler/Scope型に`Sync`バウンドを追加した。
|
|
既存のユーザーコードで`Sync`未実装の型を使用している場合、コンパイルエラーになる。
|
|
|
|
### 3. エラー時のon_abort呼び出し
|
|
|
|
現在、`on_abort`はキャンセルとフックAbort時のみ呼ばれる。
|
|
ストリームエラー等のその他エラー時には呼ばれないため、一貫性に欠ける可能性がある。
|