topfans/backend/services/assetService/main.go
2026-04-07 22:29:48 +08:00

190 lines
5.8 KiB
Go

package main
import (
"flag"
"fmt"
"os"
"os/signal"
"strconv"
"syscall"
"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/logger"
"github.com/topfans/backend/pkg/models"
pbAsset "github.com/topfans/backend/pkg/proto/asset"
pbRanking "github.com/topfans/backend/pkg/proto/ranking"
pbUser "github.com/topfans/backend/pkg/proto/user"
assetClient "github.com/topfans/backend/services/assetService/client"
"github.com/topfans/backend/services/assetService/config"
"github.com/topfans/backend/services/assetService/provider"
"github.com/topfans/backend/services/assetService/repository"
"github.com/topfans/backend/services/assetService/service"
)
var (
port = flag.Int("port", getEnvInt("PORT", 20003), "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")
userServiceURL = flag.String("user-service-url", getEnv("USER_SERVICE_URL", "tri://localhost:20000"), "User service URL")
)
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: "asset-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 Asset 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")
// 自动迁移数据库表
if err := autoMigrate(); err != nil {
logger.Logger.Fatal(fmt.Sprintf("Failed to migrate database: %v", err))
}
// 创建 Repository 层实例
assetRepo := repository.NewAssetRepository(database.GetDB())
mintOrderRepo := repository.NewMintOrderRepository(database.GetDB())
assetLikeRepo := repository.NewAssetLikeRepository(database.GetDB())
rankingRepo := repository.NewRankingRepository(database.GetDB())
logger.Logger.Info("Repository layer initialized")
// 创建 Dubbo 客户端
cli, err := client.NewClient(
client.WithClientURL(*userServiceURL),
)
if err != nil {
logger.Logger.Fatal(fmt.Sprintf("Failed to create Dubbo client: %v", err))
}
// 获取 User Service RPC 客户端
userServiceClient, err := pbUser.NewUserSocialService(cli)
if err != nil {
logger.Logger.Fatal(fmt.Sprintf("Failed to create User Service RPC client: %v", err))
}
userClient := assetClient.NewUserServiceClient(userServiceClient)
logger.Logger.Info("User Service RPC client initialized")
// 创建 Service 层实例
assetService := service.NewAssetService(assetRepo, mintOrderRepo, assetLikeRepo, userClient, database.GetDB())
mintService := service.NewMintService(assetRepo, mintOrderRepo, userClient, database.GetDB(), config.GlobalAssetConfig)
assetLikeService := service.NewAssetLikeService(assetRepo, assetLikeRepo, database.GetDB())
rankingService := service.NewRankingService(rankingRepo, userClient)
logger.Logger.Info("Service layer initialized")
// 创建 Provider 层实例
assetProvider := provider.NewAssetProvider(assetService, mintService, assetLikeService)
rankingProvider := provider.NewRankingProvider(rankingService)
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 := pbAsset.RegisterAssetServiceHandler(srv, assetProvider); err != nil {
logger.Logger.Fatal(fmt.Sprintf("Failed to register Asset Service: %v", err))
}
// 注册 Ranking Service
if err := pbRanking.RegisterRankingServiceHandler(srv, rankingProvider); err != nil {
logger.Logger.Fatal(fmt.Sprintf("Failed to register Ranking Service: %v", err))
}
// 启动服务
if err := srv.Serve(); err != nil {
logger.Logger.Fatal(fmt.Sprintf("Failed to start Asset Service: %v", err))
}
logger.Logger.Info(fmt.Sprintf("Asset 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 Asset Service...")
}
// autoMigrate 自动迁移数据库表
func autoMigrate() error {
db := database.GetDB()
if db == nil {
return fmt.Errorf("database is not initialized")
}
// 按顺序迁移资产相关表
tables := []interface{}{
&models.Asset{},
&models.MintOrder{},
&models.AssetLike{},
}
for _, table := range tables {
if err := db.AutoMigrate(table); err != nil {
return fmt.Errorf("failed to migrate table: %w", err)
}
}
logger.Logger.Info("Database migration completed successfully")
return nil
}