From 1be6f3018867d808f18c81c1885881337fec2328 Mon Sep 17 00:00:00 2001 From: shaw Date: Thu, 23 Jul 2026 17:14:10 +0800 Subject: [PATCH] =?UTF-8?q?fix(ollama):=20=E6=B5=8B=E8=AF=95=E4=BB=93?= =?UTF-8?q?=E5=82=A8=E5=88=B0=E6=9C=9F=E6=9F=A5=E8=AF=A2=E6=B7=B1=E6=8B=B7?= =?UTF-8?q?=E8=B4=9D=E6=B6=88=E9=99=A4=E6=95=B0=E6=8D=AE=E7=AB=9E=E4=BA=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 惯例对齐。 生产仓储每次查询返回全新行,不受影响。 --- .../service/ollama_cloud_usage_test.go | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/backend/internal/service/ollama_cloud_usage_test.go b/backend/internal/service/ollama_cloud_usage_test.go index 851b30cb48..d949ce41fd 100644 --- a/backend/internal/service/ollama_cloud_usage_test.go +++ b/backend/internal/service/ollama_cloud_usage_test.go @@ -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 }