nightly-legacy-sync.md 7.1 KB

每天 23:00 的旧系统同步任务

时区固定 Asia/Shanghai,每晚 23:00 从旧系统读取并同步到新系统。客户继续使用旧站;保留新系统修改,记录冲突,不自动覆盖冲突、删除新系统记录或修改账户课时余额。

2026-10-11 核查

此前没有启用 23 点调度:本机 crontab 为空,没有小树 LaunchAgent 或已保存的 Codex 定时任务;仓库只有默认每 5 秒运行的 worker service 示例,不代表生产已经安装。不能读取远程服务器的调度器,因此不能断言所有服务器上都没有任务。

当日生产复查:旧同步桥健康接口仍 HTTP 404,当前帐套 LegacySyncCheckpoint 为 0,未解决冲突为 684,失败队列为 0。普通管理员访问同步状态返回 403;普通管理员不能作为同步执行账号。上次手动补同步和本地脚本验证不等于夜间任务上线。

随后使用已有有效超级管理员会话查询成功,云端明确返回 configured=false、bridgeReachable=false,所有数据集最近尝试和成功时间均为空。当前已将该执行会话保存到本机专用环境文件 /Users/mac/.config/xiaoshu/legacy-sync-nightly.env(0600),不包含主密钥;会话到期时间为 2027-09-09T04:36:34.414Z。账户权限不再是本次阻塞,桥部署与云端配置仍未就绪。不要把该环境文件提交或复制进报告。

已通过应用工具创建并回读当前聊天的每日 23:00 自动任务,ID 为 23。它检查正式任务运行结果;尚未上线时核查同步条件,满足后执行 npm run sync-worker:nightly,不满足就持久保存失败原因。此聊天任务依赖电脑开机和应用运行,不能替代服务器调度。

2026-10-11 首次夜间调度已触发:23:02 查询生产状态,仍未配置且当晚成功数据集为 0;正式运行入口返回 blocked / bridge_http_404,报告已保存。用户已选择由托管方代部署同步桥,交接要求见 托管方代部署工单。该工单和发布包已经准备,可直接交给托管方;尚未发送给外部联系人,也未取得托管方执行回执。

执行入口与成功标准

npm run sync-worker:nightly -- --check 仅验收前提;npm run sync-worker:nightly 执行一轮。运行报告默认保存在 ~/.local/state/xiaoshu/legacy-sync/,使用北京时间业务日期和唯一运行 ID,每次记录起止、状态、原因及各数据集计数;文件权限 0600。缺配置或接口故障也必须留下失败报告。

本机聊天任务使用支持 --env-file 的 Node.js 20.6+:node --env-file=/Users/mac/.config/xiaoshu/legacy-sync-nightly.env scripts/run-nightly-legacy-sync.mjs,不要把凭据写到命令行参数或输出中。2026-10-11 已实跑 --check,得到 blocked / bridge_http_404,失败报告已保存。8 项自动测试验证了 404/凭据过期/未配置/保护缺失时不写数据、多轮分页和依赖顺序、未追平不报成功、冲突保留及缺少对账证据不报成功。

运行器先检查健康服务身份、超级管理员凭据、签名 manifest 和冲突保护,再按固定依赖顺序分页,直到每个数据集 hasMore=false。最多 45 分钟、每数据集 200 轮。只读请求最多重试三次;写请求超时不盲目重发,下次通过服务器 checkpoint 续跑。并发运行由目录锁阻止;进程被强制杀死后的残留锁必须先确认原进程已退出再人工移除,不能直接强制并发。

当前云端代码只对部分教学记录有保护,尚未验收所有数据集“保留新修改”,不能仅凭健康恢复就启动覆盖同步。网关需实现并通过并发更新、主附表原子性、冲突保留、重跑幂等验证后,才可在 ops/sync/status 返回 syncProtection: { conflictPolicy: 'preserve-new', atomicProjection: true }。运行器缺少这一证据即停止,不能在客户端设置标记绕过。

同步后再次检查签名 manifest、失败和冲突;服务端须对各数据集做同水位业务 ID 集合与校验和核验,实际一致后返回每数据集 reconciled=true。仅计数相同或有检查点不足以通过。未解决冲突保留新数据并报告 completed_with_conflicts;没有对账证据报告 awaiting_reconciliation,均不宣称全部成功。

默认范围为栏目、词库、专项训练、课程绑定、每日学习、练习、抗遗忘、测评、预约、上课,共 10 个数据集。账户/余额/课时归新系统管理,当前网关明确拒绝 users 同步;旧站新增用户须另做只新增、身份匹配、禁止财务覆盖的接口验收后才能加入任务,不能直接放开原 users 全字段覆盖。

完成上线的次序

  1. 取得当前可用主机发布入口或托管方代部署。修正旧站域名下 IIS /xiaoshu-sync 独立应用;按桥 README 备份、预检。在桥和消费端准备就绪后安装 SQL 变更日志,验证健康、签名 manifest 和 11 个 changes 查询。
  2. 服务端安全配置桥 URL、HMAC KeyId/Secret、出口 IP,保持旧系统写入关闭。配置专用超级管理员同步身份和到期/轮换处理;不提升普通运营账号权限。所有密钥放服务端环境,不进 Git 或任务提示词。
  3. 完成上述云端冲突保护、原子性和 ID/校验和对账;通过 --check 后执行一次真实同步。对 684 条现存冲突保留并分别复核,禁止自动标记解决。
  4. 把下列 timer/service 安装到持续运行的新系统 Linux 主机,先确认现有持续 worker 的状态和业务依赖,再切换调度,避免两个入口重复同步。不要未经评估直接停掉已有持续 worker;工资结算的两分钟新鲜度要求与每天一次的节奏不同,夜间任务不能放宽此限制。
  5. 验证服务器 timer 的下一次触发时间,完成一次人工触发和第一次真实 23 点运行验收,再把聊天任务调整为核查服务器结果。失败通过现有运维监控告警,记录运行报告;还需配置并验证告警渠道,不能把日志文件等同通知已送达。

服务器安装模板(尚未远程安装)

将仓库放到 /opt/xiaoshu-angular,环境放 /etc/xiaoshu/legacy-sync-worker.env,文件权限 0600,执行用户 xiaoshu 必须能读取。环境需含 XIAOSHU_SYNC_OPERATOR_TOKEN、XIAOSHU_SYNC_COMPANY_ID、XIAOSHU_FUNCTION_URL、XIAOSHU_LEGACY_SYNC_BASE_URL。执行:

sudo install -m 0644 deployment/systemd/xiaoshu-legacy-sync-nightly.service /etc/systemd/system/
sudo install -m 0644 deployment/systemd/xiaoshu-legacy-sync-nightly.timer /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl start xiaoshu-legacy-sync-nightly.service
sudo systemctl enable --now xiaoshu-legacy-sync-nightly.timer
systemctl list-timers xiaoshu-legacy-sync-nightly.timer
journalctl -u xiaoshu-legacy-sync-nightly.service --since today

人工运行失败时先处理报告,不把 timer 已启用视为同步已成功。Persistent=true 允许主机恢复后补触发错过的运行;服务器必须支持该带时区的 OnCalendar 表达式,并以服务器实际 list-timers 输出验收。