199 lines
5.1 KiB
Go
199 lines
5.1 KiB
Go
package main
|
||
|
||
import (
|
||
"flag"
|
||
"fmt"
|
||
"os"
|
||
"os/signal"
|
||
"strconv"
|
||
"syscall"
|
||
|
||
_ "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"
|
||
pb "github.com/topfans/backend/pkg/proto/user"
|
||
"github.com/topfans/backend/services/userService/provider"
|
||
"github.com/topfans/backend/services/userService/repository"
|
||
"github.com/topfans/backend/services/userService/service"
|
||
)
|
||
|
||
var (
|
||
port = flag.Int("port", getEnvInt("PORT", 20000), "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")
|
||
)
|
||
|
||
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: "user-service",
|
||
Environment: env,
|
||
LogLevel: os.Getenv("LOG_LEVEL"),
|
||
}); err != nil {
|
||
panic(fmt.Sprintf("Failed to initialize logger: %v", err))
|
||
}
|
||
defer logger.Sync()
|
||
|
||
logger.Sugar.Info("Starting User Service...")
|
||
|
||
// 初始化数据库
|
||
if err := initDatabase(); err != nil {
|
||
logger.Sugar.Fatalf("Failed to initialize database: %v", err)
|
||
}
|
||
|
||
// 自动迁移数据库表
|
||
if err := autoMigrate(); err != nil {
|
||
logger.Sugar.Fatalf("Failed to migrate database: %v", err)
|
||
}
|
||
|
||
// 初始化 Dubbo-go 服务器
|
||
if err := initDubboService(); err != nil {
|
||
logger.Sugar.Fatalf("Failed to initialize Dubbo service: %v", err)
|
||
}
|
||
|
||
// 等待信号(优雅关闭)
|
||
logger.Sugar.Info("Dubbo-go service started successfully. Press Ctrl+C to exit.")
|
||
gracefulShutdown()
|
||
}
|
||
|
||
// initDatabase 初始化数据库连接
|
||
func initDatabase() error {
|
||
config := database.Config{
|
||
Host: *dbHost,
|
||
Port: *dbPort,
|
||
User: *dbUser,
|
||
Password: *dbPassword,
|
||
DBName: *dbName,
|
||
SSLMode: "disable",
|
||
TimeZone: "Asia/Shanghai",
|
||
}
|
||
|
||
return database.Init(config)
|
||
}
|
||
|
||
// autoMigrate 自动迁移数据库表
|
||
func autoMigrate() error {
|
||
db := database.GetDB()
|
||
if db == nil {
|
||
return fmt.Errorf("database is not initialized")
|
||
}
|
||
|
||
// 按顺序迁移(考虑外键依赖)
|
||
tables := []interface{}{
|
||
&models.Star{},
|
||
&models.User{},
|
||
&models.FanProfile{},
|
||
}
|
||
|
||
for _, table := range tables {
|
||
if err := db.AutoMigrate(table); err != nil {
|
||
return fmt.Errorf("failed to migrate table: %w", err)
|
||
}
|
||
}
|
||
|
||
logger.Sugar.Info("Database migration completed successfully")
|
||
return nil
|
||
}
|
||
|
||
// gracefulShutdown 优雅关闭
|
||
func gracefulShutdown() {
|
||
quit := make(chan os.Signal, 1)
|
||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
||
<-quit
|
||
|
||
logger.Sugar.Info("Shutting down server...")
|
||
|
||
// 关闭数据库连接
|
||
if err := database.Close(); err != nil {
|
||
logger.Sugar.Errorf("Error closing database: %v", err)
|
||
}
|
||
|
||
logger.Sugar.Info("Server exited")
|
||
}
|
||
|
||
// initDubboService 初始化Dubbo-go服务
|
||
func initDubboService() error {
|
||
db := database.GetDB()
|
||
if db == nil {
|
||
return fmt.Errorf("database is not initialized")
|
||
}
|
||
|
||
// 创建Repository实例
|
||
userRepo := repository.NewUserRepository()
|
||
fanProfileRepo := repository.NewFanProfileRepository()
|
||
starRepo := repository.NewStarRepository()
|
||
|
||
// 创建Service实例
|
||
authService := service.NewAuthService(userRepo, fanProfileRepo, starRepo, db)
|
||
userService := service.NewUserService(userRepo, fanProfileRepo, db)
|
||
identityService := service.NewIdentityService(fanProfileRepo, starRepo, userRepo, db)
|
||
|
||
// 创建Provider实例
|
||
authProvider := provider.NewAuthProvider(authService)
|
||
userProvider := provider.NewUserProvider(userService, identityService)
|
||
|
||
// 创建统一Provider实例(作为集成层,委托给其他Provider)
|
||
unifiedProvider := provider.NewUnifiedProvider(authProvider, userProvider)
|
||
|
||
// 使用编程式注册方式(参考 dubbo-go-samples/helloworld)
|
||
// 创建 Dubbo Server
|
||
srv, err := server.NewServer(
|
||
server.WithServerProtocol(
|
||
protocol.WithPort(20000),
|
||
protocol.WithTriple(),
|
||
),
|
||
)
|
||
if err != nil {
|
||
return fmt.Errorf("failed to create Dubbo server: %w", err)
|
||
}
|
||
|
||
// 使用 Triple 协议生成的 RegisterHandler 函数注册服务
|
||
if err := pb.RegisterUserSocialServiceHandler(srv, unifiedProvider); err != nil {
|
||
return fmt.Errorf("failed to register UserSocialService handler: %w", err)
|
||
}
|
||
|
||
logger.Sugar.Info("Dubbo-go unified provider registered successfully",
|
||
"service", "topfans.user.UserSocialService",
|
||
"port", 20000,
|
||
)
|
||
|
||
// 在后台启动 Dubbo 服务器
|
||
go func() {
|
||
if err := srv.Serve(); err != nil {
|
||
logger.Sugar.Fatalf("Failed to serve Dubbo: %v", err)
|
||
}
|
||
}()
|
||
|
||
return nil
|
||
}
|