add: server shutdown, tests
This commit is contained in:
@@ -1,12 +1,54 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"GoMembership/internal/config"
|
||||||
|
"GoMembership/internal/database"
|
||||||
"GoMembership/internal/server"
|
"GoMembership/internal/server"
|
||||||
"GoMembership/pkg/logger"
|
"GoMembership/pkg/logger"
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
logger.Info.Println("startup...")
|
logger.Info.Println("startup...")
|
||||||
server.Run()
|
|
||||||
|
config.LoadConfig()
|
||||||
|
logger.Info.Printf("Config loaded: %#v", config.CFG)
|
||||||
|
|
||||||
|
err := database.Open(config.DB.Path)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error.Fatalf("Couldn't init database: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if err := database.Close(); err != nil {
|
||||||
|
logger.Error.Fatalf("Failed to close database: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
go server.Run()
|
||||||
|
|
||||||
|
gracefulShutdown()
|
||||||
|
}
|
||||||
|
|
||||||
|
func gracefulShutdown() {
|
||||||
|
// Create a channel to listen for OS signals
|
||||||
|
stop := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(stop, os.Interrupt, syscall.SIGTERM)
|
||||||
|
|
||||||
|
// Block until a signal is received
|
||||||
|
<-stop
|
||||||
|
logger.Info.Println("Received shutdown signal")
|
||||||
|
|
||||||
|
// Create a context with a timeout for the shutdown process
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
// Call the server's shutdown function
|
||||||
|
server.Shutdown(ctx)
|
||||||
|
logger.Info.Println("Server gracefully stopped")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ var (
|
|||||||
|
|
||||||
func TestSuite(t *testing.T) {
|
func TestSuite(t *testing.T) {
|
||||||
_ = deleteTestDB("test.db")
|
_ = deleteTestDB("test.db")
|
||||||
if err := database.InitDB("test.db"); err != nil {
|
if err := database.Open("test.db"); err != nil {
|
||||||
log.Fatalf("Failed to create DB: %#v", err)
|
log.Fatalf("Failed to create DB: %#v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,15 +29,15 @@ func (mc *MembershipController) RegisterSubscription(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger.Info.Printf("Using API key: %v", config.Auth.APIKEY)
|
logger.Info.Printf("Using API key: %v", config.Auth.APIKEY)
|
||||||
|
|
||||||
if regData.APIKey == "" {
|
if regData.APIKey == "" {
|
||||||
logger.Error.Println("API Key is missing")
|
logger.Error.Println("API Key is missing")
|
||||||
c.JSON(http.StatusBadRequest, "API Key is missing")
|
c.JSON(http.StatusUnauthorized, "API Key is missing")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if regData.APIKey != config.Auth.APIKEY {
|
if regData.APIKey != config.Auth.APIKEY {
|
||||||
logger.Error.Printf("API Key not valid: %v", regData.APIKey)
|
logger.Error.Printf("API Key not valid: %v", regData.APIKey)
|
||||||
c.JSON(http.StatusExpectationFailed, "API Key is missing")
|
c.JSON(http.StatusUnauthorized, "API Key is missing")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -80,6 +80,28 @@ func customizeSubscription(customize func(MembershipData) MembershipData) Member
|
|||||||
|
|
||||||
func getSubscriptionData() []RegisterSubscriptionTest {
|
func getSubscriptionData() []RegisterSubscriptionTest {
|
||||||
return []RegisterSubscriptionTest{
|
return []RegisterSubscriptionTest{
|
||||||
|
{
|
||||||
|
Name: "No API Key should fail",
|
||||||
|
WantResponse: http.StatusUnauthorized,
|
||||||
|
WantDBData: map[string]interface{}{"name": "Just a Subscription"},
|
||||||
|
Assert: false,
|
||||||
|
Input: GenerateInputJSON(
|
||||||
|
customizeSubscription(func(subscription MembershipData) MembershipData {
|
||||||
|
subscription.APIKey = ""
|
||||||
|
return subscription
|
||||||
|
})),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Wrong API Key should fail",
|
||||||
|
WantResponse: http.StatusUnauthorized,
|
||||||
|
WantDBData: map[string]interface{}{"name": "Just a Subscription"},
|
||||||
|
Assert: false,
|
||||||
|
Input: GenerateInputJSON(
|
||||||
|
customizeSubscription(func(subscription MembershipData) MembershipData {
|
||||||
|
subscription.APIKey = "alskfdlkjsfjk23-dF"
|
||||||
|
return subscription
|
||||||
|
})),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: "No Details should fail",
|
Name: "No Details should fail",
|
||||||
WantResponse: http.StatusNotAcceptable,
|
WantResponse: http.StatusNotAcceptable,
|
||||||
|
|||||||
@@ -3,13 +3,14 @@ package database
|
|||||||
import (
|
import (
|
||||||
"GoMembership/internal/models"
|
"GoMembership/internal/models"
|
||||||
"GoMembership/pkg/logger"
|
"GoMembership/pkg/logger"
|
||||||
|
|
||||||
"gorm.io/driver/sqlite"
|
"gorm.io/driver/sqlite"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
var DB *gorm.DB
|
var DB *gorm.DB
|
||||||
|
|
||||||
func InitDB(dbPath string) error {
|
func Open(dbPath string) error {
|
||||||
|
|
||||||
db, err := gorm.Open(sqlite.Open(dbPath), &gorm.Config{})
|
db, err := gorm.Open(sqlite.Open(dbPath), &gorm.Config{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -26,5 +27,16 @@ func InitDB(dbPath string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
DB = db
|
DB = db
|
||||||
|
|
||||||
|
logger.Info.Print("Opened DB")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Close() error {
|
||||||
|
logger.Info.Print("Closing DB")
|
||||||
|
db, err := DB.DB()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return db.Close()
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"GoMembership/internal/config"
|
"GoMembership/internal/config"
|
||||||
"GoMembership/internal/server"
|
// "GoMembership/internal/server"
|
||||||
"GoMembership/internal/utils"
|
"GoMembership/internal/utils"
|
||||||
"GoMembership/pkg/logger"
|
"GoMembership/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,12 +4,12 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"GoMembership/internal/config"
|
"GoMembership/internal/config"
|
||||||
"GoMembership/internal/controllers"
|
"GoMembership/internal/controllers"
|
||||||
"GoMembership/internal/database"
|
|
||||||
"GoMembership/internal/repositories"
|
"GoMembership/internal/repositories"
|
||||||
|
|
||||||
// "GoMembership/internal/middlewares"
|
// "GoMembership/internal/middlewares"
|
||||||
@@ -20,15 +20,10 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var shutdownChannel = make(chan struct{})
|
||||||
|
|
||||||
// Run initializes the server configuration, sets up services and controllers, and starts the HTTP server.
|
// Run initializes the server configuration, sets up services and controllers, and starts the HTTP server.
|
||||||
func Run() {
|
func Run() {
|
||||||
config.LoadConfig()
|
|
||||||
logger.Info.Printf("Config loaded: %#v", config.CFG)
|
|
||||||
|
|
||||||
err := database.InitDB(config.DB.Path)
|
|
||||||
if err != nil {
|
|
||||||
logger.Error.Fatalf("Couldn't init database: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
emailService := services.NewEmailService(config.SMTP.Host, config.SMTP.Port, config.SMTP.User, config.SMTP.Password)
|
emailService := services.NewEmailService(config.SMTP.Host, config.SMTP.Port, config.SMTP.User, config.SMTP.Password)
|
||||||
var consentRepo repositories.ConsentRepositoryInterface = &repositories.ConsentRepository{}
|
var consentRepo repositories.ConsentRepositoryInterface = &repositories.ConsentRepository{}
|
||||||
@@ -63,7 +58,23 @@ func Run() {
|
|||||||
// accountRouter.Use(middlewares.AuthMiddleware)
|
// accountRouter.Use(middlewares.AuthMiddleware)
|
||||||
|
|
||||||
logger.Info.Println("Starting server on :8080")
|
logger.Info.Println("Starting server on :8080")
|
||||||
if err := http.ListenAndServe(":8080", router); err != nil {
|
go func() {
|
||||||
|
if err := http.ListenAndServe(":8080", router); err != nil && err != http.ErrServerClosed {
|
||||||
logger.Error.Fatalf("could not start server: %v", err)
|
logger.Error.Fatalf("could not start server: %v", err)
|
||||||
}
|
}
|
||||||
|
}()
|
||||||
|
// Wait for the shutdown signal
|
||||||
|
<-shutdownChannel
|
||||||
|
}
|
||||||
|
|
||||||
|
func Shutdown(ctx context.Context) {
|
||||||
|
// Signal the server to stop
|
||||||
|
close(shutdownChannel)
|
||||||
|
|
||||||
|
// Optionally wait for a timeout or other cleanup operations
|
||||||
|
// ctx can be used to manage shutdown timeout or cleanup tasks
|
||||||
|
// select {
|
||||||
|
// case <-ctx.Done():
|
||||||
|
// // handle context cancellation if needed
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user