Initial project structure commit.

Static directory for public folders and business logic for the app
within internal, split into domain specific folders to keep clear
seperation of concerns.
This commit is contained in:
2026-04-23 08:09:09 +02:00
parent f3ccbc95c1
commit a8862721cd
18 changed files with 1048 additions and 0 deletions
+86
View File
@@ -0,0 +1,86 @@
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")
}