Initial commit including .env

This commit is contained in:
2026-06-22 17:43:40 +05:30
commit c577d47b75
286 changed files with 85878 additions and 0 deletions

173
db/connect.go Normal file
View File

@@ -0,0 +1,173 @@
package db
import (
"context"
"database/sql"
"fmt"
"os"
"time"
"doormile/config"
"doormile/utils"
nats "github.com/nats-io/nats.go"
"github.com/redis/go-redis/v9"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
var (
DB *gorm.DB
Rdb *redis.Client
Ctx = context.Background()
Nc *nats.Conn
Js nats.JetStreamContext
)
func Connect(cfg *config.Config) {
dsn := fmt.Sprintf(
"host=%s user=%s password=%s dbname=%s port=%s sslmode=disable TimeZone=Asia/Kolkata",
cfg.DBHost,
cfg.DBUser,
cfg.DBPassword,
cfg.DBName,
cfg.DBPort,
)
var err error
maxRetries := 5
backoff := 2 * time.Second
for i := 1; i <= maxRetries; i++ {
utils.Info("Connecting to database", "attempt", i, "host", cfg.DBHost, "port", cfg.DBPort)
DB, err = gorm.Open(postgres.Open(dsn), &gorm.Config{
Logger: logger.Default.LogMode(logger.Error),
})
if err == nil {
sqlDB, dbErr := DB.DB()
if dbErr == nil {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if pingErr := sqlDB.PingContext(ctx); pingErr == nil {
setupDB(DB)
utils.Info("✅ Database connected successfully")
startDBHealthCheck(sqlDB)
return
} else {
err = pingErr
}
} else {
err = dbErr
}
}
utils.Error("❌ DB connection failed", "attempt", i, "error", err)
time.Sleep(backoff)
backoff *= 2
}
utils.Logger.Fatal("☢️ CRITICAL: DB connection failed after retries")
}
func setupDB(database *gorm.DB) {
sqlDB, err := database.DB()
if err != nil {
utils.Error("Failed to get sql.DB", "error", err)
return
}
sqlDB.SetMaxOpenConns(30)
sqlDB.SetMaxIdleConns(5)
sqlDB.SetConnMaxLifetime(5 * time.Minute)
sqlDB.SetConnMaxIdleTime(2 * time.Minute)
}
func startDBHealthCheck(sqlDB *sql.DB) {
go func() {
for {
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
err := sqlDB.PingContext(ctx)
cancel()
if err != nil {
utils.Error("❌ DB connection lost", "error", err)
}
time.Sleep(30 * time.Second)
}
}()
}
func CloseDB() {
if DB == nil {
return
}
sqlDB, err := DB.DB()
if err != nil {
utils.Error("Error retrieving sql.DB for close", "error", err)
return
}
utils.Info("Closing DB connection")
sqlDB.Close()
}
func InitRedis(cfg *config.Config) {
addr := fmt.Sprintf("%s:%s", cfg.RedisHost, cfg.RedisPort)
Rdb = redis.NewClient(&redis.Options{
Addr: addr,
Username: cfg.RedisUser,
Password: cfg.RedisPassword,
DB: 0,
DialTimeout: 5 * time.Second,
ReadTimeout: 3 * time.Second,
WriteTimeout: 3 * time.Second,
PoolSize: 10,
MinIdleConns: 2,
})
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
_, err := Rdb.Ping(ctx).Result()
if err != nil {
utils.Error("⚠️ Redis connection failed, continuing in fallback mode", "addr", addr, "error", err)
} else {
utils.Info("✅ Redis connected successfully", "addr", addr)
}
}
func InitNATS(cfg *config.Config) {
var err error
Nc, err = nats.Connect(
cfg.NatsURL,
nats.UserInfo(cfg.NatsUser, cfg.NatsPassword),
nats.ReconnectWait(2*time.Second),
nats.MaxReconnects(-1),
)
if err != nil {
utils.Error("⚠️ NATS connection failed, continuing without NATS", "url", cfg.NatsURL, "error", err)
return
}
Js, err = Nc.JetStream()
if err != nil {
utils.Error("⚠️ NATS JetStream init failed", "error", err)
Nc.Close()
Nc = nil
return
}
utils.Info("✅ NATS JetStream connected successfully", "url", cfg.NatsURL)
}
func getEnv(key, fallback string) string {
if val := os.Getenv(key); val != "" {
return val
}
return fallback
}