193 lines
6.1 KiB
Go
193 lines
6.1 KiB
Go
package main
|
||
|
||
import (
|
||
"flag"
|
||
"fmt"
|
||
"os"
|
||
"os/signal"
|
||
"strconv"
|
||
"syscall"
|
||
|
||
dubboclient "dubbo.apache.org/dubbo-go/v3/client"
|
||
_ "dubbo.apache.org/dubbo-go/v3/imports"
|
||
"dubbo.apache.org/dubbo-go/v3/protocol"
|
||
"dubbo.apache.org/dubbo-go/v3/server"
|
||
|
||
"github.com/topfans/backend/pkg/database"
|
||
"github.com/topfans/backend/pkg/health"
|
||
"github.com/topfans/backend/pkg/logger"
|
||
"github.com/topfans/backend/pkg/models"
|
||
pbAsset "github.com/topfans/backend/pkg/proto/asset"
|
||
pbGallery "github.com/topfans/backend/pkg/proto/gallery"
|
||
pbUser "github.com/topfans/backend/pkg/proto/user"
|
||
rpcclient "github.com/topfans/backend/services/galleryService/client"
|
||
"github.com/topfans/backend/services/galleryService/provider"
|
||
"github.com/topfans/backend/services/galleryService/repository"
|
||
"github.com/topfans/backend/services/galleryService/service"
|
||
)
|
||
|
||
var (
|
||
port = flag.Int("port", getEnvInt("PORT", 20001), "Dubbo service port")
|
||
dbHost = flag.String("db-host", getEnv("DB_HOST", "localhost"), "Database host")
|
||
dbPort = flag.Int("db-port", getEnvInt("DB_PORT", 5432), "Database port")
|
||
dbUser = flag.String("db-user", getEnv("DB_USER", "postgres"), "Database user")
|
||
dbPassword = flag.String("db-password", getEnv("DB_PASSWORD", ""), "Database password")
|
||
dbName = flag.String("db-name", getEnv("DB_NAME", "top-fans"), "Database name")
|
||
assetServiceURL = flag.String("asset-service-url", getEnv("ASSET_SERVICE_URL", "tri://localhost:20003"), "Asset service URL")
|
||
userServiceURL = flag.String("user-service-url", getEnv("USER_SERVICE_URL", "tri://localhost:20000"), "User service URL")
|
||
healthHandler *health.Handler
|
||
)
|
||
|
||
func getEnv(key, fallback string) string {
|
||
if v := os.Getenv(key); v != "" {
|
||
return v
|
||
}
|
||
return fallback
|
||
}
|
||
|
||
func getEnvInt(key string, fallback int) int {
|
||
if v := os.Getenv(key); v != "" {
|
||
if n, err := strconv.Atoi(v); err == nil {
|
||
return n
|
||
}
|
||
}
|
||
return fallback
|
||
}
|
||
|
||
func main() {
|
||
flag.Parse()
|
||
|
||
// 初始化日志(必须在最前面)
|
||
env := os.Getenv("ENV")
|
||
if env == "" {
|
||
env = "development"
|
||
}
|
||
|
||
if err := logger.Init(logger.Config{
|
||
ServiceName: "gallery-service",
|
||
Environment: env,
|
||
LogLevel: os.Getenv("LOG_LEVEL"),
|
||
}); err != nil {
|
||
panic(fmt.Sprintf("Failed to initialize logger: %v", err))
|
||
}
|
||
defer logger.Sync()
|
||
|
||
logger.Logger.Info("Starting Gallery Service...")
|
||
|
||
// 初始化数据库
|
||
dbConfig := database.Config{
|
||
Host: *dbHost,
|
||
Port: *dbPort,
|
||
User: *dbUser,
|
||
Password: *dbPassword,
|
||
DBName: *dbName,
|
||
SSLMode: "disable",
|
||
TimeZone: "Asia/Shanghai",
|
||
}
|
||
|
||
if err := database.Init(dbConfig); err != nil {
|
||
logger.Logger.Fatal(fmt.Sprintf("Failed to initialize database: %v", err))
|
||
}
|
||
logger.Logger.Info("Database initialized successfully")
|
||
|
||
// 启动健康检查 HTTP 服务器
|
||
healthPort := *port + 1000 // e.g., 20001 -> 21001
|
||
healthHandler = health.NewHandler("gallery-service", healthPort)
|
||
healthHandler.Start()
|
||
|
||
// 创建 Repository 层实例
|
||
db := database.GetDB()
|
||
// 自动迁移展馆相关表(booth_slots / exhibitions)
|
||
if err := db.AutoMigrate(&models.BoothSlot{}, &models.Exhibition{}); err != nil {
|
||
logger.Logger.Fatal(fmt.Sprintf("Failed to migrate gallery tables: %v", err))
|
||
}
|
||
|
||
galleryRepo := repository.NewGalleryRepository(db)
|
||
logger.Logger.Info("Repository layer initialized")
|
||
|
||
// 创建 Dubbo 客户端
|
||
assetCli, err := dubboclient.NewClient(
|
||
dubboclient.WithClientURL(*assetServiceURL),
|
||
)
|
||
if err != nil {
|
||
logger.Logger.Fatal(fmt.Sprintf("Failed to create Asset Service Dubbo client: %v", err))
|
||
}
|
||
|
||
userCli, err := dubboclient.NewClient(
|
||
dubboclient.WithClientURL(*userServiceURL),
|
||
)
|
||
if err != nil {
|
||
logger.Logger.Fatal(fmt.Sprintf("Failed to create User Service Dubbo client: %v", err))
|
||
}
|
||
|
||
// 获取 Asset Service RPC 客户端
|
||
assetServiceClient, err := pbAsset.NewAssetService(assetCli)
|
||
if err != nil {
|
||
logger.Logger.Fatal(fmt.Sprintf("Failed to create Asset Service RPC client: %v", err))
|
||
}
|
||
assetRPCClient := rpcclient.NewAssetRPCClient(assetServiceClient)
|
||
logger.Logger.Info("Asset Service RPC client initialized")
|
||
|
||
// 获取 User Service RPC 客户端
|
||
userServiceClient, err := pbUser.NewUserSocialService(userCli)
|
||
if err != nil {
|
||
logger.Logger.Fatal(fmt.Sprintf("Failed to create User Service RPC client: %v", err))
|
||
}
|
||
userRPCClient := rpcclient.NewUserRPCClient(userServiceClient)
|
||
logger.Logger.Info("User Service RPC client initialized")
|
||
|
||
// 创建 Service 层实例
|
||
galleryService := service.NewGalleryService(galleryRepo, assetRPCClient, userRPCClient)
|
||
slotService := service.NewSlotService(galleryRepo, userRPCClient)
|
||
exhibitionService := service.NewExhibitionService(galleryRepo, assetRPCClient)
|
||
logger.Logger.Info("Service layer initialized")
|
||
|
||
// 创建并启动清理 Worker(注入 assetRPCClient 以便下架时清除点赞记录)
|
||
cleanupWorker := service.NewCleanupWorker(galleryRepo, assetRPCClient)
|
||
go cleanupWorker.Start()
|
||
logger.Logger.Info("Cleanup worker started")
|
||
|
||
// 创建 Provider 层实例
|
||
galleryProvider := provider.NewGalleryProvider(galleryService, slotService, exhibitionService)
|
||
logger.Logger.Info("Provider layer initialized")
|
||
|
||
// 创建 Dubbo 服务器
|
||
srv, err := server.NewServer(
|
||
server.WithServerProtocol(
|
||
protocol.WithPort(*port),
|
||
protocol.WithTriple(),
|
||
),
|
||
)
|
||
if err != nil {
|
||
logger.Logger.Fatal(fmt.Sprintf("Failed to create Dubbo server: %v", err))
|
||
}
|
||
|
||
// 使用 Triple 协议生成的 RegisterHandler 函数注册服务
|
||
if err := pbGallery.RegisterGalleryServiceHandler(srv, galleryProvider); err != nil {
|
||
logger.Logger.Fatal(fmt.Sprintf("Failed to register Gallery Service: %v", err))
|
||
}
|
||
|
||
// 启动服务
|
||
if err := srv.Serve(); err != nil {
|
||
logger.Logger.Fatal(fmt.Sprintf("Failed to start Gallery Service: %v", err))
|
||
}
|
||
|
||
logger.Logger.Info(fmt.Sprintf("Gallery Service started successfully on port %d", *port))
|
||
|
||
// 等待退出信号
|
||
quit := make(chan os.Signal, 1)
|
||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
||
<-quit
|
||
|
||
logger.Logger.Info("Shutting down Gallery Service...")
|
||
|
||
// 停止健康检查服务器
|
||
if healthHandler != nil {
|
||
healthHandler.Stop()
|
||
}
|
||
|
||
// 停止清理 Worker
|
||
cleanupWorker.Stop()
|
||
logger.Logger.Info("Cleanup worker stopped")
|
||
}
|