package main import ( "context" "flag" "log" "net/http" "os" "os/signal" "syscall" "time" "scratchbox/internal/cleanup" "scratchbox/internal/config" httpapi "scratchbox/internal/http" "scratchbox/internal/storage" ) func main() { configPath := flag.String("config", "", "path to config file") flag.Parse() cfg, err := config.Load(*configPath) if err != nil { log.Fatalf("config load failed: %v", err) } logger := log.New(os.Stdout, "[pastebin] ", log.LstdFlags|log.LUTC) store, err := storage.NewFilesystemStore(cfg.Storage.DataDir) if err != nil { logger.Fatalf("storage init failed: %v", err) } server, err := httpapi.NewServer(cfg, store, logger) if err != nil { logger.Fatalf("http init failed: %v", err) } cleanupWorker := cleanup.NewWorker(store, cfg.Storage.CleanupIntervalParsed, logger) ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer cancel() go cleanupWorker.Start(ctx) httpServer := &http.Server{ Addr: cfg.Server.ListenAddr, Handler: server.Routes(), } go func() { <-ctx.Done() shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 10*time.Second) defer shutdownCancel() if err := httpServer.Shutdown(shutdownCtx); err != nil { logger.Printf("http shutdown failed: %v", err) } }() logger.Printf("listening on %s", cfg.Server.ListenAddr) if err := httpServer.ListenAndServe(); err != nil && err != http.ErrServerClosed { logger.Fatalf("http server exited with error: %v", err) } }