{ "summary": [ { "name": "pbl_runtime_event", "title": "运行时事件流(append-only)", "primary": ["id"], "catelog": "entity", "comment": "【本表定位】world_sync 侧消费方契约副本:运行时事件流(append-only,禁 UPDATE/DELETE;生产库由权威模块 pbl_runtime_ext 的存储过程 pbl_assert_append_only + BEFORE UPDATE/BEFORE DELETE 触发器强制,本副本只声明列契约、不复制那套物理实现)。【结构权威源 · PM 裁决】PM 裁决(任务 u0EO4x3ajntR41acaHj5H)选 B:以 modules/pbl_runtime_ext/models/pbl_runtime_event.json 为唯一真源(M11b-1 已批准产物,本任务禁止反向修改);建表 DDL 派生源为该模块 scripts/pbl_runtime_event_ddl.py 与 scripts/migrations/*.sql。本文件是按真源逐字段内联的 world_sync 侧副本(25 列全量抄录),不是引用式 schema —— database-table-definition-spec 只承认 summary/fields/indexes/codes 四段式,scripts/validate_models_json.py 对 key=schema 引用式写法直接判 FAIL(QC #5),故 QC 要求内联。两份定义的一致性由 scripts/m11b2b_column_diff.py(代码列名 vs 权威列集双向 diff)与 scripts/m11b2b_selftest.py(四段式/抽象类型/主键/索引/编码 6 项断言 + 真源镜像 sha256)机械核对,真源列集变更时必须同步本副本。【id 生成方 · 单一口径,QC #4】本副本声明 id 由应用层生成:world_sync/pbl_runtime_tx.py::new_event_uid()(uuid4().hex,32 位小写十六进制),写路径 INSERT 列集(= 本文件 fields[] 全列,见 pbl_runtime_sql.py::EVENT_COLUMNS 由 fields[] 机械导出)显式提交 id,不依赖任何数据库 AUTO_INCREMENT。真源侧 id 为 type=long + auto_increment(BIGINT AUTO_INCREMENT),属其私有物理实现,本副本按 spec 归一为 str(32) 且不保留 auto_increment 键;两者差异已在 M11b-2b-B 交付件正文登记为 DEVIATION(WS-2) 并冒泡 agent.pm 裁决生产库列型收敛方案(改 VARCHAR(32) 或统一走 event_uid 定位),本副本不再同时声称两种生成方。对外幂等与跨系统追溯一律使用 event_uid(str 64,uk_event_uid),不依赖 id 的物理类型。【主键口径 · QC #2 归一,本副本无偏离】summary[0].primary=[\"id\"],严格遵循 spec「单键表 primary 恒为 [\\\"id\\\"]」,本副本不再声明复合主键、也不再自称任何偏离(旧版 primary=[\\\"id\\\",\\\"created_at\\\"] 属未登记偏离,QC #2 判定口径未闭环,已按改法 (a) 归一)。真源侧因按 created_at 做按月 RANGE COLUMNS 分区、受 MySQL/MariaDB 错误码 1503(分区表的每个唯一键必须包含分区列)约束而使用复合物理主键 (id, created_at)——该约束属物理实现,由真源 modules/pbl_runtime_ext/models/pbl_runtime_event.json:12(primary)与其 DDL 派生源(scripts/pbl_runtime_event_ddl.py、scripts/migrations/*.sql)表达,本副本不写 partition/engine/guards 等私有键,故不在逻辑契约里复制该复合主键。分区列约束在本副本中的等价表达是:两条唯一键 uk_event_uid(tenant_id,event_uid,created_at)、uk_tenant_idem(tenant_id,idem_key,created_at) 以及普通索引 ix_created_at(created_at) 均已包含 created_at,消费方按唯一键定位/幂等去重时天然满足「查询落在分区列上」的要求,不依赖主键形态。【私有键剥离】真源使用的 spec 未定义顶层扩展键 module/engine/charset/collate/tenant_scoped/append_only/write_paths/guards/partition/ddl_source,以及 fields[].ddl_type/comment/auto_increment、indexes[].comment、codes[].comment,本副本一律不保留:根键仅 summary/fields/indexes/codes,summary[0] 仅 name/title/primary/catelog/comment,fields[] 仅 name/title/type/length/dec/nullable/default,indexes[] 仅 name/idxtype/idxfields(主键不写进 indexes,由 summary[0].primary 表达),codes[] 仅 field/table/valuefield/textfield/cond。物理细节(分区、触发器、字符集、存储过程)以真源与其 DDL 派生源为准。【消费方清单】modules/world_sync/world_sync/pbl_runtime_sql.py(EVENT_TABLE/EVENT_COLUMNS,由本文件 fields[] 机械导出)、modules/world_sync/world_sync/pbl_runtime_tx.py::write_event_with_state(单事务事件+状态写入)、modules/world_sync/world_sync/pbl_runtime_authority.py(列契约解析层 + 本地/测试 DDL 渲染,已适配本内联四段式副本)、modules/world_sync/world_sync/init.py(事件写入门面)。上述代码引用的列名必须全部出现在本文件 fields[] 中,核对证据见 M11b-2b-B 交付件「字段交叉核对清单」与 scripts/m11b2b_column_diff_output.txt。【打包镜像】apps/scense/pkgs/world_sync/models/pbl_runtime_event.json 是本文件的打包镜像,只由 modules/world_sync/scripts/sync_models_mirror.py 生成,禁止手工双写;一致性由 scripts/m11b2b_selftest.py 的 A7 sha256 断言守护(改本文件后必须重跑 sync_models_mirror.py)。" } ], "fields": [ {"name": "id", "title": "主键ID(应用层生成)", "type": "str", "length": 32, "nullable": "no"}, {"name": "tenant_id", "title": "租户ID", "type": "str", "length": 32, "nullable": "no", "default": ""}, {"name": "event_uid", "title": "事件UID", "type": "str", "length": 64, "nullable": "no"}, {"name": "event_code", "title": "事件编码", "type": "str", "length": 64, "nullable": "no", "default": ""}, {"name": "idem_key", "title": "幂等键", "type": "str", "length": 128, "nullable": "no", "default": ""}, {"name": "world_id", "title": "世界ID", "type": "long", "nullable": "no", "default": 0}, {"name": "scene_id", "title": "场景/会话ID", "type": "long", "nullable": "no", "default": 0}, {"name": "session_id", "title": "游戏会话ID", "type": "long", "nullable": "no", "default": 0}, {"name": "entity_id", "title": "实体ID", "type": "str", "length": 64, "nullable": "no", "default": ""}, {"name": "actor_id", "title": "触发者", "type": "str", "length": 64, "nullable": "no", "default": ""}, {"name": "event_type", "title": "事件类型", "type": "str", "length": 64, "nullable": "no"}, {"name": "payload", "title": "事件负载", "type": "text", "nullable": "yes"}, {"name": "payload_json", "title": "事件负载JSON", "type": "text", "nullable": "yes"}, {"name": "causation_id", "title": "因果链", "type": "str", "length": 64, "nullable": "no", "default": ""}, {"name": "seq", "title": "会话内单调序号", "type": "long", "nullable": "no", "default": 0}, {"name": "seq_no", "title": "会话内单调序号(M11a)", "type": "long", "nullable": "no", "default": 0}, {"name": "source", "title": "来源", "type": "str", "length": 32, "nullable": "no", "default": "runtime"}, {"name": "state", "title": "事件状态", "type": "str", "length": 16, "nullable": "no", "default": "applied"}, {"name": "state_version", "title": "服务端权威版本", "type": "long", "nullable": "no", "default": 0}, {"name": "tx_group", "title": "事务组", "type": "str", "length": 64, "nullable": "no", "default": ""}, {"name": "broadcast", "title": "是否参与广播", "type": "short", "nullable": "no", "default": 1}, {"name": "created_by", "title": "创建人", "type": "long", "nullable": "no", "default": 0}, {"name": "created_at", "title": "创建时间", "type": "datetime", "nullable": "no", "default": "CURRENT_TIMESTAMP"}, {"name": "updated_at", "title": "记录时间戳", "type": "datetime", "nullable": "no", "default": "CURRENT_TIMESTAMP"}, {"name": "occurred_at", "title": "兼容列(旧分区键)", "type": "datetime", "nullable": "yes"} ], "indexes": [ {"name": "uk_event_uid", "idxtype": "unique", "idxfields": ["tenant_id", "event_uid", "created_at"]}, {"name": "uk_tenant_idem", "idxtype": "unique", "idxfields": ["tenant_id", "idem_key", "created_at"]}, {"name": "ix_scene_created", "idxtype": "index", "idxfields": ["scene_id", "created_at"]}, {"name": "ix_tenant_session_seq", "idxtype": "index", "idxfields": ["tenant_id", "session_id", "seq"]}, {"name": "ix_tenant_session_seqno", "idxtype": "index", "idxfields": ["tenant_id", "session_id", "seq_no"]}, {"name": "ix_tenant_world_type", "idxtype": "index", "idxfields": ["tenant_id", "world_id", "event_type"]}, {"name": "ix_tx_group", "idxtype": "index", "idxfields": ["tx_group"]}, {"name": "ix_created_at", "idxtype": "index", "idxfields": ["created_at"]} ], "codes": [ { "field": "event_type", "table": "appcodes_kv", "valuefield": "k", "textfield": "v", "cond": "parentid='pbl_event_type'" } ] }