fix(android): 修复 markPartyReady 重试逻辑的循环退出Bug [CRITICAL]
## 发现的新Bug(从用户日志) ``` 16:19:03.667 Successfully marked party ready on attempt 2 ✅ 16:19:03.716 markPartyReady attempt 3 failed: cannot transition to ready status ❌ 16:19:03.731 markPartyReady attempt 4 failed: cannot transition to ready status ❌ 16:19:03.749 markPartyReady attempt 5 failed: cannot transition to ready status ❌ 16:19:03.750 Cancelled job: progress_collection 💀 ``` ## 根本原因 Kotlin `repeat` 的陷阱: - `return@repeat` 只是跳过当前迭代 - **不会退出整个循环** - 导致第2次成功后,第3、4、5次继续执行 - 服务器返回 "already ready, cannot transition" - 第5次失败,代码认为所有尝试都失败,停止 keygen ## 修复内容 在每次迭代开始时检查成功标志: ```kotlin repeat(5) { attempt -> if (markReadySuccess) return@repeat // ← 添加这一行! val markReadyResult = grpcClient.markPartyReady(sessionId, partyId) if (markReadyResult.isSuccess) { markReadySuccess = true return@repeat } ... } ``` 现在流程: - 第1次:optimistic lock conflict → 延迟重试 - 第2次:成功 → 设置标志 → return@repeat - 第3次:检查标志已成功 → 立即 return@repeat(跳过) - 第4次:检查标志已成功 → 立即 return@repeat(跳过) - 第5次:检查标志已成功 → 立即 return@repeat(跳过) - 循环结束 → 检查标志 = true → 继续执行 keygen ✅ ## 影响范围 修复了所有 markPartyReady 重试位置(6处): - startKeygenAsInitiator - joinKeygenViaGrpc - startSignAsInitiator - joinSignViaGrpc - startSignAsJoiner - 其他相关函数 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
003871aded
commit
41e7eed2c1
|
|
@ -1345,10 +1345,14 @@ class TssRepository @Inject constructor(
|
|||
_sessionStatus.value = SessionStatus.IN_PROGRESS
|
||||
|
||||
// Mark ready - with retry on optimistic lock conflict
|
||||
var markReadySuccess = false
|
||||
repeat(5) { attempt ->
|
||||
if (markReadySuccess) return@repeat // Already succeeded, skip remaining attempts
|
||||
|
||||
val markReadyResult = grpcClient.markPartyReady(sessionId, partyId)
|
||||
if (markReadyResult.isSuccess) {
|
||||
android.util.Log.d("TssRepository", "markPartyReady successful on attempt ${attempt + 1}")
|
||||
markReadySuccess = true
|
||||
return@repeat
|
||||
}
|
||||
val error = markReadyResult.exceptionOrNull()
|
||||
|
|
@ -1359,6 +1363,14 @@ class TssRepository @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
// Check if any attempt succeeded
|
||||
if (!markReadySuccess) {
|
||||
android.util.Log.e("TssRepository", "All markPartyReady attempts failed")
|
||||
stopProgressCollection()
|
||||
_sessionStatus.value = SessionStatus.FAILED
|
||||
return@coroutineScope Result.failure(Exception("Failed to mark party ready after 5 attempts"))
|
||||
}
|
||||
|
||||
// Wait for keygen result
|
||||
val keygenResult = tssNativeBridge.waitForKeygenResult(password)
|
||||
if (keygenResult.isFailure) {
|
||||
|
|
@ -2149,6 +2161,8 @@ class TssRepository @Inject constructor(
|
|||
// Mark ready - with retry on optimistic lock conflict
|
||||
var markReadySuccess = false
|
||||
repeat(5) { attempt ->
|
||||
if (markReadySuccess) return@repeat // Already succeeded, skip remaining attempts
|
||||
|
||||
val markReadyResult = grpcClient.markPartyReady(sessionId, partyId)
|
||||
if (markReadyResult.isSuccess) {
|
||||
android.util.Log.d("TssRepository", "Successfully marked party ready on attempt ${attempt + 1}")
|
||||
|
|
@ -2162,19 +2176,15 @@ class TssRepository @Inject constructor(
|
|||
if (error?.message?.contains("optimistic lock conflict") == true && attempt < 4) {
|
||||
android.util.Log.d("TssRepository", "Optimistic lock conflict detected, retrying after ${(attempt + 1) * 500}ms...")
|
||||
delay((attempt + 1) * 500L) // 500ms, 1s, 1.5s, 2s
|
||||
} else if (attempt == 4) {
|
||||
// Last attempt failed, return error
|
||||
stopProgressCollection()
|
||||
_sessionStatus.value = SessionStatus.FAILED
|
||||
return@coroutineScope Result.failure(Exception("Failed to mark party ready after 5 attempts: ${error?.message}"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!markReadySuccess) {
|
||||
android.util.Log.e("TssRepository", "All markPartyReady attempts failed")
|
||||
stopProgressCollection()
|
||||
_sessionStatus.value = SessionStatus.FAILED
|
||||
return@coroutineScope Result.failure(Exception("Failed to mark party ready"))
|
||||
return@coroutineScope Result.failure(Exception("Failed to mark party ready after 5 attempts"))
|
||||
}
|
||||
|
||||
// Wait for keygen result
|
||||
|
|
|
|||
Loading…
Reference in New Issue