package main import ( "context" "net/http" "os" "os/signal" "syscall" "time" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/mattnite/cairn/internal/blob" "github.com/mattnite/cairn/internal/config" "github.com/mattnite/cairn/internal/database" "github.com/mattnite/cairn/internal/forgejo" "github.com/mattnite/cairn/internal/web" ) func main() { zerolog.TimeFieldFormat = zerolog.TimeFormatUnix cfg, err := config.Load() if err != nil { log.Fatal().Err(err).Msg("Loading config") } ctx, cancel := context.WithCancel(context.Background()) defer cancel() db, err := database.Connect(cfg.DatabaseURL) if err != nil { log.Fatal().Err(err).Msg("Connecting to database") } if err := database.Migrate(db); err != nil { log.Fatal().Err(err).Msg("Running migrations") } store, err := blob.NewS3Store(cfg.S3Endpoint, cfg.S3AccessKey, cfg.S3SecretKey, cfg.S3Bucket, cfg.S3UseSSL) if err != nil { log.Fatal().Err(err).Msg("Creating blob store") } if err := store.EnsureBucket(ctx); err != nil { log.Fatal().Err(err).Msg("Ensuring bucket") } var forgejoClient *forgejo.Client if cfg.ForgejoURL != "" && cfg.ForgejoToken != "" { forgejoClient = forgejo.NewClient(cfg.ForgejoURL, cfg.ForgejoToken) log.Info().Str("url", cfg.ForgejoURL).Msg("Forgejo integration enabled") } router, err := web.NewRouter(web.RouterConfig{ DB: db, Store: store, ForgejoClient: forgejoClient, ForgejoURL: cfg.ForgejoURL, WebhookSecret: cfg.ForgejoWebhookSecret, }) if err != nil { log.Fatal().Err(err).Msg("Creating router") } srv := &http.Server{ Addr: cfg.ListenAddr, Handler: router, ReadTimeout: 30 * time.Second, WriteTimeout: 60 * time.Second, IdleTimeout: 120 * time.Second, } go func() { sigCh := make(chan os.Signal, 1) signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM) <-sigCh log.Info().Msg("Shutting down...") shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 10*time.Second) defer shutdownCancel() if err := srv.Shutdown(shutdownCtx); err != nil { log.Error().Err(err).Msg("Shutdown error") } }() log.Info().Str("addr", cfg.ListenAddr).Msg("Cairn server listening") if err := srv.ListenAndServe(); err != http.ErrServerClosed { log.Fatal().Err(err).Msg("Server error") } }