存量用户初始额度改为 db.js 里的自动迁移
原计划是部署后上服务器手工执行一条 SQL 补额度,漏执行的后果是所有 存量用户的提醒立刻大面积降级。改成 PRAGMA user_version 驱动的一次性 自动迁移,部署即执行、不可能漏。 幂等性两层保证:user_version 版本号 + INSERT OR IGNORE 只补尚无记录的 openid,已有记录一律不覆盖。整段包在事务里。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -86,4 +86,50 @@ tryAddColumn('anniversaries', 'lunarMonth', 'INTEGER')
|
||||
tryAddColumn('anniversaries', 'lunarDay', 'INTEGER')
|
||||
tryAddColumn('anniversaries', 'isLeapMonth', 'INTEGER DEFAULT 0')
|
||||
|
||||
// ---- 版本化数据迁移 ----
|
||||
//
|
||||
// 用 SQLite 的 PRAGMA user_version 记录「这个库已经跑到第几版迁移」。
|
||||
// 它是存在数据库文件头里的一个整数,读写都随事务提交/回滚,天生适合做迁移标记
|
||||
// (见 MAINTENANCE.md 场景 11)。新增迁移的做法:写一个 migrateVN(),
|
||||
// 在 runMigrations 里加一行 `if (current < N) migrateVN()`,并把 SCHEMA_VERSION 改成 N。
|
||||
const SCHEMA_VERSION = 1
|
||||
|
||||
/**
|
||||
* v1:给存量用户补订阅额度初始值
|
||||
*
|
||||
* Why:subscribe_quota 是随「订阅消息额度治理」新建的表,所有存量用户余额都是 0。
|
||||
* 而 reminder.js 在余额为 0 时只会发一条探针,其余按优先级取舍——不补的话,
|
||||
* 后端一上线,老用户的提醒会立刻大面积降级,而他们手机上还是旧版小程序,
|
||||
* 根本没有补额度的入口。
|
||||
* 存量用户过去每存一条纪念日就授权过一次订阅,所以按「该用户的纪念日条数」
|
||||
* 估算初始余额是合理的(这也是原计划文档里那条手工 SQL 的口径)。
|
||||
* 做成代码里的自动迁移是为了「部署即执行」,不依赖人记得上服务器敲命令。
|
||||
*
|
||||
* 幂等性有两层保证:外层的 user_version 版本号(跑过就不再进来),
|
||||
* 以及 INSERT OR IGNORE(只给 subscribe_quota 里尚无记录的 openid 补,绝不覆盖已有记录)。
|
||||
*/
|
||||
function migrateV1() {
|
||||
db.prepare(`
|
||||
INSERT OR IGNORE INTO subscribe_quota (openid, balance, grantedTotal, sentTotal, updateTime)
|
||||
SELECT openid, COUNT(*), COUNT(*), 0, ?
|
||||
FROM anniversaries
|
||||
WHERE openid IS NOT NULL
|
||||
GROUP BY openid
|
||||
`).run(Date.now())
|
||||
}
|
||||
|
||||
function runMigrations() {
|
||||
const current = db.pragma('user_version', { simple: true })
|
||||
if (current >= SCHEMA_VERSION) return
|
||||
|
||||
// 整段包在事务里:迁移和版本号必须同生共死,中途崩了要能整体回滚重来
|
||||
db.transaction(() => {
|
||||
if (current < 1) migrateV1()
|
||||
db.pragma(`user_version = ${SCHEMA_VERSION}`)
|
||||
})()
|
||||
|
||||
console.log(`[db] 数据迁移完成: user_version ${current} -> ${SCHEMA_VERSION}`)
|
||||
}
|
||||
runMigrations()
|
||||
|
||||
module.exports = db
|
||||
|
||||
Reference in New Issue
Block a user