熟悉度系统渐进式部署指南

部署策略

采用渐进式升级策略,确保线上服务不受影响:

✅ 第一阶段:添加新字段(当前阶段)

目标:添加 familiarity 字段,但不破坏现有逻辑

实现

  1. ✅ 在数据库中添加 familiarity 字段(默认 0)
  2. ✅ 保留所有 status 相关逻辑
  3. ✅ API 同时更新 statusfamiliarity
  4. ✅ 前端优先使用 familiarity,不存在时回退到 status

部署步骤

# 1. 更新数据库 schema
pnpm db:push

# 2. 验证数据库
pnpm db:studio
# 检查 study_item 表是否有 familiarity 字段

# 3. 部署代码
git add .
git commit -m "feat: add familiarity field with backward compatibility"
git push

# 4. 观察线上表现
# - 检查 API 是否正常工作
# - 检查是否同时更新了 status 和 familiarity
# - 检查排序是否正确

回滚方案

  • 如果出现问题,只需回滚代码
  • familiarity 字段可以保留(不影响旧逻辑)
  • status 字段始终保持更新,数据不会丢失

📊 第二阶段:数据迁移(稳定后执行)

目标:将现有 status 数据迁移到 familiarity

SQL 脚本

-- 一次性转换现有数据
UPDATE study_item
SET familiarity = CASE
  WHEN status = 0 THEN 0   -- 待学习 → 0%
  WHEN status = 1 THEN 20  -- 陌生 → 20%
  WHEN status = 2 THEN 40  -- 模糊 → 40%
  WHEN status = 3 THEN 60  -- 认识 → 60%
  WHEN status = 4 THEN 80  -- 熟识 → 80%
  ELSE 0
END
WHERE familiarity = 0 OR familiarity IS NULL;

执行时机

  • 第一阶段部署稳定运行 1-2 周后
  • 确认没有重大问题
  • 选择低峰期执行

🔮 第三阶段:逐步废弃 status(未来规划)

目标:完全切换到 familiarity,废弃 status

步骤

  1. 观察 familiarity 使用情况(1-2 个月)
  2. 确认所有新功能都基于 familiarity
  3. 标记 status 为 deprecated
  4. 逐步移除 status 相关代码
  5. (可选)最终删除 status 字段

⚠️ 注意:第三阶段可能在半年或更久之后,不着急执行

向后兼容机制

前端回退逻辑

const getFamiliarity = (word: Word) => {
  // 优先使用 familiarity
  if (word.familiarity && word.familiarity > 0) {
    return word.familiarity;
  }

  // 回退到 status 映射
  switch (word.status) {
    case 0: return 0;   // 待学习
    case 1: return 20;  // 陌生
    case 2: return 40;  // 模糊
    case 3: return 60;  // 认识
    case 4: return 80;  // 熟识
    default: return 0;
  }
};

API 双写策略

create: {
  status: mark.known ? 3 : 0,      // 继续更新 status
  familiarity: mark.known ? 60 : 20, // 同时更新 familiarity
},
update: {
  status: mark.known ? 3 : 0,      // 继续更新 status
  familiarity: Math.max(0, Math.min(100,
    (existing?.familiarity ?? 0) + (mark.known ? 10 : -5)
  )), // 累积更新 familiarity
}

监控指标

第一阶段监控

  • API 响应时间是否正常
  • 数据库写入是否成功(status + familiarity)
  • 用户标记单词是否正常
  • 排序是否符合预期
  • 错误日志是否有异常

第二阶段监控

  • 迁移脚本执行时间
  • 数据一致性检查
  • familiarity 分布是否合理
  • 用户学习体验是否改善

测试检查清单

部署前测试

  • 新用户标记单词(familiarity 从 0 开始)
  • 老用户标记单词(status 已存在)
  • 单词排序是否正确
  • 统计数据是否准确
  • 单词详情对话框是否正常
  • 熟悉度进度条是否显示

部署后验证

  • 在生产环境标记几个单词
  • 检查数据库中 status 和 familiarity 是否都更新了
  • 刷新页面,排序是否保持正确
  • 尝试"换一批"功能
  • 检查错误日志

风险评估

低风险 ✅

  • ✅ 添加新字段不影响现有逻辑
  • ✅ 保留 status 作为后备
  • ✅ 前端有回退机制
  • ✅ API 双写保证数据完整

中风险 ⚠️

  • ⚠️ 数据库字段增加,查询性能可能轻微下降
    • 缓解:添加了索引
  • ⚠️ API 需要多写一个字段
    • 缓解:影响很小,可以忽略

可控风险 🛡️

  • 🛡️ 用户看到的排序可能发生变化
    • 缓解:逐步生效,用户可以适应
  • 🛡️ 熟悉度更新算法可能需要调整
    • 缓解:可以通过后续更新优化

回滚计划

快速回滚(5 分钟内)

如果发现严重问题:

# 1. 回滚到上一个版本
git revert HEAD
git push

# 2. 验证服务恢复
curl https://your-domain.com/api/health

# 3. 通知团队

数据回滚(如果需要)

-- 不需要删除 familiarity 字段
-- 只要代码回滚,familiarity 就不会被使用
-- status 始终保持更新,数据完整

常见问题

Q: 如果 familiarity 更新失败怎么办?

A: status 仍然会正常更新,前端会回退到 status 显示,不影响用户使用。

Q: 老数据的 familiarity 都是 0,会不会有问题?

A: 不会。前端会检测到 familiarity 为 0,自动使用 status 映射值。

Q: 什么时候完全切换到 familiarity?

A: 至少等待 1-2 个月稳定运行后,观察数据质量和用户反馈,再考虑废弃 status。

Q: 如果想调整熟悉度更新算法怎么办?

A: 只需修改 API 中的增量值(目前是 +10/-5),不需要迁移数据。

成功标准

第一阶段部署成功的标准:

  • ✅ 零错误日志
  • ✅ API 响应时间 < 200ms
  • ✅ 用户可以正常标记单词
  • ✅ 排序逻辑正确
  • ✅ 统计数据准确
  • ✅ 运行稳定 1 周以上

达到以上标准后,可以考虑进入第二阶段。