# 機能設計書 26-リクエストキャンセル

## 概要

本ドキュメントは、libuv の `uv_cancel()` API による未処理リクエストのキャンセル機能について、その設計仕様を記述する。

### 本機能の処理概要

`uv_cancel()` は、スレッドプールに投入されたがまだ実行されていないリクエストをキャンセルする関数である。

**業務上の目的・背景**：libuv のスレッドプールで実行されるファイルシステム操作、DNS解決、カスタムワークなどの非同期リクエストは、投入後も実行前であればキャンセルが可能である。アプリケーションの終了処理やタイムアウト処理において、不要になったリクエストをキャンセルすることでリソースを効率的に解放し、コールバックの不必要な実行を防ぐことができる。

**機能の利用シーン**：アプリケーション終了時のクリーンアップ、タイムアウトによるリクエストの打ち切り、ユーザー操作によるキャンセル要求への対応に使用される。

**主要な処理内容**：
1. リクエストの型を switch 文で判定（UV_FS, UV_GETADDRINFO, UV_GETNAMEINFO, UV_RANDOM, UV_WORK）
2. リクエスト型に応じて内部の `uv__work` 構造体とループへの参照を取得
3. `uv__work_cancel()` を呼び出してスレッドプールからリクエストを取り消す
4. 未対応のリクエスト型の場合は UV_EINVAL を返却

**関連システム・外部連携**：スレッドプール（threadpool）との連携。

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

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 8 | リクエスト基底 | 主機能 | uv_cancel()による未処理リクエストキャンセルのAPI定義 |
| 25 | スレッドプール | 補助機能 | uv_cancel()によるワークリクエストキャンセルのAPI定義 |

## 機能種別

制御処理（リクエストのキャンセル）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| req | uv_req_t* | Yes | キャンセルするリクエストへのポインタ | NULLでないこと。対応する型であること |

### 入力データソース

関数の引数として直接指定される。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 戻り値 | int | 0: キャンセル成功、UV_EINVAL: 未対応のリクエスト型、UV_EBUSY: リクエストが実行中でキャンセル不可 |

### 出力先

関数の戻り値として呼び出し元に返却される。キャンセルされた場合、リクエストのコールバックが UV_ECANCELED エラーで呼び出される。

## 処理フロー

### 処理シーケンス

```
1. req->type で分岐
   ├─ UV_FS:          uv_fs_t としてキャスト、loop と work_req を取得
   ├─ UV_GETADDRINFO:  uv_getaddrinfo_t としてキャスト
   ├─ UV_GETNAMEINFO:  uv_getnameinfo_t としてキャスト
   ├─ UV_RANDOM:       uv_random_t としてキャスト
   ├─ UV_WORK:         uv_work_t としてキャスト
   └─ default:         UV_EINVAL を返却
2. uv__work_cancel(loop, req, wreq) を呼び出し
   └─ スレッドプールのキューからリクエストを除去
3. 結果を返却
```

### フローチャート

```mermaid
flowchart TD
    A[uv_cancel] --> B{req->type}
    B -->|UV_FS| C1["loop/wreq 取得"]
    B -->|UV_GETADDRINFO| C2["loop/wreq 取得"]
    B -->|UV_GETNAMEINFO| C3["loop/wreq 取得"]
    B -->|UV_RANDOM| C4["loop/wreq 取得"]
    B -->|UV_WORK| C5["loop/wreq 取得"]
    B -->|default| D["return UV_EINVAL"]
    C1 --> E["uv__work_cancel(loop, req, wreq)"]
    C2 --> E
    C3 --> E
    C4 --> E
    C5 --> E
    E --> F["結果を返却"]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-26-01 | 対応リクエスト型の制限 | UV_FS, UV_GETADDRINFO, UV_GETNAMEINFO, UV_RANDOM, UV_WORK のみキャンセル可能 | 常時 |
| BR-26-02 | 実行中リクエストのキャンセル不可 | スレッドプールで既に実行開始されたリクエストはキャンセルできない（UV_EBUSY） | リクエストが実行中の場合 |
| BR-26-03 | コールバック呼び出し | キャンセル成功時、リクエストのコールバックが UV_ECANCELED エラーで呼び出される | キャンセル成功時 |

### 計算ロジック

リクエスト型に基づく構造体キャストと内部フィールドの取得。

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

該当なし。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| UV_EINVAL | 不正引数 | 未対応のリクエスト型が渡された場合 | 対応する型のリクエストのみ渡す |
| UV_EBUSY | 実行中 | リクエストが既にスレッドプールで実行中の場合 | リクエストの完了を待つ |

### リトライ仕様

リトライは不要。UV_EBUSY の場合、リクエストの完了を待つ必要がある。

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

該当なし。

## パフォーマンス要件

スレッドプールのミューテックスロックを取得してキューを操作するため、ロック競合が発生する可能性がある。

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

特になし。

## 備考

- キャンセルが成功した場合でも、コールバックは必ず呼び出される（UV_ECANCELED エラーとして）。
- TCP/UDP 等のストリーム/データグラムリクエストはキャンセル対象外である。
- `uv__work_cancel()` の内部実装はスレッドプールの作業キューからの除去とコールバックのスケジューリングを行う。

---

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

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

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | uv.h | `include/uv.h` | **207-214行目**: uv_req_type 列挙型。UV_FS, UV_WORK, UV_GETADDRINFO 等の定義 |
| 1-2 | uv.h | `include/uv.h` | **432-444行目**: UV_REQ_FIELDS マクロと uv_req_s 構造体。type フィールドを含む |

**読解のコツ**: 各リクエスト型は `uv_req_t` を基底として共有している。`uv_cancel()` は `req->type` でリクエストの具体型を判定し、適切な構造体にキャストする。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | uv.h | `include/uv.h` | **1200行目**: uv_cancel() の宣言 |

#### Step 3: 実装を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | threadpool.c | `src/threadpool.c` | **399-429行目**: uv_cancel() の実装 |

**主要処理フロー**:
- **399行目**: uv_cancel 関数開始
- **403行目**: switch(req->type) で分岐
- **404-406行目**: UV_FS の場合、uv_fs_t にキャストして loop と work_req を取得
- **408-410行目**: UV_GETADDRINFO の場合
- **412-414行目**: UV_GETNAMEINFO の場合
- **416-418行目**: UV_RANDOM の場合
- **420-422行目**: UV_WORK の場合
- **424-425行目**: default で UV_EINVAL を返却
- **428行目**: uv__work_cancel(loop, req, wreq) を呼び出し

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

```
uv_cancel(req)
    │
    ├─ switch(req->type) でリクエスト型を判定
    │      ├─ UV_FS / UV_GETADDRINFO / UV_GETNAMEINFO / UV_RANDOM / UV_WORK
    │      └─ 各型に応じて loop, wreq を取得
    │
    └─ uv__work_cancel(loop, req, wreq)
           ├─ スレッドプールのキューからリクエストを除去
           └─ コールバックをスケジューリング（UV_ECANCELED）
```

### データフロー図

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

uv_req_t* ───────▶ req->type 判定 ──────────────▶ int (0 / UV_EINVAL / UV_EBUSY)
                   uv__work_cancel() 呼び出し
                   └─ キューからの除去
                   └─ コールバックスケジューリング
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| uv.h | `include/uv.h` | ヘッダ | API宣言（L1200）、uv_req_type 列挙型定義 |
| threadpool.c | `src/threadpool.c` | ソース | uv_cancel() の実装（L399-429） |
