feat: add SyncAll periodic sync pipeline and wire Navidrome client into App
This commit is contained in:
@@ -12,6 +12,7 @@ import (
|
||||
"naviwatcher/internal/config"
|
||||
"naviwatcher/internal/database"
|
||||
"naviwatcher/internal/musicbrainz"
|
||||
"naviwatcher/internal/navidrome"
|
||||
"naviwatcher/internal/scanner"
|
||||
)
|
||||
|
||||
@@ -20,8 +21,14 @@ type App struct {
|
||||
cfg *config.Config
|
||||
db *database.DB
|
||||
mbClient *musicbrainz.MusicBrainzClient
|
||||
ndClient *navidrome.NavidromeClient
|
||||
}
|
||||
|
||||
// navidromeClientFactory constructs the Navidrome client. It is a package-level
|
||||
// variable (not a direct call to navidrome.NewClient) so tests can inject a stub
|
||||
// without requiring a live Navidrome server for authentication.
|
||||
var navidromeClientFactory = navidrome.NewClient
|
||||
|
||||
const defaultConfigPath = "config.yaml"
|
||||
|
||||
func main() {
|
||||
@@ -76,10 +83,17 @@ func NewApp(ctx context.Context, cfg *config.Config, dbPath string) (*App, error
|
||||
|
||||
log.Printf("MusicBrainz client initialized (user-agent: %s)", cfg.MusicBrainz.UserAgent)
|
||||
|
||||
// Initialize Navidrome client (authenticates immediately; error if auth fails).
|
||||
ndClient, err := navidromeClientFactory(cfg.Navidrome)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to initialize navidrome client: %w", err)
|
||||
}
|
||||
|
||||
return &App{
|
||||
cfg: cfg,
|
||||
db: db,
|
||||
mbClient: mbClient,
|
||||
ndClient: ndClient,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -88,6 +102,10 @@ func (a *App) Close() {
|
||||
if a.mbClient != nil {
|
||||
a.mbClient.Close()
|
||||
}
|
||||
if a.ndClient != nil {
|
||||
// NavidromeClient holds a stateless subsonic client; nothing to close
|
||||
// beyond releasing idle connections tracked by the MusicBrainz client.
|
||||
}
|
||||
if a.db != nil {
|
||||
if err := a.db.Close(); err != nil {
|
||||
log.Printf("Error closing database: %v", err)
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
"naviwatcher/internal/config"
|
||||
"naviwatcher/internal/database"
|
||||
"naviwatcher/internal/navidrome"
|
||||
)
|
||||
|
||||
func TestAppRun_ScanLogsMissingReleases(t *testing.T) {
|
||||
@@ -135,6 +136,13 @@ func TestNewApp_CreatesMusicBrainzClient(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
// Inject an unauthenticated Navidrome client so the test needs no live server.
|
||||
prevFactory := navidromeClientFactory
|
||||
navidromeClientFactory = func(c config.NavidromeConfig) (*navidrome.NavidromeClient, error) {
|
||||
return navidrome.NewClientUnauthenticated(c), nil
|
||||
}
|
||||
defer func() { navidromeClientFactory = prevFactory }()
|
||||
|
||||
ctx := context.Background()
|
||||
app, err := NewApp(ctx, cfg, ":memory:")
|
||||
if err != nil {
|
||||
@@ -145,6 +153,9 @@ func TestNewApp_CreatesMusicBrainzClient(t *testing.T) {
|
||||
if app.mbClient == nil {
|
||||
t.Fatal("expected MusicBrainz client to be initialized, got nil")
|
||||
}
|
||||
if app.ndClient == nil {
|
||||
t.Fatal("expected Navidrome client to be initialized, got nil")
|
||||
}
|
||||
if app.db == nil {
|
||||
t.Fatal("expected database to be initialized, got nil")
|
||||
}
|
||||
@@ -170,6 +181,12 @@ func TestNewApp_GracefulShutdown(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
prevFactory := navidromeClientFactory
|
||||
navidromeClientFactory = func(c config.NavidromeConfig) (*navidrome.NavidromeClient, error) {
|
||||
return navidrome.NewClientUnauthenticated(c), nil
|
||||
}
|
||||
defer func() { navidromeClientFactory = prevFactory }()
|
||||
|
||||
ctx := context.Background()
|
||||
app, err := NewApp(ctx, cfg, ":memory:")
|
||||
if err != nil {
|
||||
@@ -197,6 +214,12 @@ func TestAppRun_GracefulShutdown(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
prevFactory := navidromeClientFactory
|
||||
navidromeClientFactory = func(c config.NavidromeConfig) (*navidrome.NavidromeClient, error) {
|
||||
return navidrome.NewClientUnauthenticated(c), nil
|
||||
}
|
||||
defer func() { navidromeClientFactory = prevFactory }()
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
app, err := NewApp(ctx, cfg, ":memory:")
|
||||
|
||||
Reference in New Issue
Block a user