Files

201 lines
5.1 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 (
"errors"
"flag"
"fmt"
"log"
"net/http"
"time"
"goalfymax-admin/internal/api/routes"
"goalfymax-admin/internal/config"
"goalfymax-admin/internal/jobs"
"goalfymax-admin/internal/models"
"goalfymax-admin/internal/notifier"
"goalfymax-admin/internal/services"
"goalfymax-admin/internal/storage"
"goalfymax-admin/pkg/middleware"
"goalfymax-admin/pkg/redis"
"goalfymax-admin/pkg/utils"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
func main() {
// 解析命令行参数
var configPath string
flag.StringVar(&configPath, "config", "", "配置文件路径(可选,优先级最高)")
var env string
flag.StringVar(&env, "env", "dev", "运行环境(dev/test/prod等)")
flag.Parse()
// 加载配置
// 根据env推导配置文件路径(当未显式指定 --config 时)
if configPath == "" {
// 优先匹配 etc/config-<env>.yaml不存在则回退 etc/config.yaml
guessed := fmt.Sprintf("etc/config-%s.yaml", env)
if err := config.LoadConfig(guessed); err != nil {
// 回退默认
if err2 := config.LoadConfig("etc/config.yaml"); err2 != nil {
log.Fatalf("加载配置失败: %v (fallback error: %v)", err, err2)
}
}
} else if err := config.LoadConfig(configPath); err != nil {
log.Fatalf("加载配置失败: %v", err)
}
cfg := config.GetConfig()
// 初始化日志
logger, err := utils.NewLogger(cfg.Log.Level, cfg.Log.Format, cfg.Log.Output)
if err != nil {
log.Fatalf("初始化日志失败: %v", err)
}
logger.Info("应用启动中...")
// 初始化通知服务
notifier.Init(cfg.Alert, env, logger)
// 初始化数据库
if err := storage.InitDatabase(logger); err != nil {
logger.Fatal("初始化数据库失败", zap.Error(err))
}
// 自动迁移数据库
if err := storage.AutoMigrate(); err != nil {
logger.Fatal("数据库迁移失败", zap.Error(err))
}
// 初始化PostgreSQL用于 MCP 配置)
if err := storage.InitPostgres(logger); err != nil {
logger.Warn("PostgreSQL初始化失败MCP配置将不可用", zap.Error(err))
} else {
logger.Info("PostgreSQL初始化完成")
}
logger.Info("数据库初始化完成")
// 初始化Redis客户端
redisClient, err := redis.NewClient(cfg.Redis)
if err != nil {
logger.Warn("Redis初始化失败余额查询功能将不可用", zap.Error(err))
redisClient = nil // 设置为nil服务会优雅处理
} else {
logger.Info("Redis初始化完成")
defer redisClient.Close()
}
// 创建服务实例
ssoAdminService := services.NewSSOAdminService()
userService := services.NewUserService(
storage.NewUserStorage(),
storage.NewRBACStorage(),
storage.NewGoalfyMaxUserStorage(),
utils.NewJWTManager("your-jwt-secret"),
logger,
ssoAdminService,
)
roleService := services.NewRoleService(
storage.NewRoleStorage(),
logger,
)
pageService := services.NewPageService(
storage.NewPageStorage(),
logger,
)
// 创建网关客户端和配额服务
gatewayClient := services.NewGatewayClient(
cfg.Gateway.BaseURL,
time.Duration(cfg.Gateway.Timeout)*time.Second,
logger,
)
quotaService := services.NewQuotaService(gatewayClient, logger)
// 创建SSO客户端和SSO服务
ssoConfig := &models.SSOConfig{
SSOServerURL: cfg.SSO.SSOServerURL,
ClientID: cfg.SSO.ClientID,
ClientSecret: cfg.SSO.ClientSecret,
RedirectURI: cfg.SSO.RedirectURI,
Scope: cfg.SSO.Scope,
ResourceAud: cfg.SSO.ResourceAud,
Timeout: cfg.SSO.Timeout,
}
// 创建RBAC服务
rbacService := services.NewRBACService(
storage.NewRBACStorage(),
storage.NewUserStorage(),
logger,
)
ssoClient := middleware.NewSSOClient(ssoConfig, logger)
ssoService := services.NewSSOService(
ssoClient,
storage.NewPKCEStateStorage(),
storage.NewLoginInfoStorage(),
rbacService,
logger,
)
// 创建用户等级配置服务
userLevelConfigService := services.NewUserLevelConfigService(
storage.NewUserLevelConfigStorage(),
logger,
)
// 创建系统配置服务
systemConfigService := services.NewSystemConfigService(
storage.NewSystemConfigStorage(),
logger,
)
// 设置路由
router := routes.SetupRoutes(
userService,
roleService,
pageService,
quotaService,
ssoService,
rbacService,
userLevelConfigService,
systemConfigService,
redisClient,
logger,
cfg,
)
// 启动定时任务
jobs.StartMcpUsageBalanceScheduler(cfg.Jobs.McpUsageBalance, logger)
jobs.StartModelTokenBalanceScheduler(cfg.Jobs.ModelTokenBalance, logger)
// 启动HTTP服务器
startHTTPServer(cfg, router, logger)
}
// startHTTPServer 启动HTTP服务器
func startHTTPServer(cfg *config.Config, router *gin.Engine, logger *utils.Logger) {
// 构建服务器地址
addr := fmt.Sprintf("%s:%d", cfg.Server.Addr, cfg.Server.Port)
// 启动服务器
server := &http.Server{
Addr: addr,
Handler: router,
ReadTimeout: 15 * time.Second,
WriteTimeout: 15 * time.Second,
IdleTimeout: 60 * time.Second,
}
logger.Info("HTTP服务器启动", zap.String("addr", addr))
logger.Info("应用启动完成")
// 启动服务器
if err := server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
logger.Fatal("HTTP服务器启动失败", zap.Error(err))
}
}