topfans/backend/services/userService/main.go

211 lines
5.5 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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/health"
"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")
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: "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 healthHandler != nil {
healthHandler.Stop()
}
// 关闭数据库连接
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 {
// 启动健康检查 HTTP 服务器
healthPort := *port + 1000 // e.g., 20000 -> 21000
healthHandler = health.NewHandler("user-service", healthPort)
healthHandler.Start()
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
}