initial commit
This commit is contained in:
139
internal/config/config.go
Normal file
139
internal/config/config.go
Normal file
@@ -0,0 +1,139 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
// Config содержит конфигурацию приложения
|
||||
type Config struct {
|
||||
// Database
|
||||
DatabaseURL string
|
||||
|
||||
// Server
|
||||
ServerHost string
|
||||
ServerPort string
|
||||
AppEnv string
|
||||
|
||||
// JWT
|
||||
JWTSecret string
|
||||
JWTAccessTokenTTL time.Duration
|
||||
JWTRefreshTokenTTL time.Duration
|
||||
|
||||
// CORS
|
||||
CORSAllowedOrigins []string
|
||||
CORSAllowedMethods []string
|
||||
CORSAllowedHeaders []string
|
||||
|
||||
// Rate Limiting
|
||||
RateLimitRequestsPerMinute int
|
||||
RateLimitBurst int
|
||||
|
||||
// Matching Algorithm
|
||||
MatchingDefaultRadiusMeters int
|
||||
MatchingDefaultLimit int
|
||||
}
|
||||
|
||||
// Load загружает конфигурацию из переменных окружения
|
||||
func Load() (*Config, error) {
|
||||
// Загружаем .env файл если он существует
|
||||
_ = godotenv.Load()
|
||||
|
||||
cfg := &Config{
|
||||
DatabaseURL: getDatabaseURL(),
|
||||
ServerHost: getEnv("APP_HOST", "0.0.0.0"),
|
||||
ServerPort: getEnv("APP_PORT", "8080"),
|
||||
AppEnv: getEnv("APP_ENV", "development"),
|
||||
|
||||
JWTSecret: getEnv("JWT_SECRET", "change_me_to_secure_random_string_min_32_chars"),
|
||||
JWTAccessTokenTTL: parseDuration(getEnv("JWT_ACCESS_TOKEN_EXPIRY", "15m")),
|
||||
JWTRefreshTokenTTL: parseDuration(getEnv("JWT_REFRESH_TOKEN_EXPIRY", "168h")), // 7 days
|
||||
|
||||
RateLimitRequestsPerMinute: getEnvInt("RATE_LIMIT_REQUESTS_PER_MINUTE", 60),
|
||||
RateLimitBurst: getEnvInt("RATE_LIMIT_BURST", 10),
|
||||
|
||||
MatchingDefaultRadiusMeters: getEnvInt("MATCHING_DEFAULT_RADIUS_METERS", 10000),
|
||||
MatchingDefaultLimit: getEnvInt("MATCHING_DEFAULT_LIMIT", 20),
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
// NewDBPool создает новый пул соединений с БД
|
||||
func NewDBPool(ctx context.Context, databaseURL string) (*pgxpool.Pool, error) {
|
||||
config, err := pgxpool.ParseConfig(databaseURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse database URL: %w", err)
|
||||
}
|
||||
|
||||
// Настройка пула соединений
|
||||
config.MaxConns = 25
|
||||
config.MinConns = 5
|
||||
config.MaxConnLifetime = time.Hour
|
||||
config.MaxConnIdleTime = time.Minute * 30
|
||||
config.HealthCheckPeriod = time.Minute
|
||||
|
||||
pool, err := pgxpool.NewWithConfig(ctx, config)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create connection pool: %w", err)
|
||||
}
|
||||
|
||||
// Проверка соединения
|
||||
if err := pool.Ping(ctx); err != nil {
|
||||
return nil, fmt.Errorf("failed to ping database: %w", err)
|
||||
}
|
||||
|
||||
return pool, nil
|
||||
}
|
||||
|
||||
// getDatabaseURL собирает DATABASE_URL из отдельных переменных или использует готовый
|
||||
func getDatabaseURL() string {
|
||||
// Если задан DATABASE_URL, используем его
|
||||
if url := os.Getenv("DATABASE_URL"); url != "" {
|
||||
return url
|
||||
}
|
||||
|
||||
// Иначе собираем из отдельных переменных
|
||||
user := getEnv("DB_USER", "volontery")
|
||||
password := getEnv("DB_PASSWORD", "volontery")
|
||||
host := getEnv("DB_HOST", "localhost")
|
||||
port := getEnv("DB_PORT", "5432")
|
||||
name := getEnv("DB_NAME", "volontery_db")
|
||||
sslmode := getEnv("DB_SSLMODE", "disable")
|
||||
|
||||
return fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=%s",
|
||||
user, password, host, port, name, sslmode)
|
||||
}
|
||||
|
||||
// getEnv получает переменную окружения или возвращает значение по умолчанию
|
||||
func getEnv(key, defaultValue string) string {
|
||||
if value := os.Getenv(key); value != "" {
|
||||
return value
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
// getEnvInt получает целочисленную переменную окружения
|
||||
func getEnvInt(key string, defaultValue int) int {
|
||||
if value := os.Getenv(key); value != "" {
|
||||
if intVal, err := strconv.Atoi(value); err == nil {
|
||||
return intVal
|
||||
}
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
// parseDuration парсит duration строку
|
||||
func parseDuration(s string) time.Duration {
|
||||
d, err := time.ParseDuration(s)
|
||||
if err != nil {
|
||||
return 15 * time.Minute // default
|
||||
}
|
||||
return d
|
||||
}
|
||||
Reference in New Issue
Block a user