diag: 总页数未更新问题 — 增加Reconciliation诊断日志 + 修复keepCurrentWindow后pending不移除
1. RDEPUBPageMapReconciliationCoordinator: 在evaluateTakeover、
evaluateSegmentTakeover、evaluateFullPageMapTakeover的每个返回点
增加RDEPUBBackgroundTrace日志,记录关键决策参数:
- currentSpineIndex、candidateChapters/pages、currentChapters/pages
- hasPrev/hasNext、lastBuildableSpineIndex
- jumpSession protected coverage ratio
用于确认fullMap被拒绝的具体原因
2. RDEPUBPresentationRuntime: .keepCurrentWindow分支增加
removePendingPageMapUpdate(at: index),防止被拒绝的
reconcileFullMap update无限期留在pending队列中不被消费。
之前return false不移除,导致:
- 后续commitPendingPageMapUpdateIfNeeded重试时条件不变
仍然keepCurrentWindow,形成无效循环
- 如果用户不再翻页,总页数永远不更新
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
c555329948
commit
2fa58b1026
@ -28,8 +28,10 @@ final class RDEPUBPageMapReconciliationCoordinator {
|
||||
|
||||
guard let currentWindow else {
|
||||
if let candidatePageMap {
|
||||
RDEPUBBackgroundTrace.log("Reconciliation", "evaluateTakeover: no currentWindow, fullReplace candidateChapters=\(candidatePageMap.totalChapters) candidatePages=\(candidatePageMap.totalPages)")
|
||||
return .fullReplace(candidatePageMap)
|
||||
}
|
||||
RDEPUBBackgroundTrace.log("Reconciliation", "evaluateTakeover: no currentWindow, no candidate")
|
||||
return .keepCurrentWindow
|
||||
}
|
||||
|
||||
@ -54,7 +56,7 @@ final class RDEPUBPageMapReconciliationCoordinator {
|
||||
if coverageRatio < 0.8 {
|
||||
RDEPUBBackgroundTrace.log(
|
||||
"Reconciliation",
|
||||
"blocked: candidate doesn't cover protected area (coverage=\(coverageRatio))"
|
||||
"evaluateTakeover: blocked by jumpSession protection coverage=\(String(format: "%.2f", coverageRatio)) currentSpine=\(currentSpineIndex) protected=\(protectedIndices)"
|
||||
)
|
||||
return .keepCurrentWindow
|
||||
}
|
||||
@ -72,7 +74,7 @@ final class RDEPUBPageMapReconciliationCoordinator {
|
||||
if !hasPrev || !hasNext {
|
||||
RDEPUBBackgroundTrace.log(
|
||||
"Reconciliation",
|
||||
"blocked: missing adjacent chapter coverage"
|
||||
"evaluateTakeover: blocked by missing adjacent coverage (segment) currentSpine=\(currentSpineIndex) hasPrev=\(hasPrev) hasNext=\(hasNext)"
|
||||
)
|
||||
return .keepCurrentWindow
|
||||
}
|
||||
@ -85,7 +87,7 @@ final class RDEPUBPageMapReconciliationCoordinator {
|
||||
if candidateSegment.renderSignature != currentRenderSignature {
|
||||
RDEPUBBackgroundTrace.log(
|
||||
"Reconciliation",
|
||||
"blocked: render signature mismatch"
|
||||
"evaluateTakeover: blocked by render signature mismatch"
|
||||
)
|
||||
return .keepCurrentWindow
|
||||
}
|
||||
@ -109,6 +111,7 @@ final class RDEPUBPageMapReconciliationCoordinator {
|
||||
)
|
||||
}
|
||||
|
||||
RDEPUBBackgroundTrace.log("Reconciliation", "evaluateTakeover: no candidate, keepCurrentWindow")
|
||||
return .keepCurrentWindow
|
||||
}
|
||||
|
||||
@ -123,6 +126,10 @@ final class RDEPUBPageMapReconciliationCoordinator {
|
||||
|
||||
if let currentSpineIndex {
|
||||
if !candidateIndices.contains(currentSpineIndex) {
|
||||
RDEPUBBackgroundTrace.log(
|
||||
"Reconciliation",
|
||||
"evaluateSegmentTakeover: keepCurrentWindow — currentSpine=\(currentSpineIndex) not in candidate"
|
||||
)
|
||||
return .keepCurrentWindow
|
||||
}
|
||||
}
|
||||
@ -132,6 +139,10 @@ final class RDEPUBPageMapReconciliationCoordinator {
|
||||
let hasNext = candidateIndices.contains(currentSpineIndex + 1) ||
|
||||
currentSpineIndex == lastBuildableSpineIndex
|
||||
if !hasPrev || !hasNext {
|
||||
RDEPUBBackgroundTrace.log(
|
||||
"Reconciliation",
|
||||
"evaluateSegmentTakeover: keepCurrentWindow — missing adjacent spine=\(currentSpineIndex) hasPrev=\(hasPrev) hasNext=\(hasNext)"
|
||||
)
|
||||
return .keepCurrentWindow
|
||||
}
|
||||
}
|
||||
@ -164,9 +175,14 @@ final class RDEPUBPageMapReconciliationCoordinator {
|
||||
lastBuildableSpineIndex: Int
|
||||
) -> RDEPUBPageMapTakeoverDecision {
|
||||
let candidateIndices = Set(candidatePageMap.entries.map { $0.spineIndex })
|
||||
let currentEntries = currentWindow.entries.count
|
||||
|
||||
if let currentSpineIndex {
|
||||
if !candidateIndices.contains(currentSpineIndex) {
|
||||
RDEPUBBackgroundTrace.log(
|
||||
"Reconciliation",
|
||||
"evaluateFullPageMapTakeover: keepCurrentWindow — currentSpine=\(currentSpineIndex) not in candidate (candidateChapters=\(candidateIndices.count) currentChapters=\(currentEntries) candidatePages=\(candidatePageMap.totalPages) currentPages=\(currentWindow.totalPages))"
|
||||
)
|
||||
return .keepCurrentWindow
|
||||
}
|
||||
}
|
||||
@ -176,15 +192,27 @@ final class RDEPUBPageMapReconciliationCoordinator {
|
||||
let hasNext = candidateIndices.contains(currentSpineIndex + 1) ||
|
||||
currentSpineIndex == lastBuildableSpineIndex
|
||||
if !hasPrev || !hasNext {
|
||||
RDEPUBBackgroundTrace.log(
|
||||
"Reconciliation",
|
||||
"evaluateFullPageMapTakeover: keepCurrentWindow — missing adjacent spine=\(currentSpineIndex) hasPrev=\(hasPrev) hasNext=\(hasNext) lastBuildable=\(lastBuildableSpineIndex)"
|
||||
)
|
||||
return .keepCurrentWindow
|
||||
}
|
||||
}
|
||||
|
||||
let isComplete = candidateIndices.count >= currentWindow.entries.count
|
||||
let isComplete = candidateIndices.count >= currentEntries
|
||||
if isComplete {
|
||||
RDEPUBBackgroundTrace.log(
|
||||
"Reconciliation",
|
||||
"evaluateFullPageMapTakeover: fullReplace — candidateChapters=\(candidateIndices.count) currentChapters=\(currentEntries) candidatePages=\(candidatePageMap.totalPages) currentPages=\(currentWindow.totalPages)"
|
||||
)
|
||||
return .fullReplace(candidatePageMap)
|
||||
}
|
||||
|
||||
RDEPUBBackgroundTrace.log(
|
||||
"Reconciliation",
|
||||
"evaluateFullPageMapTakeover: keepCurrentWindow — candidateChapters=\(candidateIndices.count) < currentChapters=\(currentEntries)"
|
||||
)
|
||||
return .keepCurrentWindow
|
||||
}
|
||||
|
||||
|
||||
@ -226,7 +226,8 @@ final class RDEPUBPresentationRuntime {
|
||||
|
||||
switch decision {
|
||||
case .keepCurrentWindow:
|
||||
RDEPUBBackgroundTrace.log("Reconciliation", "decision: keepCurrentWindow")
|
||||
RDEPUBBackgroundTrace.log("Reconciliation", "decision: keepCurrentWindow — pending update removed to prevent indefinite retry")
|
||||
removePendingPageMapUpdate(at: index)
|
||||
return false
|
||||
|
||||
case .fullReplace(let newPageMap):
|
||||
|
||||
Loading…
Reference in New Issue
Block a user