Files
chongming-plugins/README.md
T

218 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Worker 插件开发指南
每个子目录代表一个独立的 Worker 插件,封装特定领域的业务逻辑。插件通过 Zenoh RPC 对外提供服务,
HTTP 路由由框架根据 TOML 配置自动生成。
---
## 目录结构约定
```text
plugin_name/
├── __init__.py # 入口:create_workers() 工厂 + cleanup()
├── global_var.py # 模块级全局状态(数据库连接、API 客户端等)
├── router/ # RPC 端点实现
│ ├── __init__.py # 导入所有端点模块,__all__ 导出
│ └── <操作名>.py # 每个端点一个文件,使用 @rpc_method 装饰器
├── models/ # 数据模型
│ ├── __init__.py # 模型导出(自动生成,勿手动修改)
│ ├── pydantic.py # Pydantic 请求/响应模型(由 gen_models.py 自动生成)
│ └── <表名>.py # SQLModel ORM 模型(如需要数据库)
└── README.md # 插件说明文档
```
---
## 开发新插件:完整流程
### 第一步:创建目录结构
```bash
mkdir -p src/plugins/<plugin_name>/router
mkdir -p src/plugins/<plugin_name>/models
touch src/plugins/<plugin_name>/__init__.py
touch src/plugins/<plugin_name>/global_var.py
touch src/plugins/<plugin_name>/router/__init__.py
```
### 第二步:注册插件
在 `config/workers/config.toml` 中添加:
```toml
[[workers]]
type = "<plugin_name>"
module = "plugins.<plugin_name>"
factory = "create_workers"
cleanup = "cleanup"
count = 3
[workers.config]
type = "<plugin_name>"
# 自定义配置项...
```
### 第三步:编写端点 TOML 配置
创建 `config/workers/<plugin_name>/config.toml`(分组配置):
```toml
[worker]
defaults = { timeout = 3.0, auth_required = true, cacheable = false, internal = false }
[worker.registration]
router_prefix = "/<prefix>"
```
创建每个操作的 `.toml` 文件,如 `config/workers/<plugin_name>/my_action.toml`:
```toml
[POST]
summary = "我的操作"
auth_required = true
[POST.response_model]
result = { type = "str", required = true }
message = { type = "str", default = "" }
```
### 第四步:生成 Pydantic 模型
```bash
uv run python -m chongming.scripts.gen_models
```
这会自动在 `src/plugins/<plugin_name>/models/` 下生成 `pydantic.py` 和更新 `__init__.py`。
### 第五步:实现 RPC 端点
`src/plugins/<plugin_name>/router/my_action.py`:
```python
from chongming_worker.decorators import rpc_method
from ..models.pydantic import MyActionPostRequest, MyActionPostResponse
@rpc_method(
subject="<plugin_name>.my_action",
method="POST",
response_model=MyActionPostResponse,
)
async def my_action(request: MyActionPostRequest) -> MyActionPostResponse:
"""业务逻辑实现"""
result = await do_something(request)
return MyActionPostResponse(result="success", message="done")
```
### 第六步:更新 router 导出
`src/plugins/<plugin_name>/router/__init__.py`:
```python
from . import my_action
__all__ = ["my_action"]
```
### 第七步:实现工厂函数
`src/plugins/<plugin_name>/__init__.py`:
```python
from chongming_worker.runtime import create_workers as _create_workers
def create_workers(session, config, count, worker_manager):
"""插件入口:初始化全局资源,启动 Worker"""
from . import router # 触发 @rpc_method 注册
from .global_var import set_db
# 初始化数据库、客户端等
from chongming_database import Database
db = Database(config["data_dir"] / "mydb.db")
# await db.initialize() -- 在异步环境中
set_db(db)
_create_workers(session, config, count, worker_manager)
async def cleanup(worker_manager):
"""清理资源"""
from .global_var import db
if db:
await db.dispose()
```
---
## 为现有插件添加新端点
1. 在 `config/workers/<plugin_name>/` 下创建 `<新操作>.toml`
2. 运行 `uv run python -m chongming.scripts.gen_models`
3. 在 `router/` 下创建 `<新操作>.py`,引用生成的模型
4. 更新 `router/__init__.py`
5. 重启服务
---
## 全局变量模式
每个插件通过 `global_var.py` 管理模块级共享资源,避免跨请求的状态冲突:
```python
# global_var.py
db: "Database | None" = None
def set_db(database: "Database"):
global db
db = database
```
在端点中直接引用:
```python
from ..global_var import db
@rpc_method(subject="plugin.action", method="GET", ...)
async def handler(request: RequestModel):
async with db.get_session() as session:
# 执行数据库操作
...
```
---
## 装饰器说明
```python
@rpc_method(
subject="<plugin>.<operation>", # Zenoh 主题(必需)
method="GET", # HTTP 方法:GET 或 POST
response_model=ResponseCls, # Pydantic 响应模型类
)
async def handler(request: RequestCls) -> ResponseCls:
...
```
- **GET 端点**:参数通过 URL query string 传递,在 TOML 中用 `params` 定义
- **POST 端点**:参数通过 JSON body 传递,自动绑定到 Pydantic 请求模型
- **internal 端点**:设置 `internal = true` 后,不注册 HTTP 路由,仅可通过 Zenoh RPC 内部调用
---
## 命名约定
| 概念 | 约定 | 示例 |
| ----------------- | --------------- | ----------------------------------- |
| 插件名 | 小写下划线 | `doubao`, `auth`, `example` |
| 操作名 | 小写下划线 | `analyze`, `add`, `change_password` |
| Zenoh subject | `<插件>.<操作>` | `example.add`, `doubao.analyze` |
| TOML 文件名 | 与操作名一致 | `analyze.toml`, `add.toml` |
| Python 路由文件名 | 与操作名一致 | `analyze.py`, `add.py` |
---
## 现有插件
| 插件 | 说明 | 文档 |
| ---------------------------- | -------------------------------------- | ---------------- |
| [auth](auth/README.md) | 用户注册、登录、JWT 鉴权、用户信息管理 | 含 SQLite 数据库 |
| [doubao](doubao/README.md) | 火山引擎豆包视觉理解模型集成 | 第三方 API 调用 |
| [example](example/README.md) | 四则运算示例 + 访问计数器 | 入门参考 |