country-geo-locations/main.go
Tom Neuber 4060ec09c4
All checks were successful
ci/woodpecker/push/lint Pipeline was successful
ci/woodpecker/push/test Pipeline was successful
ci/woodpecker/push/build Pipeline was successful
ci/woodpecker/push/deploy Pipeline was successful
fix: adjust some code structure to satisfy linter
2025-04-18 15:34:34 +02:00

114 lines
2.7 KiB
Go

package main
import (
"log/slog"
"net/http"
"os"
"os/signal"
"syscall"
"time"
apiv1 "git.ar21.de/yolokube/country-geo-locations/api/v1"
"git.ar21.de/yolokube/country-geo-locations/internal/cache"
"git.ar21.de/yolokube/country-geo-locations/internal/cmd"
csvimporter "git.ar21.de/yolokube/country-geo-locations/internal/csv_importer"
"git.ar21.de/yolokube/country-geo-locations/internal/database"
"git.ar21.de/yolokube/country-geo-locations/internal/downloader"
"git.ar21.de/yolokube/country-geo-locations/internal/exporter"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
"github.com/go-chi/render"
)
func main() {
cli := cmd.CLI{}
config, err := cli.Parse()
if err != nil {
panic(err)
}
handleGracefulShutdown()
r := chi.NewRouter()
r.Use(middleware.RequestID)
r.Use(middleware.Logger)
r.Use(middleware.Recoverer)
r.Use(render.SetContentType(render.ContentTypeJSON))
ctx := downloader.NewContext(config.DataFile, config.DataURL)
if !ctx.FileExists() {
if downloadErr := ctx.Download(); downloadErr != nil {
panic(err)
}
slog.Info("saved file", "path", ctx.Filename)
}
cache := cache.NewCache(config.CacheTTL)
db, err := database.NewDatabase(config)
if err != nil {
slog.Error("database creation failed")
panic(err)
}
if config.EnableExporter {
exporter := exporter.NewExporter(config, cache, db)
r.Use(exporter.Middleware())
ticker := time.NewTicker(config.ExporterInterval)
exit := make(chan struct{})
go func() {
for {
select {
case <-ticker.C:
exporter.Collect()
case <-exit:
ticker.Stop()
return
}
}
}()
slog.Info("prometheus exporter refreshes metric data", "interval", config.ExporterInterval)
go func() {
err = exporter.Start()
if err != nil {
panic(err)
}
}()
slog.Info("prometheus exporter started", "address", config.ExporterAddress)
}
slog.Info("importing data from file", "path", config.DataFile)
err = csvimporter.ImportCSV(config.DataFile, db)
if err != nil {
slog.Error("data import from file failed")
panic(err)
}
slog.Info("imported data from file successfully")
lh := apiv1.NewLocationHandler(cache, db)
r.Mount("/api/v1", apiv1.NewRouter(lh))
server := &http.Server{
Addr: config.ServerAddress,
Handler: r,
ReadHeaderTimeout: config.ReadHeaderTimeout,
}
slog.Info("starting server", "address", server.Addr)
if err = server.ListenAndServe(); err != nil {
panic(err)
}
}
func handleGracefulShutdown() {
var signals = make(chan os.Signal, 1)
signal.Notify(signals, syscall.SIGTERM, syscall.SIGINT)
go func() {
sig := <-signals
slog.Info("caught signal", "signal", sig)
os.Exit(0)
}()
}