2026-09-19 13:07:15 +08:00

133 lines
5.6 KiB
Python
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.

# -*- coding: utf-8 -*-
"""m11b_api —— M11b 对外契约的 **async 包装层**(dspy 直接调用的名字)。
dspy 端点以「裸全局名 + await」调用,因此这里导出的每个名字必须:
① 在本文件有真实实现(或从 tx_write/broadcast 再导出)
② 在 __init__.py 有 import 导出
③ 在 init.py load_pbl_runtime_ext() 内有 ``env.<name> = <name>`` 注册
三处缺一,上线即 ``NameError: name 'xxx' is not defined``(QC #1 指出的正是此缺口)。
导出(6 个契约):
apply_runtime_event / poll_events / read_states / assert_append_only
pbl_runtime_broadcast_pull / pbl_runtime_broadcast_stats
"""
import inspect
from . import broadcast as _hub
from . import latency as _lat
from . import rtx_db
from . import tx_write as _w
from .m11b_config import CHANNEL_PREFIX, contracts as _contracts
__all__ = ["apply_runtime_event", "poll_events", "read_states", "assert_append_only",
"pbl_runtime_broadcast_pull", "pbl_runtime_broadcast_stats",
"get_hub", "contracts"]
# 再导出核心实现(保持单一事实源:实现只在 tx_write/broadcast 里)
apply_runtime_event = _w.apply_runtime_event
poll_events = _w.poll_events
read_states = _w.read_states
assert_append_only = _w.assert_append_only
get_hub = _hub.get_hub
contracts = _contracts
def _bad(msg):
return {"ok": False, "code": "PBL-PARAM-0001", "error": msg}
def _fail(exc):
code = getattr(exc, "code", "PBL-RTX-0002")
return {"ok": False, "code": code, "error": str(getattr(exc, "msg", exc))}
async def pbl_runtime_broadcast_pull(tenant_id=None, world_id=None, session_id=None,
after_cursor=None, after_seq=None, limit=200,
channel=None, **_ignored):
"""广播拉取端点(3s 轮询兜底用)。
两种用法:
* 传 tenant_id(+world_id) → 走 poll_events(hub 命中优先,未命中退回查库)
* 只传 channel → 直接按通道名从 hub 取增量(跨租户禁用,须带 tenant_id 前缀)
"""
try:
if tenant_id in (None, "") and channel:
expect = "%s.%s." % (CHANNEL_PREFIX, "")
if not str(channel).startswith(CHANNEL_PREFIX + "."):
return _bad("channel 必须以 %s. 开头" % CHANNEL_PREFIX)
parts = str(channel).split(".")
if len(parts) < 4 or parts[3] in ("", "*"):
return _bad("channel 必须含租户段(pbl.world.<tenant>.<world>),"
"拒绝跨租户拉取")
tenant_id = parts[3]
world_id = parts[4] if len(parts) > 4 else None
events, truncated = _hub.get_hub().pull(
channel or _hub.channel_of(world_id, tenant_id), after_cursor,
limit or 200)
if events and not truncated and after_seq in (None, ""):
return {"ok": True, "source": "hub", "truncated": False,
"events": events, "next_cursor": events[-1]["cursor"],
"count": len(events)}
res = await poll_events(tenant_id=tenant_id, world_id=world_id,
session_id=session_id, after_cursor=after_cursor,
after_seq=after_seq, limit=limit)
res["count"] = len(res.get("events") or [])
return res
except rtx_db.RtxError as exc:
return _fail(exc)
except Exception as exc: # noqa: BLE001
return _fail(exc)
async def pbl_runtime_broadcast_stats(tenant_id=None, world_id=None, **_ignored):
"""广播/时延统计端点:hub 扇出计数 + 各阶段 SLA 实测摘要。"""
try:
hub = _hub.get_hub()
st = hub.stats()
st["sla"] = _lat.summary()
st["contracts"] = sorted(_contracts().keys())
st["channel_prefix"] = CHANNEL_PREFIX
if tenant_id not in (None, "") and world_id not in (None, ""):
st["channel"] = _hub.channel_of(world_id, tenant_id)
buffered, _ = hub.pull(st["channel"], None, 50)
st["channel_buffered"] = len(buffered)
st["ok"] = True
return st
except Exception as exc: # noqa: BLE001
return _fail(exc)
def self_check():
"""离线自检:6 个契约全部存在、可调用、协程签名正确(防三处同步漏项)。"""
msgs, ok = [], True
coros = ("apply_runtime_event", "poll_events", "read_states",
"pbl_runtime_broadcast_pull", "pbl_runtime_broadcast_stats")
for name in coros:
fn = globals().get(name)
if fn is None:
ok = False
msgs.append("m11b_api FAIL:契约 %s 未定义" % name)
elif not inspect.iscoroutinefunction(fn):
ok = False
msgs.append("m11b_api FAIL:%s 非协程" % name)
if ok:
msgs.append("m11b_api PASS:%d 个协程契约齐备" % len(coros))
if not callable(assert_append_only):
ok = False
msgs.append("m11b_api FAIL:assert_append_only 不可调用")
else:
msgs.append("m11b_api PASS:assert_append_only 同步守卫可调用")
if sorted(_contracts().keys()) != sorted([
"apply_runtime_event", "assert_append_only", "broadcast_hub",
"ensure_forward_partitions", "pbl_runtime_broadcast_pull",
"pbl_runtime_broadcast_stats", "poll_events", "read_states"]):
ok = False
msgs.append("m11b_api FAIL:contracts 清单与注册表不一致 %r"
% sorted(_contracts().keys()))
else:
msgs.append("m11b_api PASS:contracts 清单 8 项与注册表一致")
if ok:
msgs.append("m11b_api.self_check PASS")
return ok, msgs