87 lines
2.3 KiB
Go
87 lines
2.3 KiB
Go
package app
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"log/slog"
|
|
|
|
gatewaypb "chatappgateway/api/proto"
|
|
"chatappgateway/internal/config"
|
|
"chatappgateway/internal/integration/paygrpc"
|
|
"chatappgateway/internal/integration/usergrpc"
|
|
"chatappgateway/internal/service/auth"
|
|
"chatappgateway/internal/service/pay"
|
|
httpserver "chatappgateway/internal/transport/http"
|
|
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/credentials/insecure"
|
|
)
|
|
|
|
// Application 组合网关运行所需的全部组件。
|
|
type Application struct {
|
|
server *httpserver.Server
|
|
closers []io.Closer
|
|
}
|
|
|
|
// New 构造完整应用,包括 gRPC 连接、业务服务和 HTTP 服务。
|
|
func New(ctx context.Context, cfg config.Config, logger *slog.Logger) (*Application, error) {
|
|
userConn, err := dialGRPC(ctx, cfg.GRPC.User.Target)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("dial ChatAppUser: %w", err)
|
|
}
|
|
|
|
payConn, err := dialGRPC(ctx, cfg.GRPC.Pay.Target)
|
|
if err != nil {
|
|
_ = userConn.Close()
|
|
return nil, fmt.Errorf("dial ChatAppPay: %w", err)
|
|
}
|
|
|
|
userClient := usergrpc.New(gatewaypb.NewChatAppUserClient(userConn), cfg.GRPC.User.Timeout)
|
|
payClient := paygrpc.New(gatewaypb.NewChatAppPayClient(payConn), cfg.GRPC.Pay.Timeout)
|
|
|
|
authService := auth.New(userClient)
|
|
payService := pay.New(payClient)
|
|
readinessChecker := newReadinessGroup(
|
|
namedChecker{
|
|
name: "ChatAppUser",
|
|
check: grpcConnectionReady(userConn),
|
|
},
|
|
namedChecker{
|
|
name: "ChatAppPay",
|
|
check: grpcConnectionReady(payConn),
|
|
},
|
|
)
|
|
server := httpserver.New(cfg.App.Name, cfg.App.HTTPAddr, cfg.App.ShutdownTimeout, logger, authService, payService, readinessChecker)
|
|
|
|
return &Application{
|
|
server: server,
|
|
closers: []io.Closer{userConn, payConn},
|
|
}, nil
|
|
}
|
|
|
|
// Run 启动 HTTP 服务。
|
|
func (a *Application) Run(ctx context.Context) error {
|
|
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
|
|
}
|
|
|
|
func dialGRPC(ctx context.Context, target string) (*grpc.ClientConn, error) {
|
|
// 网关只做自身健康检查,因此这里使用懒连接,避免下游暂时不可用时阻塞启动。
|
|
return grpc.DialContext(
|
|
ctx,
|
|
target,
|
|
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
|
)
|
|
}
|