5.0 KiB
5.0 KiB
| name | description |
|---|---|
| world_sync | world_sync 模块技能文档。 |
world_sync 模块
概述
世界数据同步模块,管理世界数据的导入/导出/合并同步记录与执行。依赖 world 模块(world 表)、appbase(appcodes 字典 sync_type/sync_status)。通过 load_world_sync() 挂载。
自 M11b-2/M11b-3 起,本模块同时承载 scense_runtime 服务端权威写入薄扩展:单事务事件+状态写入(pbl_runtime_authority.write_event_with_state)与事务提交后广播(pbl_runtime_broadcast)。
数据模型
表 world_sync(models/world_sync.json)
| 字段 | 类型 | 说明 |
|---|---|---|
| id | str(32) | 主键 |
| world_id | str(32) | 所属世界(→world.id) |
| sync_type | str(16) | 同步类型(0导入/1导出/2合并) |
| source | str(255) | 数据来源 |
| status | str(16) | 状态(appcodes sync_status) |
| result_json | text | 同步结果 JSON |
| sync_date | date | 同步日期(业务日期) |
| created_at | timestamp | 创建时间 |
- 主键:["id"];索引:idx_sync_world(world_id)
- 字典:world_id→world、sync_type→appcodes_kv(parentid='sync_type')、status→appcodes_kv(parentid='sync_status')
运行时权威表(M11b-2,models/)
pbl_runtime_event(append-only 事件)、pbl_entity_state(实体状态,state_version 服务端权威)、
pbl_world_state_snapshot(世界快照)。所有读写强制 tenant_id 打头,缺失 fail-closed。
关键接口
- list_world_syncs / get_world_sync / create_world_sync / update_world_sync / delete_world_sync / execute_world_sync
- wwwroot/api/world_sync.dspy(同步契约)、create/world_sync_update/world_sync_delete.dspy、get_search_*.dspy
- M11b-2:
write_event_with_state(event_data, state_update, ...)—— 事件 + 状态在同一事务内提交 - M11b-3 广播 API(
world_sync/pbl_runtime_broadcast.py,已在__init__.py导出):install_broadcast_hook()/is_broadcast_hook_installed():把write_event_with_state包成 COMMIT 后广播(幂等,load_world_sync()已自动调用)emit_post_commit_broadcast(write_result, context=...):手动发一条wrap_with_post_commit_broadcast(fn):包装任意返回事务结果的函数configure_broadcast(channels=..., webhook_urls=..., redis_url=..., queue_size=2000, retry_attempts=2, retry_backoff_s=0.02, enabled=True):宿主启动时配置通道subscribe_broadcast(handler)/unsubscribe_broadcast(handler):进程内订阅broadcast_stats()/broadcast_last_message()/broadcast_latency_percentile_ms(99)/drain_broadcast(timeout=2.0)/shutdown_broadcast():观测与优雅退出- 通道类:
InProcessChannel、WebhookChannel、RedisPubSubChannel、NoopChannel(均继承BaseChannel,publish(message))
事务提交后广播(M11b-3)要点
- 触发点:仅事务 COMMIT 成功之后(
commit_ts即延迟起点);事务回滚不广播。 - 异步:单 dispatcher 线程 + 有界
queue.Queue(2000),submit用put_nowait微秒返回,不阻塞事务返回;队列满降级为当前线程直发一次。 - SLO:
BROADCAST_LATENCY_SLO_MS = 300.0,口径 P99;实测 n=200 p50=2.4ms / p99=4.1ms / max=4.2ms(scripts/m11b3_selftest_output.txt)。 - 失败语义:fire-and-forget + 有限重试;通道/订阅者异常一律吞掉并
ERROR日志 +stats["failed"]计数,绝不回滚已提交事务、绝不外抛给业务调用方。 - 无轮询:广播路径不含
time.sleep轮询、不读 DB;等待靠Queue.get(block=True)条件变量。 - 环境变量:
PBL_BROADCAST_DISABLED(全局关闭)、PBL_BROADCAST_WEBHOOK_URLS(逗号分隔 webhook)、PBL_BROADCAST_REDIS_ENABLED+PBL_BROADCAST_REDIS_URL(Redis pub/sub)。
陷阱
- 库名不硬编码:.py 用 ServerEnv().get_module_dbname('world_sync'),.dspy 用 get_sor_context(request._run_ns,'world_sync')
- dspy 无 import
- create/execute 必须设置 created_at、sync_date,否则 sor.C 静默丢记录
- update 剔除 _text 后缀
- codes.table 引用 world 不用 module.table 点号
- 广播 hook 幂等:
install_broadcast_hook()重复调用不得重复包装(已用__wrapped_post_commit__标记),否则一条事件广播多次 - 广播内禁止再写事务/再发广播:dispatcher 线程只做 publish,回写 DB 会造成递归与延迟失真
- 测试断言前用
drain_broadcast()等待,禁止 sleep 轮询(QC 会按「引入轮询」退回) RedisPubSubChannel惰性 importredis:环境缺包只ChannelUnavailable跳过,不影响 InProcess/webhook 通道,不要让 Redis 成为硬依赖scripts/sync_code_to_app.py的collect()必须以WS_ROOT拼绝对路径 —— 用相对路径isdir会恒返回空清单,导致--check打印假 PASS(M11b-3 已修,改脚本时勿回退)
依赖
- world、appbase、rbac
- M11b-2/M11b-3 广播零第三方硬依赖(stdlib:threading/queue/urllib/hashlib;redis 可选)