Files
tokens-reef/backend/cmd/server/wire.go

333 lines
8.0 KiB
Go
Raw 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.
//go:build wireinject
// +build wireinject
package main
import (
"context"
"log"
"net/http"
"sync"
"time"
"github.com/Wei-Shaw/sub2api/ent"
"github.com/Wei-Shaw/sub2api/internal/config"
"github.com/Wei-Shaw/sub2api/internal/handler"
"github.com/Wei-Shaw/sub2api/internal/payment"
"github.com/Wei-Shaw/sub2api/internal/repository"
"github.com/Wei-Shaw/sub2api/internal/server"
"github.com/Wei-Shaw/sub2api/internal/server/middleware"
"github.com/Wei-Shaw/sub2api/internal/service"
"github.com/Wei-Shaw/sub2api/internal/setup"
"github.com/google/wire"
"github.com/redis/go-redis/v9"
)
type Application struct {
Server *http.Server
Cleanup func()
Bootstrap func() error
}
func initializeApplication(buildInfo handler.BuildInfo) (*Application, error) {
wire.Build(
// Infrastructure layer ProviderSets
config.ProviderSet,
// Business layer ProviderSets
repository.ProviderSet,
service.ProviderSet,
middleware.ProviderSet,
handler.ProviderSet,
// Server layer ProviderSet
server.ProviderSet,
// Payment providers
payment.ProviderSet,
// Privacy client factory for OpenAI training opt-out
providePrivacyClientFactory,
// BuildInfo provider
provideServiceBuildInfo,
// Cleanup function provider
provideCleanup,
provideBootstrap,
// Application struct
wire.Struct(new(Application), "Server", "Cleanup", "Bootstrap"),
)
return nil, nil
}
func providePrivacyClientFactory() service.PrivacyClientFactory {
return repository.CreatePrivacyReqClient
}
func provideServiceBuildInfo(buildInfo handler.BuildInfo) service.BuildInfo {
return service.BuildInfo{
Version: buildInfo.Version,
BuildType: buildInfo.BuildType,
}
}
func provideBootstrap(settingService *service.SettingService, userRepo service.UserRepository, cfg *config.Config) func() error {
return newBootstrapFunc(settingService.InitializeDefaultSettings, setup.RecoverAutoSetupAdmin, userRepo, cfg)
}
func newBootstrapFunc(
initDefaults func(context.Context) error,
recoverAdmin func(context.Context, service.UserRepository, *config.Config) error,
userRepo service.UserRepository,
cfg *config.Config,
) func() error {
return func() error {
ctx := context.Background()
if err := initDefaults(ctx); err != nil {
return err
}
if err := recoverAdmin(ctx, userRepo, cfg); err != nil {
return err
}
return nil
}
}
func provideCleanup(
entClient *ent.Client,
rdb *redis.Client,
opsMetricsCollector *service.OpsMetricsCollector,
opsAggregation *service.OpsAggregationService,
opsAlertEvaluator *service.OpsAlertEvaluatorService,
opsCleanup *service.OpsCleanupService,
opsScheduledReport *service.OpsScheduledReportService,
opsSystemLogSink *service.OpsSystemLogSink,
soraMediaCleanup *service.SoraMediaCleanupService, // 从本地版本合并
schedulerSnapshot *service.SchedulerSnapshotService,
tokenRefresh *service.TokenRefreshService,
accountExpiry *service.AccountExpiryService,
subscriptionExpiry *service.SubscriptionExpiryService,
usageCleanup *service.UsageCleanupService,
idempotencyCleanup *service.IdempotencyCleanupService,
pricing *service.PricingService,
emailQueue *service.EmailQueueService,
billingCache *service.BillingCacheService,
usageRecordWorkerPool *service.UsageRecordWorkerPool,
subscriptionService *service.SubscriptionService,
oauth *service.OAuthService,
openaiOAuth *service.OpenAIOAuthService,
geminiOAuth *service.GeminiOAuthService,
antigravityOAuth *service.AntigravityOAuthService,
openAIGateway *service.OpenAIGatewayService,
scheduledTestRunner *service.ScheduledTestRunnerService,
backupSvc *service.BackupService,
paymentOrderExpiry *service.PaymentOrderExpiryService,
) func() {
return func() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
type cleanupStep struct {
name string
fn func() error
}
// 应用层清理步骤可并行执行基础设施资源Redis/Ent最后按顺序关闭。
parallelSteps := []cleanupStep{
{"OpsScheduledReportService", func() error {
if opsScheduledReport != nil {
opsScheduledReport.Stop()
}
return nil
}},
{"OpsCleanupService", func() error {
if opsCleanup != nil {
opsCleanup.Stop()
}
return nil
}},
{"OpsSystemLogSink", func() error {
if opsSystemLogSink != nil {
opsSystemLogSink.Stop()
}
return nil
}},
{"OpsAlertEvaluatorService", func() error {
if opsAlertEvaluator != nil {
opsAlertEvaluator.Stop()
}
return nil
}},
{"OpsAggregationService", func() error {
if opsAggregation != nil {
opsAggregation.Stop()
}
return nil
}},
{"OpsMetricsCollector", func() error {
if opsMetricsCollector != nil {
opsMetricsCollector.Stop()
}
return nil
}},
{"SchedulerSnapshotService", func() error {
if schedulerSnapshot != nil {
schedulerSnapshot.Stop()
}
return nil
}},
{"UsageCleanupService", func() error {
if usageCleanup != nil {
usageCleanup.Stop()
}
return nil
}},
{"IdempotencyCleanupService", func() error {
if idempotencyCleanup != nil {
idempotencyCleanup.Stop()
}
return nil
}},
{"TokenRefreshService", func() error {
tokenRefresh.Stop()
return nil
}},
{"AccountExpiryService", func() error {
accountExpiry.Stop()
return nil
}},
{"SubscriptionExpiryService", func() error {
subscriptionExpiry.Stop()
return nil
}},
{"SubscriptionService", func() error {
if subscriptionService != nil {
subscriptionService.Stop()
}
return nil
}},
{"PricingService", func() error {
pricing.Stop()
return nil
}},
{"EmailQueueService", func() error {
emailQueue.Stop()
return nil
}},
{"BillingCacheService", func() error {
billingCache.Stop()
return nil
}},
{"UsageRecordWorkerPool", func() error {
if usageRecordWorkerPool != nil {
usageRecordWorkerPool.Stop()
}
return nil
}},
{"OAuthService", func() error {
oauth.Stop()
return nil
}},
{"OpenAIOAuthService", func() error {
openaiOAuth.Stop()
return nil
}},
{"GeminiOAuthService", func() error {
geminiOAuth.Stop()
return nil
}},
{"AntigravityOAuthService", func() error {
antigravityOAuth.Stop()
return nil
}},
{"OpenAIWSPool", func() error {
if openAIGateway != nil {
openAIGateway.CloseOpenAIWSPool()
}
return nil
}},
{"ScheduledTestRunnerService", func() error {
if scheduledTestRunner != nil {
scheduledTestRunner.Stop()
}
return nil
}},
{"BackupService", func() error {
if backupSvc != nil {
backupSvc.Stop()
}
return nil
}},
{"PaymentOrderExpiryService", func() error {
if paymentOrderExpiry != nil {
paymentOrderExpiry.Stop()
}
return nil
}},
{"SoraMediaCleanupService", func() error {
if soraMediaCleanup != nil {
soraMediaCleanup.Stop()
}
return nil
}},
}
infraSteps := []cleanupStep{
{"Redis", func() error {
if rdb == nil {
return nil
}
return rdb.Close()
}},
{"Ent", func() error {
if entClient == nil {
return nil
}
return entClient.Close()
}},
}
runParallel := func(steps []cleanupStep) {
var wg sync.WaitGroup
for i := range steps {
step := steps[i]
wg.Add(1)
go func() {
defer wg.Done()
if err := step.fn(); err != nil {
log.Printf("[Cleanup] %s failed: %v", step.name, err)
return
}
log.Printf("[Cleanup] %s succeeded", step.name)
}()
}
wg.Wait()
}
runSequential := func(steps []cleanupStep) {
for i := range steps {
step := steps[i]
if err := step.fn(); err != nil {
log.Printf("[Cleanup] %s failed: %v", step.name, err)
continue
}
log.Printf("[Cleanup] %s succeeded", step.name)
}
}
runParallel(parallelSteps)
runSequential(infraSteps)
// Check if context timed out
select {
case <-ctx.Done():
log.Printf("[Cleanup] Warning: cleanup timed out after 10 seconds")
default:
log.Printf("[Cleanup] All cleanup steps completed")
}
}
}