Răsfoiți Sursa

docs: 记录 2026-10-31 夜间同步核查结果(身份冲突阻塞、未完成)

彭峰 1 zi în urmă
părinte
comite
1395f7fad2

+ 19 - 0
.workbuddy/memory/2026-10-31.md

@@ -0,0 +1,19 @@
+# 2026-10-31
+
+## 建立每日 23:00 旧系统同步核查自动化
+- 自动化 ID `5c1de505-9c7f-4206-9fa4-125f086de0f7`,RRULE `FREQ=DAILY;BYHOUR=23;BYMINUTE=0`,首次触发 2026-11-01 23:00 CST。
+- 定位:只监测系统 LaunchAgent `cn.xiaoshu.legacy-direct-sync-nightly`,不重复启动同步、不走同步桥、不抢服务器租约、不删有效目录锁。
+- 辅助脚本 `tmp/direct-v1-status-check.mjs`(gitignored):只 POST `action:'status'` 到 `<XIAOSHU_FUNCTION_URL>/xiaoshu/sync/direct-v1`,输出脱敏,不 claim、不建锁。
+
+## 当晚(业务日 2026-10-31)实际状态
+- LaunchAgent 真实 23:00 触发,服务端 runId `579148c2-4320-46e7-9304-8bf38498a481`,started 15:00:06Z,finishedAt 仍为 null,服务端状态 `running`。
+- 本地每 5 分钟重试,23:30 报告显示 `blocked / legacy_account_identity_conflict`,账号 `source 749, matched 744, conflicts 170, identityConflicts 1`;其余整点重试为 `another_sync_running`。
+- 运行缓存目录 `direct-579148c2.../` 为空,9 个业务数据集未产生任何分页进度。
+- 对比:业务日 2026-10-30 成功(identityConflicts 0、failed 0、9 数据集 reconciled=true、财务 42136 行 reconciled、保留冲突 4193),完成于 2026-10-31 00:06。
+- 结论:identityConflicts 由 0 变 1 是相对昨日的重大失败变化,属硬阻塞(阅读账号生成编号与旧系统身份冲突),不会自动恢复。
+
+## 补记(00:28 收尾)
+- 10 分钟间隔轮询 4 次(23:58/00:08/00:18/00:28):服务端始终 `running` + `finishedAt=null`,本地重试始终 `blocked / legacy_account_identity_conflict`,零进展。
+- 9 个业务数据集全部未执行(缓存目录为空),账号 source 749 / matched 744 / conflicts 170 / identityConflicts 1,栏目 461/461,财务未执行,failed=1,settlementReady=false。
+- 交付:`docs/migration/nightly-legacy-sync-check-2026-10-31.md`、私有 `heartbeat-23-status-2026-10-31.json`(0600)。
+- 风险:该 run 仍持服务端租约,零点后 2026-11-01 业务日重试一律 `another_sync_running`;未删锁、未抢租约。需人工核实这 1 处身份冲突(参照 10-30 授权退休 1869/1870 占用账号的做法)。

+ 65 - 0
docs/migration/nightly-legacy-sync-check-2026-10-31.md

@@ -0,0 +1,65 @@
+# 夜间同步核查记录(业务日 2026-10-31)
+
+核查窗口:北京时间 2026-10-31 23:43 — 2026-11-01 00:28。本轮只监测,不重复执行、不走同步桥、不抢占租约、不删除目录锁。
+
+## 结论
+
+**业务日 2026-10-31 的夜间同步未完成,判定为「阻塞 / 未完成」,没有服务端成功回执。**
+
+- 真实 23:00 触发已发生:服务端 runId `579148c2-4320-46e7-9304-8bf38498a481`,`startedAt = 2026-10-31T15:00:06.098Z`(北京时间 23:00:06),`finishedAt` 至今为 `null`。
+- 服务端状态仍显示 `running`,但没有任何完成回执、没有 `summary`、没有 9 个数据集的 `reconciled` 记录。这属于「挂起」而非「成功」,不能按成功计。
+- 本机同一 runId 每 5 分钟重试一次,全部以 `blocked / legacy_account_identity_conflict` 结束;零点后的重试(业务日已翻为 2026-11-01)返回 `another_sync_running`,因为旧运行仍持有服务端租约。
+- 10 分钟间隔、连续 4 次轮询(23:58 / 00:08 / 00:18 / 00:28)状态零变化,阻塞为确定性原因,不会自行恢复。
+
+## 阻塞根因
+
+`legacy_account_identity_conflict: resolve reading-generated IDs before syncing business records`
+
+账号补缺阶段发现 1 处身份冲突:某个旧系统用户编号被新系统中「阅读账号生成的编号」占用。按既定保护策略(阅读账号生成的编号不能代表旧系统身份),同步在投影任何业务数据之前即停止,避免把真实学员的课程挂到阅读账号上。
+
+| 项目 | 2026-10-30(上次成功) | 2026-10-31(本次) | 变化 |
+| --- | ---: | ---: | --- |
+| 源账号数 | 748 | 749 | +1 |
+| 已匹配 | 744 | 744 | 0 |
+| 账号资料差异(保留冲突) | 167 | 170 | +3 |
+| 身份冲突 identityConflicts | 0 | 1 | **+1** |
+| 已排除(已删除 / SyncExcluded) | 4 | 4 | 0 |
+| 终态 | completed-with-preserved-conflicts | blocked(未完成) | 成功 → 失败 |
+
+2026-10-30 晚间的同类冲突(旧编号 1869 / 1870 与阅读账号 熊紫羽 / 彭宇哲高三 相撞)是在用户明确授权退休这两个阅读账号后才解除的,运行于 2026-10-31 00:06 完成。本次冲突尚未经人工核实与决策,因此任务停在原地。
+
+## 9 个业务数据集核验结果
+
+全部未执行。运行缓存目录 `direct-579148c2-4320-46e7-9304-8bf38498a481/` 为空,日志中没有产生任何分页进度行。
+
+| 数据集 | 是否执行 | 服务端 reconciled |
+| --- | --- | --- |
+| 专项训练 | 否 | 否 |
+| 词库 | 否 | 否 |
+| 课程绑定 | 否 | 否 |
+| 每日学习 | 否 | 否 |
+| 练习 | 否 | 否 |
+| 抗遗忘 | 否 | 否 |
+| 预约 | 否 | 否 |
+| 上课 | 否 | 否 |
+| 测评 | 否 | 否 |
+
+- 账号:源 749、新增 0、匹配 744、缺失 0、排除 4、保留冲突 170、身份冲突 1;现有账户余额未改动(`existingAccountBalancesUntouched: true`)。
+- 栏目:源 461、新增 0、匹配 461、缺失 0(只补缺,符合策略)。
+- 财务分组(会员流水 stype=1/2/3/4):未执行,无回读核对。
+- `failed = 1`,`settlementReady = false`,冲突只记录未自动解决,来源 `old-api/WXAPP`、`bridgeUsed = false`。
+
+## 本机任务与日志证据
+
+- LaunchAgent `cn.xiaoshu.legacy-direct-sync-nightly`:program 为 `/usr/local/bin/node --env-file=… /Users/mac/Library/Application Support/XiaoshuSync/scripts/run-nightly-direct-sync.mjs --scheduled`,`TZ=Asia/Shanghai`,日历触发 `Hour=23 / Minute=0`,`runs = 25`,`last exit code = 1`。配置项与要求一致。
+- `launchagent.log` 尾部重复出现 `blocked / legacy_account_identity_conflict`(runId 579148c2)与 `another_sync_running` 交替。
+- `launchagent-error.log` 最后写入时间为 2026-10-19,今晚没有新的进程级异常;历史 `ERR_MODULE_NOT_FOUND: sync-alerts.mjs` 已不存在(该模块已于 2026-10-15 安装到位),不是本次阻塞原因。
+- 告警状态 `direct-alert-state.json`:`{"failed":true,"lastKey":"failure","conflicts":4193,...}`。
+
+## 需要人工决策的事项
+
+1. 核实今晚新增的那 1 处身份冲突:确认该旧系统编号对应的真实学员,并决定是退休/停用占用的阅读账号,还是保留冲突不做投影。2026-10-30 用的是「授权退休冲突账号」这条路。
+2. 该运行仍持有服务端租约;在它被收口之前,2026-11-01 业务日的夜间同步同样会以 `another_sync_running` 被挡住。本核查按约束未删除锁、未抢占租约、未做任何写操作。
+3. 未设置 `settlementReady`;工资结算仍不能使用本结果,也不能用它替代专项核验。
+
+私有运行报告位于 `~/.local/state/xiaoshu/legacy-sync/2026-10-31-direct-579148c2-4320-46e7-9304-8bf38498a481.json`,心跳文件为同目录 `heartbeat-23-status-2026-10-31.json`(0600)。报告与本文档均不含任何凭据内容。