- 范围:全仓除已完成的 game-cloud/game-admin(及排除区);91 文件 - cn.iocoder.yudao→com.wanxiang.huijing / cn.wanxiang.game→com.wanxiang.huijing.game / cn.iocoder.cloud→com.wanxiang / Yudao*→Huijing* / bare yudao→huijing - 含 contracts/api-schemas(apiInterface FQCN)、docs/architecture+agent-specs(含中文名,git ls-files -z 修复)、AGENTS.md/CLAUDE.md 等根文档 - 保留不动:上游归属 URL(gitee/github yudaocode·YunaiV,改则断链+违反署名)、game-cloud Flyway 迁移注释(保 checksum)、lockfile(装包重生) - 纯文档/字符串,零构建影响(game-cloud/game-admin 字节码未动) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
114 lines
12 KiB
SQL
114 lines
12 KiB
SQL
-- =============================================================================
|
||
-- 契约 #2 DB 迁移 | 模块:runtime(编译 / 沙箱预览 / 试玩会话)| owner:WS3
|
||
-- 文件:V3.0.0__create_game_runtime.sql(Flyway,只新增;已合入禁止修改,回滚写新补偿迁移)
|
||
-- 内容:runtime 模块核心表 —— 编译任务 / 版本运行包 / 试玩会话
|
||
-- 约定:InnoDB + utf8mb4;显式列;含 Huijing 审计列 + tenant_id;状态机用 tinyint,非法流转由服务端拒绝
|
||
-- 错误码段:runtime = 1-102-***-***
|
||
--
|
||
-- 脊柱对接(闭环贯通):
|
||
-- - 上游输入:GamePackage(契约 #4)。game_id/version_id 关联 project.game_project / game_version。
|
||
-- - 对外产物:game_runtime_package 为「试玩宿主」提供包清单(manifest URL + checksum + 预加载策略,对齐 #4 manifest 段)。
|
||
-- - 宿主↔游戏边界:postMessage(契约 #3)由宿主落地,本模块不建表承载。
|
||
-- - 试玩会话:game_runtime_session 记录 play_start/play_end/duration_ms,供回灌 telemetry(契约 #5,telemetry 模块消费)。
|
||
--
|
||
-- MVP 范围纪律:只建编译/运行包/会话三表。渠道转换、云游戏容器属"扩"远期,不建表。
|
||
-- =============================================================================
|
||
|
||
-- -----------------------------------------------------------------------------
|
||
-- 表:game_runtime_build —— 编译任务表(GameConfig→版本化运行包,异步幂等任务)
|
||
-- 状态机 status:0排队 → 1编译中 →(2成功 / 3失败)
|
||
-- 合法流转由 RuntimeBuildService 校验,DO 层不承载校验
|
||
-- 编译消费该 version 的 GamePackage(#4),做 GameConfig 静态校验(T-RT-16)/体积门禁(T-RT-08)/打包(T-RT-02)/版本化上传(T-RT-03)
|
||
-- -----------------------------------------------------------------------------
|
||
CREATE TABLE `game_runtime_build` (
|
||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '编译任务 ID(buildId)',
|
||
`game_id` BIGINT NOT NULL COMMENT '游戏 ID(project.game_project.id)',
|
||
`version_id` BIGINT NOT NULL COMMENT '版本 ID(project.game_version.id = GamePackage.versionId)',
|
||
`template_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '玩法模板 ID(决定 Runtime 容器/校验规则)',
|
||
`status` TINYINT NOT NULL DEFAULT 0 COMMENT '编译状态机:0排队 1编译中 2成功 3失败',
|
||
`package_url` VARCHAR(512) NOT NULL DEFAULT '' COMMENT '产出 GamePackage(manifest)OSS/CDN URL(成功时回写,对齐 #4 manifest)',
|
||
`bundle_size` BIGINT NOT NULL DEFAULT 0 COMMENT '包总字节(体积门禁 T-RT-08:≤10MB;首屏≤2MB 由编译期单独校验)',
|
||
`checksum` CHAR(64) NOT NULL DEFAULT '' COMMENT '整包 sha256(hex,#4 manifest.checksum,完整性校验)',
|
||
`trace_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '链路追踪 trace_id(贯穿 生成→编译→加载→运行,T-RT-28)',
|
||
`fail_code` VARCHAR(16) NOT NULL DEFAULT '' COMMENT '失败错误码(如 1-102-002-001 GameConfig校验失败 / 1-102-002-002 体积超限;成功为空)',
|
||
`fail_reason` VARCHAR(500) NOT NULL DEFAULT '' COMMENT '失败原因(回填运营,成功为空)',
|
||
`finish_time` DATETIME NULL COMMENT '编译完成时间(成功/失败均记)',
|
||
`creator` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建者(Huijing 审计列)',
|
||
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||
`updater` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '更新者',
|
||
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||
`deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '逻辑删除:0未删 1已删',
|
||
`tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户 ID(Huijing 多租户兼容,MVP 单租户=0)',
|
||
PRIMARY KEY (`id`),
|
||
KEY `idx_version_status` (`version_id`, `status`) COMMENT '同版本编译幂等:查进行中/已成功任务复用',
|
||
KEY `idx_game_create` (`game_id`, `create_time`) COMMENT '按游戏查编译历史'
|
||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = 'runtime 编译任务表';
|
||
|
||
-- -----------------------------------------------------------------------------
|
||
-- 表:game_runtime_package —— 版本运行包表(对外清单:试玩宿主据此加载 + 校验)
|
||
-- 一个 version 对应一行就绪运行包(编译成功后 upsert);字段语义对齐 GamePackage(#4).manifest
|
||
-- 宿主据此渲染 iframe(T-RT-04/06)、做 Manifest 完整性校验(T-RT-15)、桥接 SDK(#3)
|
||
-- 取包门禁(决策1):status 为取包权威判定字段——scene=preview 放行 status∈{0,1},scene=play 仅放行 status=1,
|
||
-- 与 project.game_version.status 不混用。status 0→1(已发布)由 publish 对接点回写,并同步置 game_version.status=3。
|
||
-- 写权属(决策5):package_url/checksum/bundle_size 的权威写者 = runtime 编译成功后回写(与本表同源),
|
||
-- 同步回写 project.game_version 同名字段;aigc 只回填 version_id,不写这些 manifest 字段。
|
||
-- -----------------------------------------------------------------------------
|
||
CREATE TABLE `game_runtime_package` (
|
||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '运行包 ID',
|
||
`game_id` BIGINT NOT NULL COMMENT '游戏 ID',
|
||
`version_id` BIGINT NOT NULL COMMENT '版本 ID(与 build 同源,对外清单主键语义)',
|
||
`template_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '玩法模板 ID(宿主据此选 Runtime 容器)',
|
||
`package_url` VARCHAR(512) NOT NULL DEFAULT '' COMMENT 'GamePackage(manifest)OSS/CDN URL,按 /games/{gameId}/versions/{versionId}/ 版本化(#4)。决策5:runtime 编译成功后回写为权威源,并同步回写 project.game_version.package_url;aigc 只回填 version_id,不写此字段',
|
||
`entry` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '入口文件相对路径(#4 manifest.entry)',
|
||
`runtime_version` VARCHAR(32) NOT NULL DEFAULT '' COMMENT '目标 WanxiangGameSDK / Canvas Runtime 版本(semver,#4 manifest.runtimeVersion)',
|
||
`preload_policy` VARCHAR(8) NOT NULL DEFAULT 'lazy' COMMENT '预加载策略(三容器,#4 manifest.preloadPolicy):eager 进容器即加载 / lazy 可见时加载',
|
||
`bundle_size` BIGINT NOT NULL DEFAULT 0 COMMENT '包总字节(#4 manifest.bundleSize)。决策5:runtime 编译成功后回写为权威源,并同步回写 project.game_version.bundle_size;aigc 不写此字段',
|
||
`checksum` CHAR(64) NOT NULL DEFAULT '' COMMENT '整包 sha256(hex,#4 manifest.checksum,宿主完整性校验 T-RT-15)。决策5:runtime 编译成功后回写为权威源,并同步回写 project.game_version.checksum;aigc 不写此字段',
|
||
`sandbox_attr` VARCHAR(255) NOT NULL DEFAULT 'allow-scripts' COMMENT 'iframe sandbox 属性值(沙箱隔离 T-RT-04,宿主据此设置)',
|
||
`allow_origins` VARCHAR(512) NOT NULL DEFAULT '' COMMENT 'postMessage 允许 origin 白名单(逗号分隔,宿主侧 #3 双校验 T-RT-14)',
|
||
`status` TINYINT NOT NULL DEFAULT 0 COMMENT '运行包状态(取包门禁权威判定字段,非 project.game_version.status):0预览就绪(编译成功回写,scene=preview 放行)1已发布(scene=play 仅放行此态,玩家可试玩)2已失效(下架/版本被替换)。0→1 由 publish 对接点 POST /admin-api/runtime/package/{versionId}/publish 在发布编排成功后回写,并同步置 project.game_version.status=3',
|
||
`creator` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建者',
|
||
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||
`updater` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '更新者',
|
||
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||
`deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '逻辑删除',
|
||
`tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户 ID',
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uk_version` (`version_id`, `deleted`, `tenant_id`) COMMENT '一个版本一行就绪运行包(含 deleted 容逻辑删除重建)',
|
||
KEY `idx_game_status` (`game_id`, `status`) COMMENT '按游戏取就绪/已发布运行包'
|
||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = 'runtime 版本运行包表(对外清单)';
|
||
|
||
-- -----------------------------------------------------------------------------
|
||
-- 表:game_runtime_session —— 试玩会话表(脊柱:play_start/play_end/时长 → 回灌 telemetry)
|
||
-- 状态机 status:0进行中 →(1已结束 / 2异常)
|
||
-- start 落一行(play_start),end 写 play_end + duration_ms(服务端以 end-start 为准)
|
||
-- client_play_token 幂等:同 token 不重复建会话
|
||
-- 口径(决策3):runtime session 仅作时长/质量观测,不计 play_count;
|
||
-- play_count 权威源 = telemetry 的 game_play_start 事件聚合(见 telemetry V5.0.0 / telemetry.yaml)。
|
||
-- 约定 sessionId(BIGINT) 透传进 telemetry envelope.session_id(int64→string)作对账键。
|
||
-- -----------------------------------------------------------------------------
|
||
CREATE TABLE `game_runtime_session` (
|
||
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '试玩会话 ID(sessionId,本局唯一键,贯穿 end 与 telemetry 回灌;透传进 telemetry envelope.session_id 转 string 作对账键,不计 play_count)',
|
||
`game_id` BIGINT NOT NULL COMMENT '游戏 ID',
|
||
`version_id` BIGINT NOT NULL COMMENT '版本 ID',
|
||
`player_user_id` BIGINT NOT NULL COMMENT '试玩玩家用户 ID(DataPermission;预览场景=创作者本人)',
|
||
`client_play_token` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '客户端本局唯一 token(幂等键,防抖/重连不重复计数)',
|
||
`scene` VARCHAR(8) NOT NULL DEFAULT 'play' COMMENT '场景:preview 创作者预览 / play 玩家试玩',
|
||
`status` TINYINT NOT NULL DEFAULT 0 COMMENT '会话状态机:0进行中 1已结束 2异常(加载/心跳超时或运行错误)',
|
||
`duration_ms` BIGINT NOT NULL DEFAULT 0 COMMENT '本局时长毫秒(服务端 play_end-play_start;进行中=0)',
|
||
`end_reason` VARCHAR(16) NOT NULL DEFAULT '' COMMENT '结束原因:game_end 正常 / quit 退出 / error 运行错误 / timeout 超时(进行中为空)',
|
||
`trace_id` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '链路追踪 trace_id(透传至 telemetry 回灌,#3 init / #5 事件)',
|
||
`start_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'play_start 开局时间',
|
||
`end_time` DATETIME NULL COMMENT 'play_end 结束时间(进行中为空)',
|
||
`creator` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建者',
|
||
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
|
||
`updater` VARCHAR(64) NOT NULL DEFAULT '' COMMENT '更新者',
|
||
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||
`deleted` BIT(1) NOT NULL DEFAULT b'0' COMMENT '逻辑删除',
|
||
`tenant_id` BIGINT NOT NULL DEFAULT 0 COMMENT '租户 ID',
|
||
PRIMARY KEY (`id`),
|
||
UNIQUE KEY `uk_play_token` (`client_play_token`, `tenant_id`) COMMENT '本局 token 幂等:同 token 只建一个会话',
|
||
KEY `idx_game_version` (`game_id`, `version_id`, `create_time`) COMMENT '按游戏/版本查会话(质量观测/回灌核对)',
|
||
KEY `idx_status_create` (`status`, `create_time`) COMMENT '扫描进行中超时会话(置异常)/ 按状态分页'
|
||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = 'runtime 试玩会话表(回灌 telemetry 源)';
|