# Web 阻塞 API 策略

## 功能

说明 Web 请求上下文中慢 I/O、阻塞等待和长期后台能力的运行规则。

Web 请求脚本会整体进入 BT 进程级 blocking pool 执行，避免 `fs`、短 `sleep()`、模板编译、同步脚本逻辑等阻塞 Tokio Web worker。blocking pool 的线程数、队列长度和默认等待时间由 `BT_IO_*` 配置控制。

## 语法

```bt
// 查看当前 I/O 运行边界配置
stats = BT.stats().io
```

## 参数

无参数。

## 返回值

该页面是规则说明，不提供独立函数返回值。

## Web 请求规则

| API | Web 请求中行为 | 边界 |
| ------ | ------ | ------ |
| `sleep(ms)` | 允许短休眠。 | `ms` 不能超过 `BT_IO_TIMEOUT_MS`，默认 30000 毫秒。 |
| `pause()` | 拒绝。 | Web 请求没有交互式终端。 |
| `fs.*` | 允许。 | 请求脚本整体运行在 blocking pool，受 `BT_IO_BLOCKING_WORKERS`、`BT_IO_BLOCKING_QUEUE`、`BT_IO_TIMEOUT_MS` 约束。 |
| `process.status()` / `process.output()` / `process.child()` / `process.wait()` | 拒绝。 | 这些操作可能同步等待外部进程或派生长期子进程。 |
| `reqwest.send()` | 允许。 | 使用共享 I/O runtime，单次请求默认 30000 毫秒；可用 `timeout(ms)` 设置，但 Web 请求整体仍受 `BT_IO_TIMEOUT_MS` 约束。 |
| `mysql.all()` / `mysql.one()` / `mysql.exec()` | 允许。 | 使用共享 I/O runtime 和 MySQL 查询超时，Web 请求整体仍受 `BT_IO_TIMEOUT_MS` 约束。 |
| `task(fn, ...args)` | 允许提交后台任务。 | `Task.on_done()`、`Task.await()`、`task_all()`、`task_race()` 在 Web 请求中拒绝。 |
| `device.*` | 允许。 | 串口打开和读写必须依赖设备配置中的超时，Web 请求整体受 `BT_IO_TIMEOUT_MS` 约束。 |

## 代码示例

```bt
web.header('Content-Type', 'text/plain; charset=utf-8')

sleep(5)

// 输出：ok
print 'ok'
```

```bt
web.header('Content-Type', 'text/plain; charset=utf-8')

task(fn() {
    return 1
}).await()

// 输出：不会执行到这里
print 'done'
```

## 注意事项

- `BT_IO_TIMEOUT_MS` 默认 30000 毫秒，同时作为 Web 请求脚本在 blocking pool 中等待结果的默认上限。
- 如果 blocking pool 队列已满，请求会返回明确中文错误：`I/O 阻塞任务队列已满`。
- 超时会让当前 HTTP 请求返回错误，但已经进入系统阻塞调用的底层操作不能被 Rust 安全强制中断；因此 Web 中仍应避免长时间外部进程和无超时设备操作。
- 需要验证示例时，可运行 `examples/web-blocking-policy/main.bt`。
