Files
yovision/docs/task/92-Sense旧设备能力JSONB兼容迁移.md
T

5.2 KiB
Raw Blame History

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: cbdcc65c2b7da74048713d49dcb4b49b47cec17e synchronized_at: 2026-08-15T07:30:56Z

92 Sense旧设备能力JSONB兼容迁移

  • 类型:缺陷
  • 所属 Epic:#7
  • 所属 MVP / 版本:#8
  • 状态:已完成
  • 日期:2026-08-15
  • Gitea 工单:#92
  • Wiki 页面:Task-92-Sense旧设备能力JSONB兼容迁移
  • Wiki revision:见本地镜像头

背景与目标

用户通过 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。

用户验收

  • 用户于 2026-08-15 明确确认 #92 验收通过。
  • 实现 PR #93 已合入 dev,合并提交为 eaa6ae081542b0b9c74cc2d92a9138639fdbe530。
  • #92 已完成;真实数据库备份、交付包重建与启动回归继续在 #70 的交付闭环中执行。

遗留问题

  • 当前交付包仍含 #92 修复前的 sense.exe。#92 合入 dev 后需让 #70 交付分支吸收该提交并重新打包,用户备份数据库后再运行迁移。
  • Harness strict 的 #66/#67 既有归档格式问题不属于本工单。

相关提交

  • 68b436a 兼容旧设备能力字段迁移。
  • fe3badf 覆盖旧设备完整迁移链。
  • aee5f45 记录设备能力迁移排错。