modify: workers/ 移出版本控制(开发期本地目录,容器内独立部署)
This commit is contained in:
@@ -19,6 +19,9 @@ output.md
|
|||||||
# plugins
|
# plugins
|
||||||
src/plugins/
|
src/plugins/
|
||||||
|
|
||||||
|
# 进程插件(开发期本地目录;生产在独立容器部署,不入库)
|
||||||
|
workers/
|
||||||
|
|
||||||
# chongming-web
|
# chongming-web
|
||||||
src/chongming-web
|
src/chongming-web
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
"""
|
|
||||||
进程插件目录(load_mode = "external" 的插件)
|
|
||||||
|
|
||||||
与 src/plugins/(inline 插件)结构一致,区别仅在运行方式:
|
|
||||||
- 由 Docker/K8s 编排拉起独立进程(容器入口 uv run worker_serve --type <name>)
|
|
||||||
- 进程自读 config/workers/<name>/ 配置、进程内契约校验,经 Zenoh
|
|
||||||
(chongming/routes/**)注册路由,网关动态挂载 HTTP 端点
|
|
||||||
"""
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
"""
|
|
||||||
Demo 进程插件 — 独立进程运行示例
|
|
||||||
|
|
||||||
与 inline 插件(src/plugins/)结构完全一致,区别仅在运行方式:
|
|
||||||
- config/workers/demo/config.toml 声明 load_mode = "external"、module = "workers.demo"
|
|
||||||
- 由 Docker/K8s 编排拉起独立进程: uv run worker_serve --type demo
|
|
||||||
- 启动流程: 自读 TOML → 进程内契约校验 → create_workers →
|
|
||||||
经 Zenoh 发布路由描述符(网关 RouteRegistry 动态挂载 HTTP 路由)→
|
|
||||||
每 10s 周期重发布自愈 → SIGTERM 时摘除路由并 cleanup
|
|
||||||
"""
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from chongming_worker.plugin import Plugin
|
|
||||||
|
|
||||||
from .router import * # noqa: F401,F403 触发 @rpc_method 注册
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class DemoPlugin(Plugin):
|
|
||||||
"""Demo 插件 — 无数据库的进程插件最小示例。"""
|
|
||||||
|
|
||||||
type = "demo"
|
|
||||||
db_name = None # 无数据库
|
|
||||||
auto_bind = True # 自动绑定 models/pydantic.py(支持 workers/ 路径)
|
|
||||||
|
|
||||||
async def on_init(self):
|
|
||||||
"""首次 create_workers 时调用一次:读取插件私有配置。"""
|
|
||||||
prefix = self.config.get("greeting_prefix", "Hello")
|
|
||||||
self.set_var("greeting_prefix", prefix)
|
|
||||||
logger.info("[demo] 初始化完成 (greeting_prefix=%s)", prefix)
|
|
||||||
|
|
||||||
async def on_cleanup(self):
|
|
||||||
"""cleanup 时调用(无外部资源需要释放)。"""
|
|
||||||
logger.info("[demo] 清理完成")
|
|
||||||
|
|
||||||
|
|
||||||
# 暴露给 worker_serve 的模块级入口(签名与 inline 插件一致)
|
|
||||||
plugin = DemoPlugin()
|
|
||||||
create_workers = plugin.create_workers
|
|
||||||
cleanup = plugin.cleanup
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
"""
|
|
||||||
Demo 进程插件全局运行时状态 — 与 inline 插件约定一致
|
|
||||||
|
|
||||||
约定:
|
|
||||||
- 模块只做"声明默认值",不产生任何导入期副作用
|
|
||||||
- 所有值统一在 on_init 中通过 set_global_var 显式写入
|
|
||||||
- set_global_var 仅允许写入 _ALLOWED 白名单,拼写错误会立即抛错
|
|
||||||
"""
|
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
# 允许写入的全局变量白名单(防止拼写错误静默创建无用的新变量)
|
|
||||||
_ALLOWED = frozenset({"greeting_prefix"})
|
|
||||||
|
|
||||||
# 显式声明所有运行时状态(默认值,运行时由 on_init 写入)
|
|
||||||
greeting_prefix: str = "Hello"
|
|
||||||
|
|
||||||
|
|
||||||
def set_global_var(name: str, value: Any) -> None:
|
|
||||||
"""白名单校验版 setter — 设置模块级运行时状态。"""
|
|
||||||
if name not in _ALLOWED:
|
|
||||||
raise KeyError(f"global_var 未知变量: {name}(允许: {sorted(_ALLOWED)})")
|
|
||||||
globals()[name] = value
|
|
||||||
|
|
||||||
|
|
||||||
def require(name: str) -> Any:
|
|
||||||
"""取"必须已存在"的值,未初始化时抛清晰错误。"""
|
|
||||||
if name not in _ALLOWED:
|
|
||||||
raise KeyError(f"global_var 未知变量: {name}")
|
|
||||||
return globals()[name]
|
|
||||||
|
|
||||||
|
|
||||||
__all__ = ["greeting_prefix", "set_global_var", "require"]
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
"""
|
|
||||||
模型导出 — demo
|
|
||||||
自动生成,请勿手动修改
|
|
||||||
"""
|
|
||||||
|
|
||||||
from .pydantic import DemoResponse
|
|
||||||
from .pydantic import HelloGetRequest
|
|
||||||
from .pydantic import HelloGetResponse
|
|
||||||
|
|
||||||
__all__ = [
|
|
||||||
"DemoResponse",
|
|
||||||
"HelloGetRequest",
|
|
||||||
"HelloGetResponse",
|
|
||||||
]
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
"""
|
|
||||||
自动生成的 Pydantic 模型 — demo
|
|
||||||
来源: config/workers/demo/
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from typing import Optional
|
|
||||||
from pydantic import BaseModel, Field
|
|
||||||
|
|
||||||
class HelloGetRequest(BaseModel):
|
|
||||||
"""进程插件示例:问候 — 请求体"""
|
|
||||||
name: str = Field(...)
|
|
||||||
|
|
||||||
class HelloGetResponse(BaseModel):
|
|
||||||
"""进程插件示例:问候 — 响应体"""
|
|
||||||
greeting: str = Field(...)
|
|
||||||
worker_id: Optional[str] = Field(default='')
|
|
||||||
timestamp: float = Field(...)
|
|
||||||
|
|
||||||
|
|
||||||
# 所有响应模型的联合类型
|
|
||||||
DemoResponse = HelloGetResponse
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
"""Demo 进程插件路由端点"""
|
|
||||||
|
|
||||||
from . import hello # noqa: F401 触发 @rpc_method 注册
|
|
||||||
|
|
||||||
__all__ = ["hello"]
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
"""问候端点 — 演示框架参数注入(worker_id)与插件私有配置读取"""
|
|
||||||
import time
|
|
||||||
|
|
||||||
from chongming_worker import rpc_method
|
|
||||||
|
|
||||||
from .. import global_var as gv
|
|
||||||
from ..models.pydantic import HelloGetRequest, HelloGetResponse
|
|
||||||
|
|
||||||
|
|
||||||
@rpc_method(
|
|
||||||
subject="demo.hello",
|
|
||||||
method="GET",
|
|
||||||
summary="进程插件示例:问候",
|
|
||||||
response_model=HelloGetResponse,
|
|
||||||
)
|
|
||||||
async def hello(
|
|
||||||
hello_get_request: HelloGetRequest,
|
|
||||||
worker_id: str = "",
|
|
||||||
) -> HelloGetResponse:
|
|
||||||
"""返回问候语 + 处理请求的 worker 副本 ID(证明请求经独立进程处理)"""
|
|
||||||
return HelloGetResponse(
|
|
||||||
greeting=f"{gv.greeting_prefix}, {hello_get_request.name}!",
|
|
||||||
worker_id=worker_id,
|
|
||||||
timestamp=time.time(),
|
|
||||||
)
|
|
||||||
Reference in New Issue
Block a user