fix(import): 复用口径忠实化;管道 Outcome 契约与 succeeded_with_issues;报告写入时序;stale 警告
评审修复(Plan 3 Task 1 复审):
- 复用路径只返回 job 锚定字段(jobId/status/reused/siteId/mapping_version/
report_path),快照/版本块仅在非复用时解析返回——复用结果不再回显编造数据
- ImportPipeline 契约钉死:返回 Promise<ImportPipelineOutcome>
({ counts, issues });服务按"累加器 ⊕ 返回值"合并(counts 同键返回值
覆盖、issues 累加器在前),issues 非空 → succeeded_with_issues;
ctx.report 即累加器(管道抛错时部分产出仍入报告)
- 报告时序:mkdir + tmp 写入 + rename 先于终态行更新——report_path 落库
即文件存在;写失败 → failed(REPORT_WRITE_FAILED),不挂悬空路径
- CLI 复用命中非终态(queued/running)→ 崩溃残留警告(重试需显式换 --key)
- 管道抛 ImportError 保留原 code 入 error_code,summary 冠 [pipeline]
- 确定性 23505 探针:未提交孪生 job 行事务内持唯一键触发真实 PG 唯一
冲突 → 败者复用既有 job
- 报告补 idempotencyKey / attempt 字段
- 计划文档 Task 6 增补 stale 回收决策项(ADR-017)
测试 282 通过(279 + 3:Outcome 合并/ImportError 前缀/23505 探针);
typecheck 四段链 + lint 全绿。
Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
+20
-10
@@ -180,18 +180,28 @@ program
|
||||
console.log(
|
||||
`[import] job=${result.jobId} status=${result.status}${result.reused ? '(复用既有 job,未重跑)' : ''}`,
|
||||
)
|
||||
console.log(` site=${result.siteKey} connection=${result.connectionId}`)
|
||||
console.log(
|
||||
` wxr 快照: ${result.wxrSnapshot.sha256.slice(0, 12)}… (${result.wxrSnapshot.id})`,
|
||||
)
|
||||
console.log(
|
||||
` media_bundle: ${result.mediaBundleSnapshot === null ? '(无)' : result.mediaBundleSnapshot.id} / manual_url_list: ${result.manualUrlListSnapshot === null ? '(无)' : result.manualUrlListSnapshot.id}`,
|
||||
)
|
||||
console.log(
|
||||
` 版本: adapter=${result.versions.adapter} mapping=${result.versions.mapping} sanitizer=${result.versions.sanitizer} parser=${result.versions.parser}`,
|
||||
)
|
||||
console.log(` site=${opts.site} mapping_version=${result.mappingVersion}`)
|
||||
// 复用口径忠实化:快照/版本块只在新跑时解析返回——复用时权威记录在既有 job 报告。
|
||||
// 非复用路径结构性填满这些可选字段(服务侧不变量),此处非空断言表达该约定
|
||||
if (!result.reused) {
|
||||
console.log(` connection=${result.connectionId!}`)
|
||||
console.log(
|
||||
` wxr 快照: ${result.wxrSnapshot!.sha256.slice(0, 12)}… (${result.wxrSnapshot!.id})`,
|
||||
)
|
||||
console.log(
|
||||
` media_bundle: ${result.mediaBundleSnapshot! === null ? '(无)' : result.mediaBundleSnapshot!.id} / manual_url_list: ${result.manualUrlListSnapshot! === null ? '(无)' : result.manualUrlListSnapshot!.id}`,
|
||||
)
|
||||
console.log(
|
||||
` 版本: adapter=${result.versions!.adapter} mapping=${result.versions!.mapping} sanitizer=${result.versions!.sanitizer} parser=${result.versions!.parser}`,
|
||||
)
|
||||
}
|
||||
if (result.reportPath !== null) console.log(` report: ${result.reportPath}`)
|
||||
console.log(` total ${result.durationMs.toFixed(1)}ms`)
|
||||
// 崩溃残留哨兵:复用命中非终态(queued/running)= 上一次执行未走完终态更新——
|
||||
// 本命令不自动重跑(幂等纪律),操作者显式换 --key 才发起新执行
|
||||
if (result.reused && (result.status === 'queued' || result.status === 'running')) {
|
||||
console.error(` 警告:job 处于 ${result.status}——可能为崩溃残留,重试请显式换 --key`)
|
||||
}
|
||||
if (result.status === 'failed') process.exitCode = 1
|
||||
} finally {
|
||||
await (db as { $client: { end: () => Promise<void> } }).$client.end()
|
||||
|
||||
Reference in New Issue
Block a user