148 lines
4.1 KiB
Go
148 lines
4.1 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/grpcshutdown"
|
|
"hyapp/pkg/healthhttp"
|
|
"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
|
|
healthHTTP *healthhttp.Server
|
|
repo *mysqlstorage.Repository
|
|
walletConn *grpc.ClientConn
|
|
userConn *grpc.ClientConn
|
|
activityConn *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
|
|
}
|
|
activityConn, err := grpc.Dial(cfg.ActivityServiceAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
|
if err != nil {
|
|
_ = userConn.Close()
|
|
_ = walletConn.Close()
|
|
_ = repo.Close()
|
|
return nil, err
|
|
}
|
|
listener, err := net.Listen("tcp", cfg.GRPCAddr)
|
|
if err != nil {
|
|
_ = activityConn.Close()
|
|
_ = 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), client.NewActivityGrowthClient(activityConn))
|
|
transport := grpcserver.NewServer(svc)
|
|
gamev1.RegisterGameAppServiceServer(server, transport)
|
|
gamev1.RegisterGameCallbackServiceServer(server, transport)
|
|
gamev1.RegisterGameAdminServiceServer(server, transport)
|
|
gamev1.RegisterGameCronServiceServer(server, transport)
|
|
health := grpchealth.NewServingChecker("game-service", grpchealth.Dependency{
|
|
Name: "mysql",
|
|
Check: repo.Ping,
|
|
})
|
|
healthgrpc.RegisterHealthServer(server, grpchealth.NewServer(health))
|
|
healthHTTP, err := healthhttp.New(cfg.HealthHTTPAddr, cfg.NodeID, health)
|
|
if err != nil {
|
|
_ = listener.Close()
|
|
_ = activityConn.Close()
|
|
_ = userConn.Close()
|
|
_ = walletConn.Close()
|
|
_ = repo.Close()
|
|
return nil, err
|
|
}
|
|
|
|
return &App{server: server, listener: listener, health: health, healthHTTP: healthHTTP, repo: repo, walletConn: walletConn, userConn: userConn, activityConn: activityConn}, nil
|
|
}
|
|
|
|
func (a *App) Run() error {
|
|
a.runHealthHTTP()
|
|
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()
|
|
grpcshutdown.GracefulStop(a.server, 15*time.Second)
|
|
a.closeHealthHTTP()
|
|
if a.walletConn != nil {
|
|
_ = a.walletConn.Close()
|
|
}
|
|
if a.userConn != nil {
|
|
_ = a.userConn.Close()
|
|
}
|
|
if a.activityConn != nil {
|
|
_ = a.activityConn.Close()
|
|
}
|
|
if a.repo != nil {
|
|
_ = a.repo.Close()
|
|
}
|
|
})
|
|
}
|
|
|
|
func (a *App) runHealthHTTP() {
|
|
if a.healthHTTP == nil {
|
|
return
|
|
}
|
|
go func() {
|
|
if err := a.healthHTTP.Run(); err != nil {
|
|
logx.Error(context.Background(), "health_http_run_failed", err)
|
|
}
|
|
}()
|
|
}
|
|
|
|
func (a *App) closeHealthHTTP() {
|
|
if a.healthHTTP == nil {
|
|
return
|
|
}
|
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
|
defer cancel()
|
|
_ = a.healthHTTP.Close(ctx)
|
|
}
|