summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-05-06 15:25:57 +0300
committerPaul Buetow <paul@buetow.org>2026-05-06 15:25:57 +0300
commit0a5ae3daf7103bb319b7861253c64a4da899b48a (patch)
treea4407dd2f6dd6248aca7975ccba3092d96780c8e
parent870d5dc8bead22323d351d009ee23d8c24dd794f (diff)
internal/service: inject http.Client into podcastService constructor (task 41)
-rw-r--r--cmd/player/main.go2
-rw-r--r--internal/api/handlers_podcast_test.go2
-rw-r--r--internal/service/podcast.go14
-rw-r--r--internal/service/podcast_test.go23
4 files changed, 34 insertions, 7 deletions
diff --git a/cmd/player/main.go b/cmd/player/main.go
index c07ab93..66d2889 100644
--- a/cmd/player/main.go
+++ b/cmd/player/main.go
@@ -96,7 +96,7 @@ func wireDeps(cfg *internal.Config, store repository.Store, logger *slog.Logger,
authSvc := service.NewAuthService(store, clk, hasher, sm)
helper := service.NewAccessHelper(store)
- podcastSvc := service.NewPodcastServiceWithLogger(store, clk, cfg.MediaRoot, helper, prober, thumbGen, cfg.PodcastCheckMinutes, logger)
+ podcastSvc := service.NewPodcastServiceWithLogger(store, clk, cfg.MediaRoot, helper, prober, thumbGen, &http.Client{Timeout: service.DefaultHTTPClientTimeout}, cfg.PodcastCheckMinutes, logger)
gcWorker := service.NewGCWorker(store, clk, cfg.MediaRoot, time.Duration(cfg.GCIntervalMinutes)*time.Minute, logger)
diff --git a/internal/api/handlers_podcast_test.go b/internal/api/handlers_podcast_test.go
index 7942914..043a0f1 100644
--- a/internal/api/handlers_podcast_test.go
+++ b/internal/api/handlers_podcast_test.go
@@ -85,7 +85,7 @@ func setupPodcastE2E(t *testing.T) (srv *Server, store repository.Store, sm *aut
thumbGen := &thumb.MockGenerator{}
mediaSvc := service.NewMediaService(dbStore, clk, mediaRoot, thumbGen, prober)
- podcastSvc := service.NewPodcastService(dbStore, clk, mediaRoot, helper, prober, thumbGen, 60)
+ podcastSvc := service.NewPodcastService(dbStore, clk, mediaRoot, helper, prober, thumbGen, &http.Client{Timeout: service.DefaultHTTPClientTimeout}, 60)
cfg := &internal.Config{
SessionTimeoutHours: 24,
diff --git a/internal/service/podcast.go b/internal/service/podcast.go
index f5cf5dc..77c6118 100644
--- a/internal/service/podcast.go
+++ b/internal/service/podcast.go
@@ -80,20 +80,26 @@ type podcastService struct {
downloadCover func(*http.Client, string, string) error
}
+// DefaultHTTPClientTimeout is the fallback timeout used when no http.Client is injected.
+const DefaultHTTPClientTimeout = 30 * time.Second
+
// NewPodcastService creates a PodcastService with the given dependencies.
// checkInterval should be the number of minutes between background feed checks.
-func NewPodcastService(store PodcastServiceStore, clk clock.Clock, mediaRoot string, helper *accessHelper, prober probe.Prober, thumbGen thumb.Generator, checkInterval int) *podcastService {
- return NewPodcastServiceWithLogger(store, clk, mediaRoot, helper, prober, thumbGen, checkInterval, slog.Default())
+func NewPodcastService(store PodcastServiceStore, clk clock.Clock, mediaRoot string, helper *accessHelper, prober probe.Prober, thumbGen thumb.Generator, httpClient *http.Client, checkInterval int) *podcastService {
+ return NewPodcastServiceWithLogger(store, clk, mediaRoot, helper, prober, thumbGen, httpClient, checkInterval, slog.Default())
}
// NewPodcastServiceWithLogger creates a PodcastService with an injected logger.
-func NewPodcastServiceWithLogger(store PodcastServiceStore, clk clock.Clock, mediaRoot string, helper *accessHelper, prober probe.Prober, thumbGen thumb.Generator, checkInterval int, logger *slog.Logger) *podcastService {
+func NewPodcastServiceWithLogger(store PodcastServiceStore, clk clock.Clock, mediaRoot string, helper *accessHelper, prober probe.Prober, thumbGen thumb.Generator, httpClient *http.Client, checkInterval int, logger *slog.Logger) *podcastService {
if checkInterval <= 0 {
checkInterval = 60
}
if logger == nil {
logger = slog.Default()
}
+ if httpClient == nil {
+ httpClient = &http.Client{Timeout: DefaultHTTPClientTimeout}
+ }
s := &podcastService{
store: store,
clock: clk,
@@ -101,7 +107,7 @@ func NewPodcastServiceWithLogger(store PodcastServiceStore, clk clock.Clock, med
helper: helper,
prober: prober,
thumbGen: thumbGen,
- httpClient: &http.Client{Timeout: 30 * time.Second},
+ httpClient: httpClient,
checkInterval: checkInterval,
logger: logger,
}
diff --git a/internal/service/podcast_test.go b/internal/service/podcast_test.go
index cbf6131..0d92248 100644
--- a/internal/service/podcast_test.go
+++ b/internal/service/podcast_test.go
@@ -27,11 +27,32 @@ func setupPodcastService(t *testing.T) (*podcastService, *repository.MockStore)
store := repository.NewMockStore()
helper := &accessHelper{store: store}
logger := slog.New(slog.NewTextHandler(io.Discard, nil))
- svc := NewPodcastService(store, clk, mediaRoot, helper, nil, nil, 60)
+ svc := NewPodcastService(store, clk, mediaRoot, helper, nil, nil, &http.Client{Timeout: DefaultHTTPClientTimeout}, 60)
svc.logger = logger
return svc, store
}
+func TestPodcastService_CustomHTTPClient(t *testing.T) {
+ custom := &http.Client{Timeout: 5 * time.Second}
+ svc := NewPodcastServiceWithLogger(repository.NewMockStore(), &clock.MockClock{T: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)}, t.TempDir(), nil, nil, nil, custom, 60, slog.New(slog.NewTextHandler(io.Discard, nil)))
+ if svc.httpClient != custom {
+ t.Fatal("expected injected httpClient to be stored")
+ }
+}
+
+func TestPodcastService_NilHTTPClient_Defaults(t *testing.T) {
+ store := repository.NewMockStore()
+ clk := &clock.MockClock{T: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)}
+ logger := slog.New(slog.NewTextHandler(io.Discard, nil))
+ svc := NewPodcastServiceWithLogger(store, clk, t.TempDir(), nil, nil, nil, nil, 60, logger)
+ if svc.httpClient == nil {
+ t.Fatal("expected non-nil httpClient when nil passed to constructor")
+ }
+ if svc.httpClient.Timeout != DefaultHTTPClientTimeout {
+ t.Fatalf("expected default timeout %v, got %v", DefaultHTTPClientTimeout, svc.httpClient.Timeout)
+ }
+}
+
func TestPodcastService_SubscribeFeed_Ok(t *testing.T) {
ctx := context.Background()
svc, store := setupPodcastService(t)