package main import ( "context" "errors" "log/slog" "net/http" "os" "os/signal" "syscall" "time" ) func main() { slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stderr, nil))) cfg, err := LoadConfig() if err != nil { slog.Error("config", "err", err) os.Exit(1) } storage, err := NewStorage(cfg.StorageRoot) if err != nil { slog.Error("storage", "err", err) os.Exit(1) } var verifier Verifier if cfg.DevMode { slog.Warn("CLOUD_DEV_MODE=1 — accepting any bearer token, NOT for production") verifier = DevVerifier{} } else { verifier = NewHTTPVerifier(cfg.AuthServiceURL, cfg.ServiceKey, cfg.AuthCacheTTL) } quota := DefaultQuota(cfg.DefaultQuotaMB * 1024 * 1024) srv := NewServer(storage, verifier, quota) httpSrv := &http.Server{ Addr: cfg.Listen, Handler: srv, ReadHeaderTimeout: 5 * time.Second, } ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer stop() go func() { slog.Info("cloud-svc listening", "addr", cfg.Listen, "storage", cfg.StorageRoot) if err := httpSrv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { slog.Error("listen", "err", err) os.Exit(1) } }() <-ctx.Done() slog.Info("shutdown requested, draining…") shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() if err := httpSrv.Shutdown(shutdownCtx); err != nil { slog.Warn("shutdown", "err", err) } }