a8862721cd
Static directory for public folders and business logic for the app within internal, split into domain specific folders to keep clear seperation of concerns.
87 lines
2.0 KiB
Go
87 lines
2.0 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
"time"
|
|
|
|
"nfeeder/internal/db"
|
|
"nfeeder/internal/web"
|
|
|
|
"github.com/jackc/pgx/v5/pgxpool"
|
|
)
|
|
|
|
func main() {
|
|
ctx, ctxCancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
|
defer ctxCancel()
|
|
|
|
// DB init
|
|
// ------------------------------------------------------------
|
|
connStr := os.Getenv("DATABASE_URL")
|
|
if connStr == "" {
|
|
log.Fatal("DATABASE_URL environment variable is not set")
|
|
}
|
|
|
|
poolConfig, err := pgxpool.ParseConfig(connStr)
|
|
if err != nil {
|
|
log.Fatalf("Unable to parse DATABASE_URL: %v", err)
|
|
}
|
|
|
|
poolConfig.MaxConns = 25
|
|
poolConfig.MinConns = 5
|
|
poolConfig.MaxConnLifetime = 5 * time.Minute
|
|
poolConfig.MaxConnIdleTime = 30 * time.Second
|
|
|
|
pool, err := pgxpool.NewWithConfig(ctx, poolConfig)
|
|
if err != nil {
|
|
log.Fatalf("Unable to create connection pool: %v", err)
|
|
}
|
|
|
|
// Verify the connection is alive before proceeding
|
|
if err := pool.Ping(ctx); err != nil {
|
|
log.Fatalf("Unable to reach database: %v", err)
|
|
}
|
|
fmt.Println("Database connection established")
|
|
|
|
defer func() {
|
|
pool.Close()
|
|
fmt.Println("Database pool closed")
|
|
}()
|
|
|
|
// Create Store sqlc wrapper
|
|
store := db.NewStore(pool)
|
|
|
|
// Server Init
|
|
// ------------------------------------------------------------
|
|
server := web.NewServer(store)
|
|
|
|
// We run it in a goroutine so it doesn't block main from reaching the signal listener.
|
|
go func() {
|
|
addr := ":3000"
|
|
fmt.Printf("Server starting on %s\n", addr)
|
|
|
|
if err := server.Start(addr); err != nil && err != http.ErrServerClosed {
|
|
log.Fatalf("Server failed: %v", err)
|
|
}
|
|
}()
|
|
|
|
// Graceful Shutdown
|
|
// ------------------------------------------------------------
|
|
<-ctx.Done()
|
|
fmt.Println("\nShutdown signal received. Starting graceful exit...")
|
|
|
|
shutdownCtx, shutdownCtxCancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer shutdownCtxCancel()
|
|
|
|
if err := server.Shutdown(shutdownCtx); err != nil {
|
|
log.Fatalf("Graceful shutdown failed: %v", err)
|
|
}
|
|
|
|
fmt.Println("Server exited properly")
|
|
}
|