"""事件出口的行为契约。 两个已知形态差别在可靠性要求上:一个把进度逐步回写业务数据库供前端轮询(要求低延迟、 可以丢),一个把审计事件送进日志管道(要求不丢、可以慢)。 ## 写这份文件时撞出来的、`design/0006` 还答不上的问题 `Event` 只有一个名字,没有字段,所以这个接缝的契约现在只能验「投递失败不打断循环」这一半, 验不了「发出去的事件里有什么」。 """ import pytest pytestmark = pytest.mark.contract async def test_emit_accepts_an_event(event_sink, records): """能收下一个事件,正常路径不抛异常。""" await event_sink.emit(records.event()) async def test_delivery_failure_does_not_break_the_caller(event_sink, records): """投递失败由库捕获、记日志、把失败计数加一,然后继续跑。 一次运行不该因为进度回写的数据库连不上就终止——事件是观察通道,不是控制通道。 这条测试面对的是一个必然投递失败的出口,断言它不会把异常泄漏成循环的终止条件。 """ await event_sink.emit(records.event(kind="always-fails")) @pytest.mark.xfail(reason="事件集还没定,见 docstring", strict=True) def test_failure_is_not_re_emitted_through_the_same_sink(): """投递失败不再转成一条事件从同一个出口发出去。 那会自我喂食:一个持续失败的出口会让失败处理路径变成递归,而递归的表现是进程卡住或 栈溢出,不是一条错误日志。 **这条现在验不了**,因为验它要求能识别「这是一条失败事件」,而 `Event` 还没有字段—— `design/0006` 里它只有一个名字。方向已经定了(观察走事件流、干预走具名回调),但事件 集与回调清单要独立成一份 design doc,这条要等到那时候。 """ pytest.fail("Event 还没有字段,识别不了「失败事件」") @pytest.mark.xfail(reason="事件集还没定,见 docstring", strict=True) def test_audit_events_carry_both_raw_and_repaired_model_output(): """审计事件要同时带模型原文与修复之后的结果。 GovDoc 有一条硬纪律:agent 的原始输出、修复后的输出、恢复来源全程留痕,禁止静默修复。 它现有的审计出口是一个「发一条带类型和载荷的事件」的接口,迁移之后这条纪律要由事件流 承载——能不能承载,取决于事件里带不带这两样。 这是 `../research-wiki/migrations/govdoc-saas.md` 缺口登记里那一条,同样等事件集定下来。 """ pytest.fail("Event 还没有字段,承载不了审计纪律")