2026-04-25 13:21:39 +08:00

113 lines
2.6 KiB
Go

package app
import (
"errors"
"net"
"net/http"
"os"
"sync"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"hyapp/services/gateway-service/internal/auth"
"hyapp/services/gateway-service/internal/client"
"hyapp/services/gateway-service/internal/config"
"hyapp/services/gateway-service/internal/healthcheck"
httptransport "hyapp/services/gateway-service/internal/transport/http"
)
// App 装配 gateway 的 HTTP 入口。
type App struct {
server *http.Server
listener net.Listener
roomConn *grpc.ClientConn
userConn *grpc.ClientConn
health *healthcheck.State
closeOnce sync.Once
}
// New 初始化 gateway 应用。
func New(cfg config.Config) (*App, error) {
roomConn, err := grpc.Dial(cfg.RoomServiceAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
return nil, err
}
userConn, err := grpc.Dial(cfg.UserServiceAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
_ = roomConn.Close()
return nil, err
}
var roomClient client.RoomClient = client.NewGRPCRoomClient(roomConn)
var userClient client.UserAuthClient = client.NewGRPCUserAuthClient(userConn)
var userIdentityClient client.UserIdentityClient = client.NewGRPCUserIdentityClient(userConn)
handler := httptransport.NewHandlerWithClients(roomClient, userClient, userIdentityClient)
verifier := auth.NewVerifier(cfg.JWTSecret)
healthState := healthcheck.NewState(nodeID(), cfg.JWTSecret, roomConn)
mux := http.NewServeMux()
healthHandler := healthcheck.NewHTTPHandler(healthState)
mux.HandleFunc("/healthz/live", healthHandler.Live)
mux.HandleFunc("/healthz/ready", healthHandler.Ready)
mux.Handle("/", handler.Routes(verifier))
listener, err := net.Listen("tcp", cfg.HTTPAddr)
if err != nil {
_ = roomConn.Close()
_ = userConn.Close()
return nil, err
}
server := &http.Server{
Handler: mux,
}
return &App{
server: server,
listener: listener,
roomConn: roomConn,
userConn: userConn,
health: healthState,
}, nil
}
// Run 启动 HTTP 服务。
func (a *App) Run() error {
a.health.MarkHTTPServing()
err := a.server.Serve(a.listener)
a.health.MarkHTTPStopped()
if errors.Is(err, http.ErrServerClosed) {
return nil
}
return err
}
// Close 关闭 HTTP 服务。
func (a *App) Close() error {
var err error
a.closeOnce.Do(func() {
a.health.MarkDraining()
if a.roomConn != nil {
_ = a.roomConn.Close()
}
if a.userConn != nil {
_ = a.userConn.Close()
}
err = a.server.Close()
})
return err
}
func nodeID() string {
hostname, err := os.Hostname()
if err != nil || hostname == "" {
return "gateway-service"
}
return hostname
}