Files
music-agregator/cmd/server/main.go
T
Alexander 945aab82c2 WIP
2026-04-29 17:29:58 +02:00

125 lines
3.1 KiB
Go

package main
import (
"context"
"flag"
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/fujin/music-agregator/internal/api"
"github.com/fujin/music-agregator/internal/config"
"github.com/fujin/music-agregator/internal/database"
"github.com/fujin/music-agregator/internal/metadata"
"github.com/fujin/music-agregator/internal/services"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
func main() {
configPath := flag.String("c", "config.yaml", "path to config file")
port := flag.Int("p", 0, "port to listen on (overrides config)")
flag.Parse()
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339})
cfg, err := config.Load(*configPath)
if err != nil {
log.Fatal().Err(err).Msg("failed to load config")
}
if *port != 0 {
cfg.App.Port = *port
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
indexerService, err := services.NewIndexerService(cfg.Indexers)
if err != nil {
log.Fatal().Err(err).Msg("failed to create indexer service")
}
log.Info().Int("count", len(cfg.Indexers)).Msg("initialized indexer service")
torrentService, err := services.NewTorrentService(cfg.Torrent)
if err != nil {
log.Fatal().Err(err).Msg("failed to create torrent service")
}
if torrentService.IsConfigured() {
if err := torrentService.Connect(ctx); err != nil {
log.Warn().Err(err).Msg("failed to connect to torrent client")
} else {
log.Info().Str("type", string(cfg.Torrent.ClientType)).Msg("connected to torrent client")
}
} else {
log.Warn().Msg("no torrent client configured")
}
metadataClient, err := metadata.NewClient(cfg.Metadata.Endpoint)
if err != nil {
log.Fatal().Err(err).Msg("failed to create metadata client")
}
log.Info().Str("endpoint", cfg.Metadata.Endpoint).Msg("initialized metadata client")
var db *database.DB
if cfg.Database.URL != "" {
db, err = database.New(ctx, cfg.Database.URL)
if err != nil {
log.Warn().Err(err).Msg("failed to connect to database (continuing without db)")
} else {
log.Info().Msg("connected to database")
}
}
handlers := &api.Handlers{
IndexerService: indexerService,
TorrentService: torrentService,
MetadataClient: metadataClient,
DB: db,
StorageBasePath: cfg.Storage.BasePath,
}
router := api.NewRouter(handlers)
server := &http.Server{
Addr: fmt.Sprintf(":%d", cfg.App.Port),
Handler: router,
}
go func() {
log.Info().Int("port", cfg.App.Port).Msg("starting server")
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatal().Err(err).Msg("server error")
}
}()
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
log.Info().Msg("shutting down server...")
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 30*time.Second)
defer shutdownCancel()
if err := server.Shutdown(shutdownCtx); err != nil {
log.Error().Err(err).Msg("server forced to shutdown")
}
if db != nil {
db.Close()
}
if torrentService.IsConfigured() {
torrentService.Disconnect(context.Background())
}
metadataClient.Close()
log.Info().Msg("server stopped")
}