mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-10-14 12:02:27 +08:00
fix(ollama): 测试仓储到期查询深拷贝消除数据竞争
ollamaUsageTestRepo.ListDueOllamaCloudUsageAccounts 返回浅拷贝共享 Extra/Credentials map,RunDue 过滤循环的无锁读与组写协程在 r.mu 下的 map 删改构成数据竞争(-race 可复现;无 -race 时也可能触发 runtime concurrent map read/write fatal 导致 CI 偶发崩溃)。两条返回路径改为 r.mu 下 mergeMap 深拷贝,并补全 ListOllamaCloudUsageGroupAccounts 只拷 Extra 不拷 Credentials 的半克隆,与基类 GetByID 惯例对齐。 生产仓储每次查询返回全新行,不受影响。
This commit is contained in:
@@ -54,16 +54,19 @@ func (r *ollamaUsageTestRepo) ListOllamaCloudUsageGroupAccounts(_ context.Contex
|
||||
if _, match := wanted[fingerprint]; !ok || !match {
|
||||
continue
|
||||
}
|
||||
clone := *account
|
||||
clone.Extra = make(map[string]any, len(account.Extra))
|
||||
for key, value := range account.Extra {
|
||||
clone.Extra[key] = value
|
||||
}
|
||||
result = append(result, clone)
|
||||
result = append(result, cloneOllamaUsageTestAccount(*account))
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// cloneOllamaUsageTestAccount 深拷贝共享 map,模拟真实仓储每次查询返回全新行:
|
||||
// 组写在 r.mu 下改成员 map,浅拷贝会让 RunDue 过滤循环无锁读到同一 map 而竞争。
|
||||
func cloneOllamaUsageTestAccount(account Account) Account {
|
||||
account.Credentials = mergeMap(nil, account.Credentials)
|
||||
account.Extra = mergeMap(nil, account.Extra)
|
||||
return account
|
||||
}
|
||||
|
||||
func (r *ollamaUsageTestRepo) SaveOllamaCloudUsageSession(_ context.Context, expected *Account, ciphertext string, autoRefresh bool) error {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
@@ -183,14 +186,18 @@ func applyOllamaUsageTestManagedExtra(account, source *Account) {
|
||||
}
|
||||
|
||||
func (r *ollamaUsageTestRepo) ListDueOllamaCloudUsageAccounts(_ context.Context, _ time.Time, limit int) ([]Account, error) {
|
||||
if len(r.due) > 0 {
|
||||
return append([]Account(nil), r.due[:min(limit, len(r.due))]...), nil
|
||||
}
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
if len(r.due) > 0 {
|
||||
out := make([]Account, 0, min(limit, len(r.due)))
|
||||
for _, account := range r.due[:min(limit, len(r.due))] {
|
||||
out = append(out, cloneOllamaUsageTestAccount(account))
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
out := make([]Account, 0, len(r.accounts))
|
||||
for _, account := range r.accounts {
|
||||
out = append(out, *account)
|
||||
out = append(out, cloneOllamaUsageTestAccount(*account))
|
||||
if len(out) == limit {
|
||||
break
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user