Files
next-tjwater-server/docs/peripheral-work-order-events.md
T

3.6 KiB

外围工单主动同步

工单的创建、编辑、现场反馈和删除改为由来源事件触发同步。浏览器继续使用已有工作台 SSE,不需要新增连接或定时工单轮询。

外围工单写入
  → 同一 PostgreSQL 事务保存源记录、历史版本和变更事件
  → COMMIT 后 NOTIFY
  → Server 工作台 SSE 唤醒外围同步器
  → 同步器通过授权 API 更新任务投影
  → task/action/notification 事件推送给浏览器

数据库范围

本次仅启用 tjwater_v2。没有新增表、列或迁移;复用 workbench.domain_event_log 的 workbench.work_order.changed topic。源事件的聚合类型为 peripheral_work_order,元数据只包含 source=peripheral_sample、工单 ID 和 created|updated|deleted,不包含工单正文。事务失败时,源记录、历史、事件及通知一起回滚;同一请求的幂等重放不再产生事件。

外围服务只写源记录及源变更事实,不直接改业务任务。任务投影、调查创建和通知仍通过 Server 状态机和现有授权 API 处理。其他数据库不写入该源事件;扩展前遵循 数据库变更门禁。事件表缺失或无写权限时,tjwater_v2 的工单写入返回存储错误,不会假装成功。

同步器

从 Server 仓库运行已有命令:

conda run -n server python scripts/sync_peripheral_work_orders.py
conda run -n server python scripts/sync_peripheral_work_orders.py --once

继续复用 OPERATIONAL_WORKER_* OAuth 工作身份及 OPERATIONAL_ACTION_PERIPHERAL_URL,不需要新账号或密钥。启动和游标过期时先读取事件游标,再进行全量对账;扫描期间的事件从该游标继续补读。相同源版本仍由原幂等键去重。同步器只被 peripheral_work_order 源事件唤醒,不被自己写出的任务投影事件再次唤醒。

正常状态收到源事件即扫描;无事件时默认每 300 秒对账一次,处理漏通知、断线、旧批量脚本直接写库及重启。可用 --reconcile-seconds 调整这一兜底周期(最小 1 秒),不再复用工况 worker 的 30 秒租约检查周期。同步失败按 5、10、20、40、60 秒退避重试;事件连接断开每 5 秒重试,保留最后游标。扫描开始前清除唤醒标记,扫描期间新到达的事件会触发下一轮,失败后的重试也不依赖新消息。

浏览器收到源事件时不会提前刷新业务快照,而是等待任务投影事件后读取对应任务。工况手动刷新仍只读 Server 权威快照。工单事件不等于 Header 通知;只有需要处理的业务待办或告警才进入通知列表。

验证与启用

conda run -n server python -m pytest tests/unit/test_peripheral_push_sync.py tests/unit/test_peripheral_work_order_events.py tests/unit/test_peripheral_task_sync.py -q
PERIPHERAL_SAMPLE_LIVE_TEST=1 conda run -n server python -m pytest tests/integration/test_peripheral_work_order_events.py -q

数据库测试强制限定 tjwater_v2,使用随机项目键和回滚事务,不保留测试工单或事件。覆盖创建、修改、反馈、删除、幂等重放及回滚无事件。HTTP 隔离测试覆盖源事件即时投影、游标重置、断线续传、失败重试和监听取消。

上线时更新外围服务、Server 同步器及前端,再按既有发布流程重启对应进程。提交代码不会自动重启现有服务;旧同步器进程仍按旧的 30 秒周期运行。回退应用代码不涉及数据结构回滚,已有事件仍可正常补读;回退到旧同步器后恢复周期对账。