REFACTOR: Create Single Connection For App Lifetime
Build, Push and Deploy CMS / build-push-deploy (push) Successful in 2m6s

This commit is contained in:
FahdShalhoub
2026-08-16 23:05:15 +03:00
parent 785154cec6
commit 8bf0eae425
2 changed files with 25 additions and 30 deletions
+21 -28
View File
@@ -4,6 +4,7 @@ import (
"context"
"database/sql"
"fmt"
"log"
"thamanyah/cms/v2/internal/db"
"time"
)
@@ -31,17 +32,21 @@ type DBClient interface {
}
type DBConcrete struct {
ConnectionString string
SQLDB *sql.DB
}
func CreateConcreteDbClient(connectionString string) DBConcrete {
sqlDB, err := sql.Open("postgres", connectionString)
if err != nil {
panic(fmt.Errorf("db: cannot open connection: %w", err))
}
return DBConcrete{
SQLDB: sqlDB,
}
}
func (svc DBConcrete) CreateVideo(ctx context.Context, v Video) (Video, error) {
sqlDB, err := sql.Open("postgres", svc.ConnectionString)
if err != nil {
return Video{}, err
}
defer sqlDB.Close()
tx, err := sqlDB.BeginTx(ctx, nil)
tx, err := svc.SQLDB.BeginTx(ctx, nil)
if err != nil {
return Video{}, err
}
@@ -75,13 +80,7 @@ func (svc DBConcrete) CreateVideo(ctx context.Context, v Video) (Video, error) {
}
func (svc DBConcrete) ListCategories(ctx context.Context) ([]string, error) {
sqlDB, err := sql.Open("postgres", svc.ConnectionString)
if err != nil {
return nil, err
}
defer sqlDB.Close()
rows, err := sqlDB.QueryContext(ctx, `SELECT name FROM categories ORDER BY name`)
rows, err := svc.SQLDB.QueryContext(ctx, `SELECT name FROM categories ORDER BY name`)
if err != nil {
return nil, err
}
@@ -99,26 +98,20 @@ func (svc DBConcrete) ListCategories(ctx context.Context) ([]string, error) {
}
func (svc DBConcrete) Migrate() {
sqlDB, err := sql.Open("postgres", svc.ConnectionString)
if err != nil {
panic(fmt.Errorf("failed to open db connection: %w", err))
}
if err := db.Migrate(sqlDB); err != nil {
if err := db.Migrate(svc.SQLDB); err != nil {
panic(err)
}
sqlDB.Close()
}
// AssertSuccessfulConnection verifies the database is reachable, mirroring
// S3Concrete's boot-time check — panics rather than let the service come up broken.
func (svc DBConcrete) AssertSuccessfulConnection(ctx context.Context) {
sqlDB, err := sql.Open("postgres", svc.ConnectionString)
func (svc DBConcrete) CloseConnection() {
err := svc.SQLDB.Close()
if err != nil {
panic(fmt.Errorf("db: cannot open connection: %w", err))
log.Fatalf("Error Closing DB Connection: %s", err)
}
defer sqlDB.Close()
}
if err := sqlDB.PingContext(ctx); err != nil {
func (svc DBConcrete) AssertSuccessfulConnection(ctx context.Context) {
if err := svc.SQLDB.PingContext(ctx); err != nil {
panic(fmt.Errorf("db: cannot connect: %w", err))
}
}
+4 -2
View File
@@ -24,7 +24,8 @@ func main() {
}
func runMigrate() {
concreteDBClient := &services.DBConcrete{ConnectionString: requireDBConnectionString()}
concreteDBClient := services.CreateConcreteDbClient(requireDBConnectionString())
defer concreteDBClient.CloseConnection()
concreteDBClient.Migrate()
log.Println("migrations applied successfully")
}
@@ -70,7 +71,8 @@ func runServer() {
OutputBucket: mediaConvertOutputBucket,
}
concreteDBClient := &services.DBConcrete{ConnectionString: requireDBConnectionString()}
concreteDBClient := services.CreateConcreteDbClient(requireDBConnectionString())
defer concreteDBClient.CloseConnection()
concreteDBClient.AssertSuccessfulConnection(context.Background())
services.DB = concreteDBClient