diff --git a/docs/task/92-Sense旧设备能力JSONB兼容迁移.md b/docs/task/92-Sense旧设备能力JSONB兼容迁移.md index 8d5e172..453fad3 100644 --- a/docs/task/92-Sense旧设备能力JSONB兼容迁移.md +++ b/docs/task/92-Sense旧设备能力JSONB兼容迁移.md @@ -2,16 +2,16 @@ generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件) wiki_page: Task-92-Sense旧设备能力JSONB兼容迁移 wiki_url: https://git.ilapage.cn/ila/yovision/wiki/Task-92-Sense%E6%97%A7%E8%AE%BE%E5%A4%87%E8%83%BD%E5%8A%9BJSONB%E5%85%BC%E5%AE%B9%E8%BF%81%E7%A7%BB.- -wiki_revision: b2f12b3e5cf8a0db14b308a7adfe6caa4f05b537 -synchronized_at: 2026-08-15T07:18:09Z +wiki_revision: d10479f732597bd90dac4de03edc0cd4b39b6352 +synchronized_at: 2026-08-15T07:19:37Z # 92 Sense旧设备能力JSONB兼容迁移 -- 类型:需求 / 缺陷 / 重构 -- 所属 Epic:# -- 所属 MVP / 版本:# -- 状态:待验收 / 已完成 +- 类型:缺陷 +- 所属 Epic:#7 +- 所属 MVP / 版本:#8 +- 状态:待验收 - 日期:2026-08-15 - Gitea 工单:https://git.ilapage.cn/ila/yovision/issues/92 - Wiki 页面:Task-92-Sense旧设备能力JSONB兼容迁移 @@ -19,32 +19,56 @@ synchronized_at: 2026-08-15T07:18:09Z ## 背景与目标 - +用户通过 Windows 包启动 Sense 时,设备迁移报 PostgreSQL `SQLSTATE 42804`。只读诊断确认旧数据库的 `sense_devices.capabilities` 为 `text NOT NULL DEFAULT ''::text`,一条旧记录保存受支持的单值能力但不是 JSON;新模型要求 JSONB,GORM AutoMigrate 无法直接转换旧默认值和数据。 + +目标是在不删除设备、不跳过迁移、不修改当前用户数据库的前提下,为旧 schema 提供确定性、可回滚的 JSONB 兼容迁移。 ## 最终方案 - +在现有 `2026081414000` 设备迁移事务开头执行 PostgreSQL 专用兼容步骤。受影响数据库尚未登记该迁移版本,后置新版本无法越过失败点,因此兼容逻辑必须放在原失败迁移内。 + +兼容步骤只处理既有 text/varchar 列:取得 ACCESS EXCLUSIVE 表锁,读取并验证全部旧值后才开始改变默认值和数据。空值转为 `[]`;六种受支持旧单值转为单元素 JSON 数组;合法字符串数组规范化后保持语义。未知单值、对象、非字符串数组、未知数组元素和超过 16 项的数组会返回不含业务值的错误,整个事务回滚。 + +全部验证通过后删除旧 text 默认值,参数化更新规范 JSON,使用显式 `USING capabilities::jsonb` 转型并设置 `'[]'::jsonb` 默认值,再继续原有 GORM AutoMigrate、菜单、权限和迁移版本登记。非 PostgreSQL、表/列不存在以及已是 json/jsonb 时不执行旧值转换。 ## 修改文件 -- `<文件>`:<改动说明> +- `Sense/server/cmd/migrate/migration/version/2026081414000_device.go`:事务内旧 text 能力验证、转换、锁表和 JSONB 默认值处理。 +- `Sense/server/cmd/migrate/migration/version/2026081414000_device_test.go`:纯函数和隔离 PostgreSQL 17 回归,包括完整设备迁移与版本登记。 +- Wiki `Troubleshooting`、`docs/06-troubleshooting.md`:备份、重试、未知旧值和回退说明。 +- `wiki-docs.json`、`docs/task/92-Sense旧设备能力JSONB兼容迁移.md`:任务归档登记和镜像。 ## 验收结果 | 验收标准 | 结果 | |---|---| -| | 通过 / 未通过 | +| 旧 text 默认值不再触发 SQLSTATE 42804 | 通过;隔离 PostgreSQL 重现结构成功转为 jsonb | +| 旧单值无损转换为 JSONB 数组 | 通过;`video` 转为单元素数组 | +| 空值与合法数组正确处理 | 通过;空字符串转空数组,合法数组保持顺序与值 | +| 未知值拒绝且无半成品 | 通过;类型、默认值和已验证行均保持旧状态 | +| 新库、jsonb 和重复执行兼容 | 通过;无表跳过、jsonb 重复调用无操作 | +| 全量 Go 和迁移回归通过 | 通过 | +| 当前用户数据库未被修改 | 通过;仅执行只读诊断,写测试使用独立数据库并在结束后删除 | +| Wiki 与归档一致 | 受影响页面定向检查通过 | ## 测试 -- 执行命令:`<命令>` -- 结果: -- **未验证部分**: +- `go test ./cmd/migrate/migration/version -run TestCanonicalLegacyCapabilities -count=1 -v`:通过。 +- 隔离 PostgreSQL 17 `TestDeviceCapabilitiesMigrationOnPostgres`:旧单值/空值/合法数组、未知值事务回滚、无表、重复调用、完整设备迁移和 `sys_migration` 登记全部通过。 +- 隔离数据库 `sense92_migration_test` 测试前确认不存在,测试后确认计数为 0。 +- `go test ./...`、`go vet ./...`、`go build ./...`:通过。 +- `go test -race ./cmd/migrate/migration/version -run TestCanonicalLegacyCapabilities -count=1`:通过。 +- `git diff --check`:通过。 +- 受影响 Wiki 定向同步与检查:通过。 +- **未验证部分**:按工单安全边界未在当前用户 `sense` 数据库执行写迁移,也未替换当前 `Sense/dist` 中的待验收 #70 二进制;需先备份,再部署包含 #92 的新包进行最终启动验收。全量 Wiki 检查仍会先发现待验收 PR #89 的 #70 镜像尚未合入 `dev`。 ## 遗留问题 - +- 当前交付包仍含 #92 修复前的 `sense.exe`。#92 合入 `dev` 后需让 #70 交付分支吸收该提交并重新打包,用户备份数据库后再运行迁移。 +- Harness strict 的 #66/#67 既有归档格式问题不属于本工单。 ## 相关提交 -- `<提交哈希>` <提交说明> +- `68b436a` 兼容旧设备能力字段迁移。 +- `fe3badf` 覆盖旧设备完整迁移链。 +- `aee5f45` 记录设备能力迁移排错。