Clone
4
Task-92-Sense旧设备能力JSONB兼容迁移
ila edited this page 2026-08-15 15:30:35 +08:00
This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 记录设备能力迁移排错。