fix: 修复Redis映射表竞态条件导致API Key临时失效问题

问题:编辑API Key后立即使用时会偶现(概率1%)报"API密钥已过期"错误,
一会儿后自动恢复。这是因为updateApiKey()方法未传递hashedKey参数给
setApiKey(),导致映射表未更新而主数据已更新的不一致状态。

修复:
- updateApiKey()传递keyData.apiKey(hashedKey)给setApiKey()
- 确保每次更新API Key时映射表也被同步更新
- 添加日志记录帮助监控映射表问题

细节:
1. updateApiKey(): 传递hashedKey参数确保映射表一致性
2. validateApiKey(): 添加警告日志检测映射表缺失
3. updateApiKey(): 增强日志记录"hashMap updated"

这解决了Redis双重存储(apikey:{id}和apikey:hash_map)的
竞态条件问题。

Fix: #API-Key-Expiry-Race-Condition
This commit is contained in:
Dave King
2025-11-27 10:06:09 +08:00
parent 291642d8ff
commit 94ff095754

View File

@@ -212,6 +212,8 @@ class ApiKeyService {
const keyData = await redis.findApiKeyByHash(hashedKey) const keyData = await redis.findApiKeyByHash(hashedKey)
if (!keyData) { if (!keyData) {
// ⚠️ 警告:映射表查找失败,可能是竞态条件或映射表损坏
logger.warn(`⚠️ API key not found in hash map: ${hashedKey.substring(0, 16)}... (possible race condition or corrupted hash map)`)
return { valid: false, error: 'API key not found' } return { valid: false, error: 'API key not found' }
} }
@@ -714,10 +716,11 @@ class ApiKeyService {
updatedData.updatedAt = new Date().toISOString() updatedData.updatedAt = new Date().toISOString()
// 更新时不需要重新建立哈希映射因为API Key本身没有变化 // 传递hashedKey以确保映射表一致性
await redis.setApiKey(keyId, updatedData) // keyData.apiKey 存储的就是 hashedKey见generateApiKey第123行
await redis.setApiKey(keyId, updatedData, keyData.apiKey)
logger.success(`📝 Updated API key: ${keyId}`) logger.success(`📝 Updated API key: ${keyId}, hashMap updated`)
return { success: true } return { success: true }
} catch (error) { } catch (error) {