package main import ( "context" "errors" "net/http" "os" "os/signal" "syscall" "time" "git.apinb.com/bsm-sdk/core/infra" "git.apinb.com/bsm-sdk/core/middleware" "git.apinb.com/ops/files/internal/config" "git.apinb.com/ops/files/internal/impl" "git.apinb.com/ops/files/internal/jobs" "git.apinb.com/ops/files/internal/models" "git.apinb.com/ops/files/internal/routers" "github.com/gin-gonic/gin" ) const ServiceKey = "Files" func main() { ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer stop() config.New(ServiceKey) impl.NewImpl() if err := models.RequireSchemaVersion(impl.DBService, "files"); err != nil { panic(err) } if err := models.RequireStorageProvider(impl.DBService, impl.StorageService.Provider()); err != nil { panic(err) } if err := jobs.StartPendingUploadCleanup(ctx); err != nil { if closeErr := impl.Close(); closeErr != nil { panic(errors.Join(err, closeErr)) } panic(err) } if err := jobs.StartIntegrity(ctx); err != nil { stop() waitCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) waitErr := jobs.Wait(waitCtx) cancel() if closeErr := impl.Close(); closeErr != nil { panic(errors.Join(err, waitErr, closeErr)) } panic(errors.Join(err, waitErr)) } app := gin.Default() middleware.Mode(app) app.Use(middleware.Cors()) app.Use(gin.Recovery()) app.HEAD("/", infra.Health) routers.Register(ServiceKey, app) serveErr := serve(ctx, app) stop() waitCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) waitErr := jobs.Wait(waitCtx) cancel() closeErr := impl.Close() if err := errors.Join(serveErr, waitErr, closeErr); err != nil { panic(err) } } func serve(ctx context.Context, app http.Handler) error { server := &http.Server{Addr: config.Spec.Addr, Handler: app, ReadHeaderTimeout: 10 * time.Second} errCh := make(chan error, 1) go func() { errCh <- server.ListenAndServe() }() select { case err := <-errCh: if errors.Is(err, http.ErrServerClosed) { return nil } return err case <-ctx.Done(): shutdownCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() return server.Shutdown(shutdownCtx) } }