Metadata-Version: 2.5
Name: chongming-request
Version: 0.1.1
Summary: worker direct communication
Requires-Python: >=3.12
Requires-Dist: eclipse-zenoh>=1.9.0
Requires-Dist: orjson>=3.10
Description-Content-Type: text/markdown

# chongming-request

Zenoh Worker 直连客户端，用于从服务端或其他 Worker 直接调用 Zenoh RPC，无需经过 HTTP 路由。

---

## 安装

```bash
uv pip install -e utils/request
```

---

## 功能

- **自动服务发现**：基于 Zenoh liveliness 自动发现存活的 Worker
- **随机负载均衡**：在可用 Worker 间随机选择；疑似故障副本进入 30s 冷静期被跳过
- **换副本重试**：超时 / 无回复 / 业务错误时换一个「未试过」的副本重试，
  无未试副本立即失败（不重复打同一个坏副本）；业务错误不列入冷静期
- **同步/异步支持**：提供 `call`（异步）和 `call_sync`（同步）接口

---

## API

### `Client` 类

```python
from chongming_request import Client

async with Client(session=zenoh_session) as client:
    result = await client.call(
        worker_type="example",
        subject="example.add",
        payload={"a": 1, "b": 2},
        method="GET"
    )
```

| 参数          | 类型            | 说明                             |
| ------------- | --------------- | -------------------------------- |
| `session`     | `zenoh.Session` | Zenoh 会话对象                   |
| `worker_type` | `str`           | Worker 类型名（如 `"example"`）  |
| `subject`     | `str`           | Zenoh 主题（如 `"example.add"`） |
| `payload`     | `dict`          | 业务参数（自动封装为信封）       |
| `method`      | `str`           | HTTP 方法（`"GET"` / `"POST"`）  |
| `timeout`     | `float`         | 单次调用超时（秒），换副本重试重新计时 |
| `retries`     | `int`           | 失败重试次数（每次重试换一个未试过的副本） |

> **信封协议**：`call()` 把 `payload` 封装为
> `{"meta": {"method": ...}, "data": payload}` 发送，**不修改调用方传入的 dict**；
> 若传入的 `payload` 已含 `meta`/`data` 键则视为完整信封**原样使用**（保留全部
> 字段、不改写 `0`/`[]` 等 falsy 值），仅缺 `meta.method` 时补入。`meta` 非 dict
> 会立即抛 `ValueError`，不会被发送。

### 与网关 `worker_manager.call_raw` 的语义对齐

- **载荷**：业务数据整体入 `data`；调用方自备信封时不改写（对齐 call_raw 的
  "谁构造信封谁负责"）。
- **回复**：worker 回复解析为 dict 返回，空回复兜底 `{}`（对齐 call_raw 的 `b"{}"`）。
- **重试**：超时 / 无回复 / 业务错误换未试过的副本重试；超时与无回复的副本进入
  30s 冷静期，后续调用跳过；失败终态抛 `RuntimeError` 并携带最后一个错误详情
  （已尝试副本数、次数上限、具体原因）。
- **信任模型**：本包定位为**内部 worker 请求工具**（worker 间调用 / 服务端内部直连），
  走 Zenoh 直连、无 HTTP 链路：`meta.user_info` **不会**被注入或校验，需要时由调用方
  自填；`cacheable`、实例定向（`instance_id`）等能力请走网关 HTTP 或 `call_raw`。

### 同步调用

```python
result = client.call_sync(
    worker_type="example",
    subject="example.add",
    payload={"a": 1, "b": 2},
    timeout=5.0
)
```

---

## 使用场景

1. **Worker 间互相调用**：一个 Worker 调用另一个 Worker 的 RPC 方法
2. **服务端内部调用**：在 FastAPI 路由处理器中直接调用 Worker
3. **内部接口调用**：调用 `internal = true` 的端点（不暴露 HTTP 路由）
4. **测试与调试**：直接测试 Worker 的 RPC 行为

---

## 与 HTTP 调用的对比

| 特性                 | HTTP 调用          | `chongming-request`  |
| -------------------- | ------------------ | -------------------- |
| 需要注册 HTTP 路由   | ✅                 | ❌（直接 Zenoh RPC） |
| 支持 `internal` 端点 | ❌                 | ✅                   |
| 序列化开销           | JSON → HTTP → JSON | JSON → Zenoh → JSON  |
| 适用场景             | 外部客户端         | 内部微服务通信       |

---

## 测试

```bash
python tests/test_client.py
```

---

## 依赖

- `zenoh` — Zenoh Python 绑定（`eclipse-zenoh`）
- `orjson` — JSON 序列化
