mirror of
https://github.com/Wei-Shaw/sub2api.git
synced 2026-09-24 16:05:44 +08:00
fix(lint): resolve depguard violation — remove redis import from service layer
Service layer must not import redis directly (depguard rule). Replace *redis.Client field with WebSearchManagerBuilder callback injected by the infra layer. Also fix remaining errcheck in manager_test.go.
This commit is contained in:
@@ -50,7 +50,7 @@ func TestManager_SearchWithBestProvider_PriorityOrder(t *testing.T) {
|
||||
srvBrave := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
resp := braveResponse{}
|
||||
resp.Web.Results = []braveResult{{URL: "https://brave.com", Title: "Brave", Description: "from brave"}}
|
||||
json.NewEncoder(w).Encode(resp)
|
||||
_ = json.NewEncoder(w).Encode(resp)
|
||||
}))
|
||||
defer srvBrave.Close()
|
||||
|
||||
@@ -80,7 +80,7 @@ func TestManager_SearchWithBestProvider_NilRedis(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
resp := braveResponse{}
|
||||
resp.Web.Results = []braveResult{{URL: "https://test.com", Title: "Test", Description: "result"}}
|
||||
json.NewEncoder(w).Encode(resp)
|
||||
_ = json.NewEncoder(w).Encode(resp)
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
"github.com/Wei-Shaw/sub2api/internal/config"
|
||||
infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors"
|
||||
"github.com/imroc/req/v3"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"golang.org/x/sync/singleflight"
|
||||
)
|
||||
|
||||
@@ -100,14 +99,17 @@ type DefaultSubscriptionGroupReader interface {
|
||||
GetByID(ctx context.Context, id int64) (*Group, error)
|
||||
}
|
||||
|
||||
// WebSearchManagerBuilder creates a websearch.Manager from config (injected by infra layer).
|
||||
type WebSearchManagerBuilder func(cfg *WebSearchEmulationConfig)
|
||||
|
||||
// SettingService 系统设置服务
|
||||
type SettingService struct {
|
||||
settingRepo SettingRepository
|
||||
defaultSubGroupReader DefaultSubscriptionGroupReader
|
||||
cfg *config.Config
|
||||
onUpdate func() // Callback when settings are updated (for cache invalidation)
|
||||
version string // Application version
|
||||
webSearchRedis *redis.Client // optional: Redis client for web search quota tracking
|
||||
settingRepo SettingRepository
|
||||
defaultSubGroupReader DefaultSubscriptionGroupReader
|
||||
cfg *config.Config
|
||||
onUpdate func() // Callback when settings are updated (for cache invalidation)
|
||||
version string // Application version
|
||||
webSearchManagerBuilder WebSearchManagerBuilder
|
||||
}
|
||||
|
||||
// NewSettingService 创建系统设置服务实例
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
|
||||
infraerrors "github.com/Wei-Shaw/sub2api/internal/pkg/errors"
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/websearch"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"golang.org/x/sync/singleflight"
|
||||
)
|
||||
|
||||
@@ -167,7 +166,7 @@ func (s *SettingService) SaveWebSearchEmulationConfig(ctx context.Context, cfg *
|
||||
})
|
||||
|
||||
// Hot-reload: rebuild the global Manager with new config
|
||||
s.RebuildWebSearchManager(ctx)
|
||||
s.rebuildWebSearchManager(ctx)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -209,34 +208,25 @@ func (s *SettingService) IsWebSearchEmulationEnabled(ctx context.Context) bool {
|
||||
return cfg.Enabled && len(cfg.Providers) > 0
|
||||
}
|
||||
|
||||
// SetWebSearchRedisClient injects the Redis client used for quota tracking.
|
||||
// Call after construction, before first use. Triggers initial Manager build.
|
||||
func (s *SettingService) SetWebSearchRedisClient(ctx context.Context, redisClient *redis.Client) {
|
||||
s.webSearchRedis = redisClient
|
||||
s.RebuildWebSearchManager(ctx)
|
||||
// SetWebSearchManagerBuilder injects a callback that creates and wires a websearch.Manager.
|
||||
// The infra layer (main/wire) provides this builder, keeping redis out of the service layer.
|
||||
// Triggers initial build.
|
||||
func (s *SettingService) SetWebSearchManagerBuilder(ctx context.Context, builder WebSearchManagerBuilder) {
|
||||
s.webSearchManagerBuilder = builder
|
||||
s.rebuildWebSearchManager(ctx)
|
||||
}
|
||||
|
||||
// RebuildWebSearchManager reads the current config and (re)creates the global websearch.Manager.
|
||||
// Called on startup and after SaveWebSearchEmulationConfig.
|
||||
func (s *SettingService) RebuildWebSearchManager(ctx context.Context) {
|
||||
// rebuildWebSearchManager reads the current config and invokes the builder.
|
||||
func (s *SettingService) rebuildWebSearchManager(ctx context.Context) {
|
||||
if s.webSearchManagerBuilder == nil {
|
||||
return
|
||||
}
|
||||
cfg, err := s.GetWebSearchEmulationConfig(ctx)
|
||||
if err != nil || !cfg.Enabled || len(cfg.Providers) == 0 {
|
||||
if err != nil {
|
||||
SetWebSearchManager(nil)
|
||||
return
|
||||
}
|
||||
providerConfigs := make([]websearch.ProviderConfig, 0, len(cfg.Providers))
|
||||
for _, p := range cfg.Providers {
|
||||
providerConfigs = append(providerConfigs, websearch.ProviderConfig{
|
||||
Type: p.Type,
|
||||
APIKey: p.APIKey,
|
||||
Priority: p.Priority,
|
||||
QuotaLimit: p.QuotaLimit,
|
||||
QuotaRefreshInterval: p.QuotaRefreshInterval,
|
||||
ExpiresAt: p.ExpiresAt,
|
||||
})
|
||||
}
|
||||
SetWebSearchManager(websearch.NewManager(providerConfigs, s.webSearchRedis))
|
||||
slog.Info("websearch: manager rebuilt", "provider_count", len(providerConfigs))
|
||||
s.webSearchManagerBuilder(cfg)
|
||||
}
|
||||
|
||||
// SanitizeWebSearchConfig returns a copy with api_key fields masked for API responses.
|
||||
|
||||
Reference in New Issue
Block a user