package app import ( "context" "fmt" "io" "log/slog" "chatappgateway/internal/config" "chatappgateway/internal/integration/paygrpc" "chatappgateway/internal/integration/upstream" "chatappgateway/internal/integration/usergrpc" "chatappgateway/internal/lifecycle" "chatappgateway/internal/service/auth" "chatappgateway/internal/service/pay" httpserver "chatappgateway/internal/transport/http" ) // Application 组合网关运行所需的全部组件。 type Application struct { server *httpserver.Server closers []io.Closer hooks lifecycle.Hooks } // New 构造完整应用,包括 gRPC 连接池、业务服务和 HTTP 服务。 func New(ctx context.Context, cfg config.Config, logger *slog.Logger) (*Application, error) { userPool, err := upstream.New(ctx, "ChatAppUser", cfg.GRPC.User) if err != nil { return nil, fmt.Errorf("build ChatAppUser pool: %w", err) } payPool, err := upstream.New(ctx, "ChatAppPay", cfg.GRPC.Pay) if err != nil { _ = userPool.Close() return nil, fmt.Errorf("build ChatAppPay pool: %w", err) } userClient := usergrpc.NewWithPool(userPool) payClient := paygrpc.NewWithPool(payPool) authService := auth.New(userClient) payService := pay.New(payClient) registryHooks := lifecycle.NewRegistryHooks(cfg.Registry, logger.With("component", "registry_hooks")) readinessChecker := newReadinessGroup( namedChecker{ name: "ChatAppUser", check: userPool.Ready, }, namedChecker{ name: "ChatAppPay", check: payPool.Ready, }, ) server := httpserver.New(cfg.App.Name, cfg.App.HTTPAddr, cfg.App.ShutdownTimeout, logger, authService, payService, readinessChecker, registryHooks) return &Application{ server: server, closers: []io.Closer{userPool, payPool}, hooks: registryHooks, }, nil } // Run 启动 HTTP 服务。 func (a *Application) Run(ctx context.Context) error { if err := a.hooks.OnRegister(ctx); err != nil { return fmt.Errorf("register lifecycle hook: %w", err) } return a.server.Run(ctx) } // Close 关闭底层 gRPC 连接。 func (a *Application) Close() error { var firstErr error for _, closer := range a.closers { if err := closer.Close(); err != nil && firstErr == nil { firstErr = err } } return firstErr }