This commit is contained in:
XOF
2025-11-20 12:24:05 +08:00
commit f28bdc751f
164 changed files with 64248 additions and 0 deletions

142
internal/app/app.go Normal file
View File

@@ -0,0 +1,142 @@
// Filename: internal/app/app.go
package app
import (
"context"
"fmt"
"gemini-balancer/internal/config"
"gemini-balancer/internal/crypto"
"gemini-balancer/internal/db/migrations"
"gemini-balancer/internal/db/seeder"
"gemini-balancer/internal/scheduler"
"gemini-balancer/internal/service"
"gemini-balancer/internal/settings"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/gin-gonic/gin"
"github.com/sirupsen/logrus"
"gorm.io/gorm"
)
// App
type App struct {
Config *config.Config
Router *gin.Engine
DB *gorm.DB
Logger *logrus.Logger
CryptoService *crypto.Service
// 拥有独立生命周期的后台服务
ResourceService *service.ResourceService
APIKeyService *service.APIKeyService
DBLogWriter *service.DBLogWriterService
AnalyticsService *service.AnalyticsService
HealthCheckService *service.HealthCheckService
SettingsManager *settings.SettingsManager
GroupManager *service.GroupManager
TokenManager *service.TokenManager
Scheduler *scheduler.Scheduler
}
// NewApp
func NewApp(
cfg *config.Config,
router *gin.Engine,
db *gorm.DB,
logger *logrus.Logger,
cryptoService *crypto.Service,
resourceService *service.ResourceService,
apiKeyService *service.APIKeyService,
dbLogWriter *service.DBLogWriterService,
analyticsService *service.AnalyticsService,
healthCheckService *service.HealthCheckService,
settingsManager *settings.SettingsManager,
groupManager *service.GroupManager,
tokenManager *service.TokenManager,
scheduler *scheduler.Scheduler,
) *App {
return &App{
Config: cfg,
Router: router,
DB: db,
Logger: logger,
CryptoService: cryptoService,
ResourceService: resourceService,
APIKeyService: apiKeyService,
DBLogWriter: dbLogWriter,
AnalyticsService: analyticsService,
HealthCheckService: healthCheckService,
SettingsManager: settingsManager,
GroupManager: groupManager,
TokenManager: tokenManager,
Scheduler: scheduler,
}
}
// Run 启动流程现在由App主动编排而非被动接受
func (a *App) Run() error {
// --- 阶段一: (数据库设置) ---
a.Logger.Info("* [SYSTEM] * Preparing: Database Setup ...")
// 步骤 1: (运行基础迁移,确保表存在)
if err := migrations.RunMigrations(a.DB, a.Logger); err != nil {
return fmt.Errorf("initial database migration failed: %w", err)
}
// 步骤 2: (运行所有版本化的数据迁移)
if err := migrations.RunVersionedMigrations(a.DB, a.Config, a.Logger); err != nil {
return fmt.Errorf("failed to run versioned migrations: %w", err)
}
// 步骤 3: (数据播种)
seeder.RunSeeder(a.DB, a.CryptoService, a.Logger)
a.Logger.Info("* [SYSTEM] * All Uitls READY. ---")
// --- 阶段二: (启动后台服务) ---
a.Logger.Info("* [SYSTEM] * Starting main: Background Services ")
a.APIKeyService.Start()
a.DBLogWriter.Start()
a.AnalyticsService.Start()
a.HealthCheckService.Start()
a.Scheduler.Start()
a.Logger.Info("* [SYSTEM] * All Background Services are RUNNING. ")
// --- 阶段三: (优雅关机) ---
defer a.Scheduler.Stop()
defer a.HealthCheckService.Stop()
defer a.AnalyticsService.Stop()
defer a.APIKeyService.Stop()
defer a.DBLogWriter.Stop()
defer a.SettingsManager.Stop()
defer a.TokenManager.Stop()
// --- 阶段四: (HTTP服务器) ---
serverAddr := fmt.Sprintf("0.0.0.0:%s", a.Config.Server.Port)
srv := &http.Server{
Addr: serverAddr,
Handler: a.Router,
}
go func() {
a.Logger.Infof("* [SYSTEM] * HTTP Server Now Listening on %s ", serverAddr)
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
a.Logger.Fatalf("HTTP server listen error: %s\n", err)
}
}()
// --- 阶段五: (处理关机信号) ---
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
a.Logger.Info("* [SYSTEM] * Shutdown signal received. Executing strategic retreat...")
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
a.Logger.Fatal("Server forced to shutdown:", err)
}
a.Logger.Info("* [SYSTEM] * All units have ceased operations. Mission complete. ")
return nil
}