387 lines
10 KiB
Markdown
387 lines
10 KiB
Markdown
# 24小时改动时间线分析
|
||
|
||
## 用户质疑
|
||
> "那你回顾一下这24小时内都在改什么?为什么导致原来的co-keygen,keygen,co-sign,sign功能失败了?"
|
||
|
||
## 完整时间线
|
||
|
||
### ✅ 阶段1:工作的版本(起点)
|
||
**最后一个完全工作的commit**: 在 003871ad 之前
|
||
|
||
**状态**:
|
||
- ✅ co-keygen 正常
|
||
- ✅ keygen 正常
|
||
- ✅ co-sign 正常
|
||
- ✅ sign 正常
|
||
|
||
---
|
||
|
||
### ⚠️ 阶段2:Bug修复(003871ad → 41e7eed2)
|
||
|
||
#### Commit 003871ad (2026-01-27 00:09:40)
|
||
**标题**: "fix(android): 修复 markPartyReady 乐观锁冲突导致 keygen 失败的关键Bug"
|
||
|
||
**改动内容**:
|
||
```kotlin
|
||
// 添加 markPartyReady 重试机制
|
||
repeat(5) { attempt ->
|
||
val markReadyResult = grpcClient.markPartyReady(sessionId, partyId)
|
||
if (markReadyResult.isSuccess) {
|
||
markReadySuccess = true
|
||
return@repeat // ❌ Bug: 不会退出循环
|
||
}
|
||
delay((attempt + 1) * 500L)
|
||
}
|
||
```
|
||
|
||
**问题**: `return@repeat` 只跳过当前迭代,不退出循环
|
||
**影响**: 可能导致重复标记 ready,但不是致命的
|
||
|
||
---
|
||
|
||
#### Commit 41e7eed2 (2026-01-27 00:24:40) ✅ **工作的版本**
|
||
**标题**: "fix(android): 修复 markPartyReady 重试逻辑的循环退出Bug"
|
||
|
||
**改动内容**:
|
||
```kotlin
|
||
repeat(5) { attempt ->
|
||
if (markReadySuccess) return@repeat // ✅ 修复:先检查标志
|
||
val markReadyResult = grpcClient.markPartyReady(sessionId, partyId)
|
||
if (markReadyResult.isSuccess) {
|
||
markReadySuccess = true
|
||
return@repeat
|
||
}
|
||
delay((attempt + 1) * 500L)
|
||
}
|
||
```
|
||
|
||
**状态**: ✅ **用户确认这个版本是工作的**
|
||
|
||
---
|
||
|
||
### ❌ 阶段3:灾难性重构(7b957114)
|
||
|
||
#### Commit 7b957114 (2026-01-27 00:56:55) 🔥 **破坏性改动**
|
||
**标题**: "feat(android): 实现可靠的 gRPC 连接和流管理机制"
|
||
|
||
**改动统计**:
|
||
```
|
||
8 files changed, 1113 insertions(+), 177 deletions(-)
|
||
```
|
||
|
||
**核心改动**:
|
||
|
||
##### 1. 添加 GrpcClient.kt Keep-Alive 配置 ✅(这个是好的)
|
||
```kotlin
|
||
+ .keepAliveTime(20, TimeUnit.SECONDS)
|
||
+ .keepAliveTimeout(5, TimeUnit.SECONDS)
|
||
+ .keepAliveWithoutCalls(true)
|
||
+ .idleTimeout(Long.MAX_VALUE, TimeUnit.DAYS)
|
||
```
|
||
|
||
##### 2. 添加网络监听 ✅(这个是好的)
|
||
```kotlin
|
||
+ fun setupNetworkMonitoring(context: Context) {
|
||
+ channel?.resetConnectBackoff()
|
||
+ }
|
||
```
|
||
|
||
##### 3. 创建 StreamManager.kt ❌(这个破坏了原有逻辑)
|
||
- 新文件:282行
|
||
- 试图封装流管理逻辑
|
||
- 引入了 callback 机制
|
||
|
||
##### 4. 修改 TssRepository.kt ❌(破坏性改动)
|
||
|
||
**之前(工作的代码)**:
|
||
```kotlin
|
||
// 41e7eed2 版本
|
||
grpcClient.registerParty(partyId, "temporary", "1.0.0") // 没有检查
|
||
startSessionEventSubscription()
|
||
|
||
private fun startSessionEventSubscription() {
|
||
jobManager.launch(JOB_SESSION_EVENT) {
|
||
grpcClient.subscribeSessionEvents(effectivePartyId).collect { event ->
|
||
// 直接处理事件
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
**之后(7b957114的改动)**:
|
||
```kotlin
|
||
grpcClient.registerParty(partyId, "temporary", "1.0.0") // 还是没有检查!
|
||
startSessionEventSubscription()
|
||
|
||
private fun startSessionEventSubscription() {
|
||
streamManager.startEventStream(
|
||
partyId = effectivePartyId,
|
||
onEvent = { event -> /* callback */ },
|
||
onError = { error -> /* callback */ }
|
||
)
|
||
}
|
||
```
|
||
|
||
##### 5. 添加 init 块监听重连 ❌(引入新问题)
|
||
```kotlin
|
||
+ init {
|
||
+ repositoryScope.launch {
|
||
+ grpcConnectionEvents
|
||
+ .filter { it is GrpcConnectionEvent.Reconnected }
|
||
+ .collect {
|
||
+ streamManager.restartAllStreams()
|
||
+ }
|
||
+ }
|
||
+ }
|
||
```
|
||
|
||
**导致的问题**:
|
||
|
||
1. **RegisterParty 失败但代码继续执行**
|
||
```
|
||
17:19:30.641 E/GrpcClient: RegisterParty failed after 2 attempts
|
||
17:19:30.643 D/TssRepository: Starting session event subscription ← 还是执行了!
|
||
```
|
||
|
||
2. **StreamManager 日志完全缺失**
|
||
```
|
||
[MISSING] StreamManager: Starting event stream for partyId=...
|
||
```
|
||
|
||
3. **双重连接导致 Channel shutdown**
|
||
```
|
||
UNAVAILABLE: Channel shutdown invoked
|
||
```
|
||
|
||
**为什么会失败**:
|
||
- StreamManager 的实现有 bug
|
||
- callback 机制不如直接 Flow.collect 可靠
|
||
- init 块的监听可能导致时序问题
|
||
- 增加了复杂度,引入了新的失败点
|
||
|
||
---
|
||
|
||
### 🔄 阶段4:回退尝试(bfbd062e)
|
||
|
||
#### Commit bfbd062e (2026-01-27 01:34:16) ⚠️ **部分回退**
|
||
**标题**: "refactor(android): 回归简单可靠的流管理架构"
|
||
|
||
**改动内容**:
|
||
1. ✅ 删除 StreamManager.kt
|
||
2. ✅ 删除 init 块监听
|
||
3. ✅ 恢复 jobManager.launch 模式
|
||
4. ✅ 添加 registerParty 错误检查(新增,好的改进)
|
||
5. ✅ 保留 Keep-Alive 配置
|
||
6. ✅ 保留网络监听
|
||
7. ⚠️ **添加了 Flow.retryWhen**(这是新增的,不在 41e7eed2)
|
||
|
||
**与 41e7eed2 的差异**:
|
||
|
||
```kotlin
|
||
// 41e7eed2(工作的版本)
|
||
jobManager.launch(JOB_SESSION_EVENT) {
|
||
grpcClient.subscribeSessionEvents(effectivePartyId).collect { event ->
|
||
// 处理事件
|
||
}
|
||
}
|
||
|
||
// bfbd062e(当前版本)
|
||
jobManager.launch(JOB_SESSION_EVENT) {
|
||
flow {
|
||
grpcClient.subscribeSessionEvents(effectivePartyId).collect { emit(it) }
|
||
}
|
||
.retryWhen { cause, attempt -> // ← 新增的
|
||
delay(min(attempt + 1, 30) * 1000L)
|
||
true
|
||
}
|
||
.collect { event ->
|
||
// 处理事件
|
||
}
|
||
}
|
||
```
|
||
|
||
**可能的问题**:
|
||
- retryWhen 可能在某些情况下影响事件流
|
||
- 虽然看起来应该没问题,但与工作版本不完全一致
|
||
|
||
---
|
||
|
||
## 根本原因分析
|
||
|
||
### 为什么功能失败了?
|
||
|
||
#### 1. 7b957114 引入的问题(最大元凶)❌
|
||
|
||
| 问题 | 原因 | 影响 |
|
||
|------|------|------|
|
||
| RegisterParty 无错误检查 | 失败后继续执行 | Channel 未就绪导致后续失败 |
|
||
| StreamManager 抽象层 | 实现有 bug,日志丢失 | 事件流不工作 |
|
||
| init 块监听重连 | 时序问题,双重连接 | Channel shutdown |
|
||
| callback 机制 | 不如直接 collect 可靠 | 事件丢失 |
|
||
|
||
#### 2. bfbd062e 的回退不彻底 ⚠️
|
||
|
||
**添加了 registerParty 错误检查(好的)**:
|
||
```kotlin
|
||
+ val registerResult = grpcClient.registerParty(partyId, "temporary", "1.0.0")
|
||
+ if (registerResult.isFailure) {
|
||
+ throw registerResult.exceptionOrNull() ?: Exception("Failed to register party")
|
||
+ }
|
||
```
|
||
|
||
**但也添加了 retryWhen(不确定)**:
|
||
```kotlin
|
||
+ .retryWhen { cause, attempt ->
|
||
+ delay(min(attempt + 1, 30) * 1000L)
|
||
+ true
|
||
+ }
|
||
```
|
||
|
||
这个 retryWhen 虽然看起来应该工作,但**不在 41e7eed2 工作版本中**!
|
||
|
||
---
|
||
|
||
## 当前状态分析
|
||
|
||
### 相比 41e7eed2(工作版本),当前版本的差异:
|
||
|
||
| 方面 | 41e7eed2 | bfbd062e (当前) | 差异 |
|
||
|------|----------|-----------------|------|
|
||
| Keep-Alive | ❌ 没有 | ✅ 有 | 新增(官方推荐)|
|
||
| 网络监听 | ❌ 没有 | ✅ 有 | 新增(官方推荐)|
|
||
| registerParty 检查 | ❌ 没有 | ✅ 有 | 新增(好的改进)|
|
||
| 事件订阅 | jobManager.launch | jobManager.launch | 相同 ✅ |
|
||
| retryWhen | ❌ 没有 | ✅ 有 | **新增(可能的问题)** |
|
||
| StreamManager | ❌ 没有 | ❌ 没有 | 相同 ✅ |
|
||
|
||
---
|
||
|
||
## 为什么当前还是不工作?
|
||
|
||
### 可能的原因:
|
||
|
||
#### 1. registerParty 现在会抛出异常 ⚠️
|
||
|
||
**41e7eed2(失败但继续)**:
|
||
```kotlin
|
||
grpcClient.registerParty(partyId, "temporary", "1.0.0") // 失败但继续
|
||
startSessionEventSubscription() // 还是会执行
|
||
```
|
||
|
||
**bfbd062e(失败就停止)**:
|
||
```kotlin
|
||
val registerResult = grpcClient.registerParty(partyId, "temporary", "1.0.0")
|
||
if (registerResult.isFailure) {
|
||
throw ... // ← 直接抛异常,后续不执行
|
||
}
|
||
startSessionEventSubscription() // 不会执行
|
||
```
|
||
|
||
**问题**: 如果 registerParty 失败,现在会直接停止,不会继续订阅事件。
|
||
**但**: 这应该是对的行为!如果注册失败,继续也没意义。
|
||
|
||
#### 2. retryWhen 可能导致重复订阅 ⚠️
|
||
|
||
```kotlin
|
||
flow {
|
||
grpcClient.subscribeSessionEvents(effectivePartyId).collect { emit(it) }
|
||
}
|
||
.retryWhen { cause, attempt ->
|
||
delay(min(attempt + 1, 30) * 1000L)
|
||
true // 永远重试
|
||
}
|
||
```
|
||
|
||
**可能的问题**:
|
||
- 如果 subscribeSessionEvents 立即失败,会立即重试
|
||
- 可能导致多次订阅尝试
|
||
- 虽然 jobManager 会取消旧 Job,但时序问题可能存在
|
||
|
||
#### 3. GrpcClient 的改动 ⚠️
|
||
|
||
7b957114 修改了 GrpcClient.kt(216 insertions, 177 deletions)
|
||
bfbd062e 没有回退这些改动!
|
||
|
||
需要检查 GrpcClient 的改动是否影响了基本功能。
|
||
|
||
---
|
||
|
||
## 测试建议
|
||
|
||
### 要验证的点:
|
||
|
||
1. **RegisterParty 是否成功**
|
||
```
|
||
看日志: "Party registered successfully"
|
||
```
|
||
|
||
2. **事件订阅是否启动**
|
||
```
|
||
看日志: "Starting session event subscription for partyId: xxx"
|
||
```
|
||
|
||
3. **retryWhen 是否影响正常流**
|
||
```
|
||
看日志: 是否有 "Event stream failed" 警告
|
||
```
|
||
|
||
4. **GrpcClient 的改动是否有问题**
|
||
```
|
||
对比 41e7eed2 和 bfbd062e 的 GrpcClient.kt
|
||
```
|
||
|
||
---
|
||
|
||
## 修复方案
|
||
|
||
### 选项A:完全回退到 41e7eed2 ✅
|
||
|
||
```bash
|
||
git checkout 41e7eed2 -- backend/mpc-system/services/service-party-android/app/src/main/java/com/durian/tssparty/data/repository/TssRepository.kt
|
||
git checkout 41e7eed2 -- backend/mpc-system/services/service-party-android/app/src/main/java/com/durian/tssparty/data/remote/GrpcClient.kt
|
||
```
|
||
|
||
**优点**: 100% 恢复到工作状态
|
||
**缺点**: 失去 Keep-Alive 和网络监听的改进
|
||
|
||
### 选项B:删除 retryWhen,保留其他改进 ✅
|
||
|
||
```kotlin
|
||
// 恢复为 41e7eed2 的简单版本
|
||
jobManager.launch(JOB_SESSION_EVENT) {
|
||
grpcClient.subscribeSessionEvents(effectivePartyId).collect { event ->
|
||
// 处理事件
|
||
}
|
||
}
|
||
```
|
||
|
||
**优点**: 保留 Keep-Alive 和 registerParty 检查
|
||
**缺点**: 失去自动重连能力(但 41e7eed2 也没有)
|
||
|
||
### 选项C:测试当前版本,看具体哪里失败 ✅
|
||
|
||
用 build-install-debug.bat 测试,查看具体日志。
|
||
|
||
---
|
||
|
||
## 总结
|
||
|
||
### 24小时内改了什么:
|
||
|
||
1. **003871ad**: 添加 markPartyReady 重试(有小bug)
|
||
2. **41e7eed2**: 修复 repeat 循环 bug ✅ **工作**
|
||
3. **7b957114**: 引入 StreamManager ❌ **破坏性改动**
|
||
4. **bfbd062e**: 删除 StreamManager ⚠️ **部分回退**
|
||
|
||
### 为什么功能失败:
|
||
|
||
1. **7b957114 引入的 StreamManager 有严重 bug**
|
||
2. **bfbd062e 的回退不彻底**:
|
||
- 添加了 retryWhen(41e7eed2 没有)
|
||
- 添加了 registerParty 检查(可能导致提前停止)
|
||
- 没有回退 GrpcClient.kt 的改动
|
||
|
||
### 下一步:
|
||
|
||
**立即测试当前版本,或完全回退到 41e7eed2**
|