2026-04-07 12:30:08 +08:00

82 lines
2.2 KiB
Go

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
}