2026-05-12 19:34:47 +08:00

98 lines
2.7 KiB
Go

package app
import (
"context"
"errors"
"net"
"sync"
"time"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
healthgrpc "google.golang.org/grpc/health/grpc_health_v1"
gamev1 "hyapp.local/api/proto/game/v1"
"hyapp/pkg/grpchealth"
"hyapp/pkg/logx"
"hyapp/services/game-service/internal/client"
"hyapp/services/game-service/internal/config"
gameservice "hyapp/services/game-service/internal/service/game"
mysqlstorage "hyapp/services/game-service/internal/storage/mysql"
grpcserver "hyapp/services/game-service/internal/transport/grpc"
)
// App 装配 game-service gRPC 入口和持久化依赖。
type App struct {
server *grpc.Server
listener net.Listener
health *grpchealth.ServingChecker
repo *mysqlstorage.Repository
walletConn *grpc.ClientConn
userConn *grpc.ClientConn
closeOnce sync.Once
}
func New(cfg config.Config) (*App, error) {
startupCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
repo, err := mysqlstorage.Open(startupCtx, cfg.MySQLDSN)
if err != nil {
return nil, err
}
walletConn, err := grpc.Dial(cfg.WalletServiceAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
_ = repo.Close()
return nil, err
}
userConn, err := grpc.Dial(cfg.UserServiceAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
_ = walletConn.Close()
_ = repo.Close()
return nil, err
}
listener, err := net.Listen("tcp", cfg.GRPCAddr)
if err != nil {
_ = userConn.Close()
_ = walletConn.Close()
_ = repo.Close()
return nil, err
}
server := grpc.NewServer(grpc.UnaryInterceptor(logx.UnaryServerInterceptor("game-service")))
svc := gameservice.New(gameservice.Config{LaunchSessionTTL: cfg.LaunchSessionTTL}, repo, client.NewWalletClient(walletConn), client.NewUserClient(userConn))
transport := grpcserver.NewServer(svc)
gamev1.RegisterGameAppServiceServer(server, transport)
gamev1.RegisterGameCallbackServiceServer(server, transport)
gamev1.RegisterGameAdminServiceServer(server, transport)
health := grpchealth.NewServingChecker("game-service")
healthgrpc.RegisterHealthServer(server, grpchealth.NewServer(health))
return &App{server: server, listener: listener, health: health, repo: repo, walletConn: walletConn, userConn: userConn}, nil
}
func (a *App) Run() error {
a.health.MarkServing()
err := a.server.Serve(a.listener)
a.health.MarkStopped()
if errors.Is(err, grpc.ErrServerStopped) {
return nil
}
return err
}
func (a *App) Close() {
a.closeOnce.Do(func() {
a.health.MarkDraining()
a.server.GracefulStop()
if a.walletConn != nil {
_ = a.walletConn.Close()
}
if a.userConn != nil {
_ = a.userConn.Close()
}
if a.repo != nil {
_ = a.repo.Close()
}
})
}