diff --git a/backend/internal/service/pricing_service.go b/backend/internal/service/pricing_service.go index 814d6ddaa1..08f38e25a2 100644 --- a/backend/internal/service/pricing_service.go +++ b/backend/internal/service/pricing_service.go @@ -218,6 +218,11 @@ func (s *PricingService) Stop() { // startUpdateScheduler 启动定时更新调度器 func (s *PricingService) startUpdateScheduler() { + if s == nil || s.cfg == nil || strings.TrimSpace(s.cfg.Pricing.RemoteURL) == "" { + logger.LegacyPrintf("service.pricing", "%s", "[Pricing] Remote sync disabled: pricing remote URL is empty") + return + } + // 定期检查哈希更新 hashInterval := time.Duration(s.cfg.Pricing.HashCheckIntervalMinutes) * time.Minute if hashInterval < time.Minute { diff --git a/backend/internal/service/pricing_service_test.go b/backend/internal/service/pricing_service_test.go index b68d034638..88553f0fbf 100644 --- a/backend/internal/service/pricing_service_test.go +++ b/backend/internal/service/pricing_service_test.go @@ -5,11 +5,42 @@ import ( "os" "path/filepath" "testing" + "time" "github.com/Wei-Shaw/sub2api/internal/config" "github.com/stretchr/testify/require" ) +func TestPricingSchedulerBlankRemoteURLDoesNotStart(t *testing.T) { + svc := NewPricingService(&config.Config{Pricing: config.PricingConfig{RemoteURL: " \t "}}, nil) + defer svc.Stop() + + svc.startUpdateScheduler() + done := make(chan struct{}) + go func() { + svc.wg.Wait() + close(done) + }() + + select { + case <-done: + case <-time.After(100 * time.Millisecond): + t.Fatal("blank remote URL must not start scheduler") + } +} + +func TestPricingNonEmptyInvalidRemoteURLStillReturnsValidationError(t *testing.T) { + svc := NewPricingService(&config.Config{Pricing: config.PricingConfig{ + RemoteURL: "://invalid", + DataDir: t.TempDir(), + }}, nil) + + err := svc.ForceUpdate() + + require.Error(t, err) + require.Contains(t, err.Error(), "invalid pricing url") +} + func TestParsePricingData_ParsesPriorityAndServiceTierFields(t *testing.T) { svc := &PricingService{} body := []byte(`{