From 21db5c41660b439dc7246fb32afd14cb71a55264 Mon Sep 17 00:00:00 2001 From: grumbulon Date: Thu, 2 Feb 2023 18:02:22 -0500 Subject: [PATCH] add server death if cannot acccess DB with clean shutdown (drains connections), and other error handling, linting. --- cmd/pomme/main.go | 26 +++++++++++++++++++++++++- internal/api/api_test.go | 5 ++++- internal/api/helpers.go | 21 ++++++++++++++++----- internal/db/db.go | 14 +++++++++----- 4 files changed, 54 insertions(+), 12 deletions(-) diff --git a/cmd/pomme/main.go b/cmd/pomme/main.go index 14a736d..e8223e0 100644 --- a/cmd/pomme/main.go +++ b/cmd/pomme/main.go @@ -1,8 +1,11 @@ package main import ( + "context" "log" "net/http" + "os" + "os/signal" "time" _ "git.freecumextremist.com/grumbulon/pomme/docs" @@ -49,5 +52,26 @@ func main() { Handler: pomme, } - log.Fatal(s.ListenAndServe()) + idleConnsClosed := make(chan struct{}) + + go func() { + sigint := make(chan os.Signal, 1) + signal.Notify(sigint, os.Interrupt) + <-sigint + + // We received an interrupt signal, shut down. + if err := s.Shutdown(context.Background()); err != nil { + // Error from closing listeners, or context timeout: + log.Printf("HTTP server Shutdown: %v", err) + } + + close(idleConnsClosed) + }() + + if err := s.ListenAndServe(); err != http.ErrServerClosed { // nolint: goerr113 + // Error starting or closing listener: + log.Fatalf("HTTP server ListenAndServe: %v", err) + } + + <-idleConnsClosed } diff --git a/internal/api/api_test.go b/internal/api/api_test.go index d01d25b..e894ea9 100644 --- a/internal/api/api_test.go +++ b/internal/api/api_test.go @@ -78,7 +78,10 @@ func TestAPI(t *testing.T) { assert.NotNil(t, err) } - db := db.InitDb(c.TestDB) + db, err, ok := db.InitDb(c.TestDB) + if err != nil && !ok { + assert.NotNil(t, err) + } hashedPassword, err := bcrypt.GenerateFromPassword([]byte(tester.password), bcrypt.DefaultCost) if err != nil { diff --git a/internal/api/helpers.go b/internal/api/helpers.go index e31a1bc..cd26208 100644 --- a/internal/api/helpers.go +++ b/internal/api/helpers.go @@ -3,8 +3,8 @@ package api import ( "context" "fmt" - "log" "net/http" + "syscall" "time" "git.freecumextremist.com/grumbulon/pomme/internal" @@ -17,17 +17,28 @@ import ( // setDBMiddleware is the http Handler func for the GORM middleware with context. func setDBMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - var pommeDB *gorm.DB + var ( + pommeDB *gorm.DB + ok bool + ) c, err := internal.ReadConfig() if err != nil { - log.Printf("No config file defined: %v", err) + logHandler(genericResponseFields{"error": err.Error(), "message": "No config file defined:"}) } switch r.Header.Get("User-Agent") { case "pomme-api-test-slave": - pommeDB = db.InitDb(c.TestDB) + pommeDB, err, ok = db.InitDb(c.TestDB) default: - pommeDB = db.InitDb(c.DB) + pommeDB, err, ok = db.InitDb(c.DB) + } + + if err != nil && !ok { + logHandler(genericResponseFields{"error": err.Error(), "message": "Error initializing DB"}) + err = syscall.Kill(syscall.Getpid(), syscall.SIGINT) + if err != nil { + panic("idk what to do with this but syscall.Kill errored out.") + } } timeoutContext, cancelContext := context.WithTimeout(context.Background(), time.Second) diff --git a/internal/db/db.go b/internal/db/db.go index 5209b55..0ad431e 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -1,23 +1,27 @@ package db import ( + "fmt" + "git.freecumextremist.com/grumbulon/pomme/internal" "github.com/glebarez/sqlite" "gorm.io/gorm" ) // InitDb is the init function for the database. -func InitDb(path string) *gorm.DB { - db, err := gorm.Open(sqlite.Open(path), &gorm.Config{}) +func InitDb(path string) (db *gorm.DB, err error, ok bool) { + ok = true + db, err = gorm.Open(sqlite.Open(path), &gorm.Config{}) + if err != nil { - panic("failed to connect database") + return db, fmt.Errorf("failed to connect database: %w", err), !ok } // Migrate the schema err = db.AutoMigrate(&internal.User{}, &internal.ZoneRequest{}) if err != nil { - panic("failed to run DB migration") + return &gorm.DB{}, fmt.Errorf("failed to run DB migration: %w", err), !ok } - return db + return db, nil, ok }