From 3e1674a06033279a2af9f7c3c2bdeadab88d779b Mon Sep 17 00:00:00 2001 From: wucm667 Date: Tue, 11 Aug 2026 04:31:36 +0800 Subject: [PATCH] fix(settings): cache unset scheduling thresholds --- .../internal/service/backup_service_test.go | 10 ++++++++-- backend/internal/service/setting_features.go | 7 +++++++ ...setting_service_platform_threshold_test.go | 20 +++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/backend/internal/service/backup_service_test.go b/backend/internal/service/backup_service_test.go index 77ffc96a2..c599d719f 100644 --- a/backend/internal/service/backup_service_test.go +++ b/backend/internal/service/backup_service_test.go @@ -24,8 +24,10 @@ import ( // ─── Mocks ─── type mockSettingRepo struct { - mu sync.Mutex - data map[string]string + mu sync.Mutex + data map[string]string + getValueErr error + getValueCalls int } func newMockSettingRepo() *mockSettingRepo { @@ -45,6 +47,10 @@ func (m *mockSettingRepo) Get(_ context.Context, key string) (*Setting, error) { func (m *mockSettingRepo) GetValue(_ context.Context, key string) (string, error) { m.mu.Lock() defer m.mu.Unlock() + m.getValueCalls++ + if m.getValueErr != nil { + return "", m.getValueErr + } v, ok := m.data[key] if !ok { return "", nil diff --git a/backend/internal/service/setting_features.go b/backend/internal/service/setting_features.go index 7cd647e9f..648fa1dc2 100644 --- a/backend/internal/service/setting_features.go +++ b/backend/internal/service/setting_features.go @@ -1114,6 +1114,13 @@ func (s *SettingService) GetAccountSchedulingThresholds(ctx context.Context) map raw, err := s.settingRepo.GetValue(dbCtx, SettingKeyAccountSchedulingThresholds) if err != nil { + if errors.Is(err, ErrSettingNotFound) { + accountSchedulingThresholdsCache.Store(&cachedAccountSchedulingThresholds{ + thresholds: cloneAccountSchedulingThresholds(thresholds), + expiresAt: time.Now().Add(accountSchedulingThresholdsCacheTTL).UnixNano(), + }) + return cloneAccountSchedulingThresholds(thresholds), nil + } slog.Warn("failed to get account scheduling thresholds, falling back to defaults", "error", err) accountSchedulingThresholdsCache.Store(&cachedAccountSchedulingThresholds{ thresholds: cloneAccountSchedulingThresholds(thresholds), diff --git a/backend/internal/service/setting_service_platform_threshold_test.go b/backend/internal/service/setting_service_platform_threshold_test.go index 7b95cb8f7..3e4543e0e 100644 --- a/backend/internal/service/setting_service_platform_threshold_test.go +++ b/backend/internal/service/setting_service_platform_threshold_test.go @@ -5,6 +5,7 @@ package service import ( "context" "testing" + "time" "github.com/Wei-Shaw/sub2api/internal/config" "github.com/stretchr/testify/require" @@ -108,6 +109,25 @@ func TestGetAccountSchedulingThresholds_ReadsStoredValue(t *testing.T) { require.NotContains(t, got, "kiro") } +func TestGetAccountSchedulingThresholds_MissingSettingUsesDefaultsAndNormalCacheTTL(t *testing.T) { + svc := newSettingServiceForPlatformThresholdTest(nil) + repo := svc.settingRepo.(*mockSettingRepo) + repo.getValueErr = ErrSettingNotFound + + got := svc.GetAccountSchedulingThresholds(context.Background()) + require.Equal(t, defaultAccountSchedulingThresholds(), got) + require.Equal(t, 1, repo.getValueCalls) + + repo.data[SettingKeyAccountSchedulingThresholds] = `{"openai":91}` + got = svc.GetAccountSchedulingThresholds(context.Background()) + require.Equal(t, 100, got[PlatformOpenAI], "missing-setting defaults should remain cached for the normal TTL") + require.Equal(t, 1, repo.getValueCalls) + + cached, ok := accountSchedulingThresholdsCache.Load().(*cachedAccountSchedulingThresholds) + require.True(t, ok) + require.Greater(t, cached.expiresAt, time.Now().Add(accountSchedulingThresholdsCacheTTL-time.Second).UnixNano()) +} + func TestUpdateSettings_OmittedAccountSchedulingThresholdsDoesNotCacheDefaults(t *testing.T) { svc := newSettingServiceForPlatformThresholdTest(map[string]string{ SettingKeyAccountSchedulingThresholds: `{"openai":85,"grok":88,"kiro":87}`,