package main import ( "database/sql" "fmt" "log" "net" "tailly_clips/internal/ffmpeg" "tailly_clips/internal/handler" "tailly_clips/internal/moderation" "tailly_clips/internal/repository" "tailly_clips/internal/service" "tailly_clips/internal/storage" "tailly_clips/proto" "time" "github.com/caarlos0/env/v8" "github.com/joho/godotenv" _ "github.com/lib/pq" "google.golang.org/grpc" ) // Config структура конфигурации type Config struct { DBHost string `env:"DB_HOST" env-default:"localhost"` DBPort string `env:"DB_PORT" env-default:"5432"` DBUser string `env:"DB_USER" env-default:"postgres"` DBPassword string `env:"DB_PASSWORD" env-default:"postgres"` DBName string `env:"DB_NAME" env-default:"clip_service"` S3Endpoint string `env:"S3_ENDPOINT,required"` S3Bucket string `env:"S3_BUCKET,required"` S3Region string `env:"S3_REGION,required"` S3AccessKey string `env:"S3_ACCESS_KEY,required"` S3SecretKey string `env:"S3_SECRET_KEY,required"` ModerationAddr string `env:"MODERATION_ADDR" env-default:"localhost:50051"` } func main() { // Загрузка конфигурации cfg, err := loadConfig() if err != nil { log.Fatalf("Failed to load config: %v", err) } // Инициализация базы данных db, err := initDatabase(cfg) if err != nil { log.Fatalf("Failed to initialize database: %v", err) } defer db.Close() // Инициализация S3 storage s3Storage := storage.NewS3Storage(storage.S3Config{ Endpoint: cfg.S3Endpoint, Bucket: cfg.S3Bucket, Region: cfg.S3Region, AccessKey: cfg.S3AccessKey, SecretKey: cfg.S3SecretKey, }) modClient, err := moderation.NewModerationClient(cfg.ModerationAddr) if err != nil { log.Fatalf("Failed to create moderation client: %v", err) } defer modClient.Close() videoProcessor := ffmpeg.NewVideoProcessor() clipRepo := repository.NewClipRepository(db) likeRepo := repository.NewLikeRepository(db) commentRepo := repository.NewCommentRepository(db) clipService := service.NewClipService(clipRepo, s3Storage, videoProcessor, modClient) likeService := service.NewLikeService(likeRepo, clipRepo) commentService := service.NewCommentService(commentRepo, clipRepo) grpcHandler := handler.NewGRPCHandler(clipService, likeService, commentService) server := grpc.NewServer() proto.RegisterClipServiceServer(server, grpcHandler) lis, err := net.Listen("tcp", ":50054") if err != nil { log.Fatalf("Failed to listen: %v", err) } log.Println("Clip service started on :50054") if err := server.Serve(lis); err != nil { log.Fatalf("Failed to serve: %v", err) } } func loadConfig() (*Config, error) { // Загружаем .env файл (игнорируем ошибку если файла нет) _ = godotenv.Load() cfg := &Config{} if err := env.Parse(cfg); err != nil { return nil, err } return cfg, nil } func initDatabase(cfg *Config) (*sql.DB, error) { connStr := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=disable", cfg.DBHost, cfg.DBPort, cfg.DBUser, cfg.DBPassword, cfg.DBName) db, err := sql.Open("postgres", connStr) if err != nil { return nil, fmt.Errorf("failed to open database: %w", err) } if err = db.Ping(); err != nil { return nil, fmt.Errorf("failed to ping database: %w", err) } db.SetMaxOpenConns(25) db.SetMaxIdleConns(25) db.SetConnMaxLifetime(5 * time.Minute) log.Println("Database connected successfully") return db, nil }