// capability-socketio 通过回调注入业务层的刷新逻辑
SocketIOManager.refreshTokenProvider = { AuthManager.refreshTokenIfNeeded() }
问题:
capability-socketio 是能力层,不应该依赖 app/auth 的业务逻辑原则:
实现:
// capability-socketio:直接从存储读取 Token(基础设施)
class SocketIORepository {
private fun getToken(): String? {
return StorageImpl.getString("access_token").takeIf { it.isNotEmpty() }
}
suspend fun connect(): Result<Unit> {
val token = getToken()
if (token.isNullOrEmpty()) {
return Result.failure(Exception("未登录"))
}
// 直接使用 Token 连接,不负责刷新
return socketService.connect(token)
}
}
Token 刷新处理:
TokenRefreshInterceptor 统一处理(已实现)如果 SocketIO 必须在连接前刷新 Token:
// base-core:定义接口(基础设施)
interface ITokenProvider {
suspend fun getToken(): String?
suspend fun refreshTokenIfNeeded(): String?
}
// app/auth:实现接口
object AuthManager : ITokenProvider {
override suspend fun getToken(): String? = TokenStore.getAccessToken()
override suspend fun refreshTokenIfNeeded(): String? { /* ... */ }
}
// capability-socketio:使用接口(不依赖具体实现)
class SocketIORepository(
private val tokenProvider: ITokenProvider? = null // 通过 DI 注入
) {
suspend fun connect() {
val token = tokenProvider?.refreshTokenIfNeeded()
?: StorageImpl.getString("access_token")
// ...
}
}
优点:
缺点:
class SocketIORepository {
// 直接从存储读取 Token(基础设施,可以依赖)
private fun getToken(): String? {
return StorageImpl.getString("access_token").takeIf { it.isNotEmpty() }
}
suspend fun connect(): Result<Unit> {
val token = getToken()
if (token.isNullOrEmpty()) {
return Result.failure(Exception("未登录(Token 为空)"))
}
// 直接连接,不负责刷新
return socketService.connect(token)
}
// 连接失败回调(通知上层处理)
var onConnectionFailed: ((Exception) -> Unit)? = null
}
// UserViewModel 或专门的 SocketIO 管理类
class SocketIOConnectionManager {
suspend fun connectWithRetry() {
var retryCount = 0
while (retryCount < 3) {
when (val result = SocketIOManager.connect()) {
is Result.Success -> return
is Result.Failure -> {
val error = result.exception
if (error.message?.contains("401") == true ||
error.message?.contains("Token") == true) {
// Token 可能过期,刷新后重试
val newToken = AuthManager.refreshTokenIfNeeded()
if (newToken != null) {
retryCount++
continue
}
}
// 其他错误,直接失败
break
}
}
}
}
}
// TokenRefreshInterceptor 已实现,统一处理 HTTP 请求的 401/402
// SocketIO 不需要单独处理
| 维度 | 当前设计 | 推荐设计 |
|---|---|---|
| 能力层职责 | 连接 + Token 刷新 | 只负责连接 |
| 依赖关系 | 通过回调依赖业务层 | 只依赖基础设施(StorageImpl) |
| 刷新逻辑 | SocketIO 自己刷新 | 统一由 Network 拦截器处理 |
| 连接失败处理 | SocketIO 内部处理 | 上层(app)处理 |
| 复杂度 | 高(能力层包含业务逻辑) | 低(职责清晰) |
| 可测试性 | 低(依赖业务层) | 高(只依赖接口) |
当前设计的问题:
推荐方案: