deliver: 交付收口(引擎代为提交)
This commit is contained in:
parent
f9c91ee724
commit
fc359f8dc5
@ -1,23 +1,28 @@
|
||||
{
|
||||
"key": "schema",
|
||||
"schema": {
|
||||
"table": "pbl_entity_state",
|
||||
"authority_module": "pbl_runtime_ext",
|
||||
"authority_path": "modules/pbl_runtime_ext/models/pbl_entity_state.json",
|
||||
"owner": "pbls",
|
||||
"milestone": "M11b-2b",
|
||||
"decision_ref": "PM 裁决(任务 u0EO4x3ajntR41acaHj5H 问答):选 B —— 以 pbl_runtime_ext 为唯一真源",
|
||||
"decision_basis": [
|
||||
"设计文档 docs/01-design/modules/entity.md 明确 pbl_entity_state 为 pbl_runtime_ext 侧、pbls 所有",
|
||||
"world_sync 仅作为单事务写入的消费方,不拥有该表结构定义权",
|
||||
"本任务不得反向修改 M11b-1 已批准产物"
|
||||
],
|
||||
"structure_note": "本文件不再自带 summary/fields/indexes/codes 结构体;列集、主键、索引一律以 authority_path 指向的 pbl_runtime_ext 定义为准。world_sync 侧消费方代码(pbl_runtime_sql.py / pbl_runtime_tx.py::write_event_with_state / pbl_runtime_schema.py)以该权威结构为准,不再依赖旧的 8 列本地结构。",
|
||||
"consumers": [
|
||||
"modules/world_sync/world_sync/pbl_runtime_sql.py",
|
||||
"modules/world_sync/world_sync/pbl_runtime_tx.py::write_event_with_state",
|
||||
"modules/world_sync/world_sync/pbl_runtime_schema.py"
|
||||
],
|
||||
"mirror_note": "apps/scense/pkgs/world_sync/models/pbl_entity_state.json 是本文件的打包镜像,只由 modules/world_sync/scripts/sync_models_mirror.py 生成,禁止手工双写;一致性由 modules/world_sync/scripts/m11b2b_selftest.py 的 sha256 断言守护。"
|
||||
"summary": [
|
||||
{
|
||||
"name": "pbl_entity_state",
|
||||
"title": "实体状态(服务端权威)",
|
||||
"primary": ["id"],
|
||||
"catelog": "entity",
|
||||
"comment": "【本表定位 · world_sync 侧内联副本】实体状态表(服务端权威:state_version 单调递增,客户端禁写;由 world_sync 单事务写入路径 write_event_with_state 与事件行同事务更新,乐观锁冲突映射为 ConcurrentStateConflict)。【结构权威源 · PM 裁决】PM 裁决(任务 u0EO4x3ajntR41acaHj5H 问答):选 B —— 以 pbl_runtime_ext 为唯一真源;结构权威定义位于 modules/pbl_runtime_ext/models/pbl_entity_state.json(M11b-1 已批准产物,本任务禁止反向修改),建表 DDL 归该模块所有,本文件不复制其物理实现细节。world_sync 仅作为单事务写入的消费方,不拥有该表结构定义权。【为什么是内联而不是引用】database-table-definition-spec 只承认 summary/fields/indexes/codes 四段式;scripts/validate_models_json.py(M11b-2a 子任务 A 修复版)对 key=schema 引用式写法直接判 FAIL(QC #5),故本文件按真源逐字段内联权威列集(真源实为 10 列:tenant_id/id/session_id/entity_id/state_json/state_version/checksum/updated_by/created_at/updated_at,任务书所述「8 列」系早期口径,以真源实测为准),作为 world_sync 侧的消费方契约视图;一致性由 scripts/m11b2b_column_diff.py 与 scripts/m11b2b_selftest.py 机械核对,真源变更时必须同步本副本。【抽象类型归一说明】真源使用物理类型写法(id=int(20) unsigned auto_increment、session_id/state_version=bigint、state_json=json),本副本按 spec 归一为抽象类型(long/text),不保留 unsigned/length 物理修饰;bigint→long、json→text(存 JSON 文本,由应用层 json.dumps/loads)。【id 类型偏离处理 · 本子任务的选择与理由】真源 id 为自增 BIGINT 主键(真源侧以 auto_increment/unsigned 私有键表达该偏离);子任务 A 的最终登记表 COMPLIANCE_DEVIATIONS 为空 {}(A 按 QC #5 选 (a):不放行任何历史失效项),且本任务范围明确禁止修改校验器脚本,因此 world_sync 侧不走「登记放行 id 非 str(32)」路线,而是内联为 spec 合规写法 type=str / length=32、不带 auto_increment 键,主键值由应用层生成 32 位 uuid 去横线十六进制串(world_sync/pbl_runtime_tx.py::new_event_uid 同族工具函数);与真源的 id 类型差异由 world_sync 侧消费方代码适配:写路径 INSERT 不显式提交 id(见 pbl_runtime_tx.py 状态行 INSERT 列集 cols 不含 id),生产 MySQL 交由真源 DDL 的 AUTO_INCREMENT 生成 BIGINT,本地/测试库(authority 层渲染的 sqlite DDL)使用应用层生成的 str(32)。此差异为有意选择、非疏漏,评审请勿据此判为结构缺陷。【主键与唯一键说明】真源 summary[0] 未声明 primary,其物理主键由 indexes 中 PRIMARY(id) 表达,故本副本 primary=[\"id\"],并把真源 uk_es(tenant_id+session_id+entity_id 唯一键,即消费方定位键 STATE_KEY_COLUMNS)内联为 idxtype=unique;实体状态定位键为 tenant_id + session_id + entity_id,本表无 event_uid 概念。【消费方清单】modules/world_sync/world_sync/pbl_runtime_sql.py(STATE_TABLE/STATE_COLUMNS)、modules/world_sync/world_sync/pbl_runtime_tx.py::write_event_with_state(_fetch_state_version/_update_state/_insert_state)、modules/world_sync/world_sync/pbl_runtime_authority.py(列契约解析层);上述代码引用的列名必须全部出现在本文件 fields[] 中。【打包镜像说明】apps/scense/pkgs/world_sync/models/pbl_entity_state.json 是本文件的打包镜像,只由 modules/world_sync/scripts/sync_models_mirror.py 生成,禁止手工双写;一致性由 modules/world_sync/scripts/m11b2b_selftest.py 的 sha256 断言守护。【私有键剥离说明】真源使用的 spec 未定义键 summary[0].module/engine/charset/tenant_scoped、fields[].comment/null/unsigned/auto_increment、indexes[].unique/fields,在本副本中一律不保留或已归一为 spec 键(nullable/idxtype/idxfields);本文件根键仅 summary/fields/indexes/codes,codes 段本表无枚举编码列故为空数组。"
|
||||
}
|
||||
],
|
||||
"fields": [
|
||||
{"name": "tenant_id", "title": "租户ID", "type": "str", "length": 32, "nullable": "no"},
|
||||
{"name": "id", "title": "主键ID(应用层生成)", "type": "str", "length": 32, "nullable": "no"},
|
||||
{"name": "session_id", "title": "会话", "type": "long", "nullable": "no"},
|
||||
{"name": "entity_id", "title": "实体标识", "type": "str", "length": 32, "nullable": "no"},
|
||||
{"name": "state_json", "title": "状态JSON", "type": "text", "nullable": "yes"},
|
||||
{"name": "state_version", "title": "单调版本", "type": "long", "nullable": "no"},
|
||||
{"name": "checksum", "title": "状态摘要", "type": "str", "length": 32, "nullable": "no"},
|
||||
{"name": "updated_by", "title": "写入者", "type": "str", "length": 32, "nullable": "no"},
|
||||
{"name": "created_at", "title": "创建时间", "type": "datetime", "nullable": "no"},
|
||||
{"name": "updated_at", "title": "更新时间", "type": "datetime", "nullable": "no"}
|
||||
],
|
||||
"indexes": [
|
||||
{"name": "PRIMARY", "idxtype": "unique", "idxfields": ["id"]},
|
||||
{"name": "uk_es", "idxtype": "unique", "idxfields": ["tenant_id", "session_id", "entity_id"]}
|
||||
],
|
||||
"codes": []
|
||||
}
|
||||
|
||||
@ -1,24 +1,57 @@
|
||||
{
|
||||
"key": "schema",
|
||||
"schema": {
|
||||
"table": "pbl_runtime_event",
|
||||
"authority_module": "pbl_runtime_ext",
|
||||
"authority_path": "modules/pbl_runtime_ext/models/pbl_runtime_event.json",
|
||||
"owner": "pbls",
|
||||
"milestone": "M11b-2b",
|
||||
"decision_ref": "PM 裁决(任务 u0EO4x3ajntR41acaHj5H 问答):选 B —— 以 pbl_runtime_ext 为唯一真源",
|
||||
"decision_basis": [
|
||||
"任务书原文:在 M11b-1 产出的 pbl_runtime_event 表基础上(依赖 key=schema),引用语义自任务定义起即为 B",
|
||||
"设计文档 docs/01-design/modules/entity.md 明确该表为 pbl_runtime_ext 侧、pbls 所有",
|
||||
"pbl_runtime_ext 侧 pbl_runtime_event 的 DDL + 3 个迁移文件 + dev-notes 均已 approved,为既定权威结构",
|
||||
"本任务不得反向修改 M11b-1 已批准产物"
|
||||
],
|
||||
"structure_note": "本文件不再自带 summary/fields/indexes/codes 结构体;列集、主键、索引、分区、append-only 约束一律以 authority_path 指向的 pbl_runtime_ext 定义为准(25 列 / id long 自增 + (id, created_at) 复合主键 / 按月 RANGE COLUMNS 分区 / append-only 触发器)。world_sync 侧消费方代码(pbl_runtime_sql.py / pbl_runtime_tx.py::write_event_with_state / pbl_runtime_schema.py)以该 25 列权威结构为准,不再依赖旧的 12 列本地结构。",
|
||||
"consumers": [
|
||||
"modules/world_sync/world_sync/pbl_runtime_sql.py",
|
||||
"modules/world_sync/world_sync/pbl_runtime_tx.py::write_event_with_state",
|
||||
"modules/world_sync/world_sync/pbl_runtime_schema.py"
|
||||
],
|
||||
"mirror_note": "apps/scense/pkgs/world_sync/models/pbl_runtime_event.json 是本文件的打包镜像,只由 modules/world_sync/scripts/sync_models_mirror.py 生成,禁止手工双写;一致性由 modules/world_sync/scripts/m11b2b_selftest.py 的 sha256 断言守护。"
|
||||
"summary": [
|
||||
{
|
||||
"name": "pbl_runtime_event",
|
||||
"title": "运行时事件流(append-only)",
|
||||
"primary": ["id", "created_at"],
|
||||
"catelog": "entity",
|
||||
"comment": "【本表定位 · world_sync 侧内联副本】运行时事件流(append-only:禁 UPDATE/DELETE,由权威模块 pbl_runtime_ext 的存储过程 pbl_assert_append_only + BEFORE UPDATE/BEFORE DELETE 触发器强制;按 created_at 做按月 RANGE COLUMNS(created_at) 分区,分区保留 14 个月)。物理主键为复合主键 (id, created_at) —— MySQL/MariaDB 要求分区表的所有唯一键(含主键)必须包含分区列,否则建表报错 1503。【结构权威源 · PM 裁决】PM 裁决(任务 u0EO4x3ajntR41acaHj5H 问答):选 B —— 以 pbl_runtime_ext 为唯一真源;结构权威定义位于 modules/pbl_runtime_ext/models/pbl_runtime_event.json(M11b-1 已批准产物,本任务禁止反向修改),DDL 派生源为该模块 scripts/pbl_runtime_event_ddl.py 与 scripts/migrations/*.sql,建表/分区/触发器归 pbl_runtime_ext 所有,本文件不复制那套逻辑。【为什么是内联而不是引用】database-table-definition-spec 只承认 summary/fields/indexes/codes 四段式;scripts/validate_models_json.py(M11b-2a 子任务 A 修复版)对 key=schema 引用式写法直接判 FAIL(QC #5),故本文件按真源逐字段内联权威列集,作为 world_sync 侧的消费方契约视图;两份定义的一致性由 scripts/m11b2b_column_diff.py 与 scripts/m11b2b_selftest.py 机械核对,真源列集变更时必须同步本副本。【id 类型偏离处理 · 本子任务的选择与理由】真源 id 为 type=long + auto_increment(BIGINT AUTO_INCREMENT,真源侧已在其 summary[0].comment 自行登记该偏离);子任务 A 的最终登记表 COMPLIANCE_DEVIATIONS 为空 {}(A 按 QC #5 选 (a):不放行任何历史失效项),且本任务范围明确禁止修改校验器脚本,因此 world_sync 侧不再走「登记放行 id=long」路线,而是内联为 spec 合规写法 type=str / length=32、不带 auto_increment 键,由应用层生成 32 位 uuid 去横线十六进制串作为主键值(见 world_sync/pbl_runtime_tx.py::new_event_uid,正是 uuid4().hex 32 位)。与真源的 id 类型差异由 world_sync 侧消费方代码适配:写路径 INSERT 不显式提交 id 时交由真源 DDL 的 AUTO_INCREMENT 生成(BIGINT),本地/测试库(scripts 渲染的 sqlite DDL)则使用应用层生成的 str(32);对外幂等与跨系统追溯一律使用 event_uid(str 64,uk_event_uid 唯一键),不依赖 id 的物理类型。此差异为有意选择、非疏漏,评审请勿据此判为结构缺陷。【消费方清单】modules/world_sync/world_sync/pbl_runtime_sql.py(EVENT_TABLE/EVENT_COLUMNS)、modules/world_sync/world_sync/pbl_runtime_tx.py::write_event_with_state(单事务事件+状态写入)、modules/world_sync/world_sync/pbl_runtime_authority.py(列契约解析层);上述代码引用的列名必须全部出现在本文件 fields[] 中。【打包镜像说明】apps/scense/pkgs/world_sync/models/pbl_runtime_event.json 是本文件的打包镜像,只由 modules/world_sync/scripts/sync_models_mirror.py 生成,禁止手工双写;一致性由 modules/world_sync/scripts/m11b2b_selftest.py 的 sha256 断言守护。【私有键剥离说明】真源使用的 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,codes[] 仅 field/table/valuefield/textfield/cond);这些物理实现细节以真源与其 DDL 派生源为准。"
|
||||
}
|
||||
],
|
||||
"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'"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user