package main import ( "context" "embed" "errors" "log" "net/http" "os" "os/signal" "syscall" "time" "gitlab.mareshq.com/lab/journal/httpserver" "gitlab.mareshq.com/lab/journal/journal" "gorm.io/driver/sqlite" "gorm.io/gorm" ) //go:embed assets/favicon.ico var favicon []byte //go:embed templates/* var templatesFS embed.FS func main() { ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer stop() logger := log.New(os.Stdout, "", log.LstdFlags) db, err := gorm.Open(sqlite.Open("var/local.db"), &gorm.Config{}) if err != nil { logger.Fatalf("failed to connect database: %v", err) } sqlDB, err := db.DB() if err != nil { logger.Fatalf("failed to get database: %v", err) } // graceful shutdown of database connections defer func() { err = sqlDB.Close() if err != nil { logger.Fatalf("failed to close database: %v", err) } }() err = db.AutoMigrate(&journal.Entry{}) if err != nil { logger.Fatalf("failed to migrate database: %v\n", err) } repo := journal.NewRepository(db) tr := httpserver.NewTemplateRenderer(templatesFS) mux := http.NewServeMux() fav := httpserver.NewFavicon(favicon) mux.HandleFunc("GET /favicon.ico", fav.FaviconHandler) // Journal server is HTTP interface journalServer := journal.NewServer(repo, tr, logger) journalServer.RegisterRoutes(mux) loggingMiddleware := httpserver.NewLoggingMiddleware(logger) server := &http.Server{ Addr: ":8080", Handler: loggingMiddleware.Logging(mux), } // start the HTTP server in a goroutine go func() { logger.Printf("Starting HTTP server on %s\n", server.Addr) if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed { logger.Fatalf("listen: %s\n", err) } }() <-ctx.Done() logger.Println("Received signal, shutting down...") ctxShutdown, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := server.Shutdown(ctxShutdown); err != nil && !errors.Is(err, http.ErrServerClosed) { logger.Fatalf("HTTP Server forced to shutdown: %v", err) } logger.Println("HTTP server shut down") }