package grpc import ( "context" "net" "net/url" "git.nobla.cn/golang/aeus/pkg/logger" netutil "git.nobla.cn/golang/aeus/pkg/net" "google.golang.org/grpc" "google.golang.org/grpc/reflection" ) type Server struct { ctx context.Context opts *options uri *url.URL serve *grpc.Server listener net.Listener } func (s *Server) createListener() (err error) { if s.listener == nil { if s.listener, err = net.Listen(s.opts.network, s.opts.address); err != nil { return } s.uri.Host = netutil.TrulyAddr(s.opts.address, s.listener) } return } func (s *Server) Start(ctx context.Context) (err error) { s.ctx = ctx if err = s.createListener(); err != nil { return } s.opts.logger.Info(ctx, "grpc server listen on: %s", s.uri.Host) reflection.Register(s.serve) s.serve.Serve(s.listener) return } func (s *Server) Endpoint(ctx context.Context) (string, error) { if err := s.createListener(); err != nil { return "", err } return s.uri.String(), nil } func (s *Server) RegisterService(sd *grpc.ServiceDesc, ss any) { s.serve.RegisterService(sd, ss) } func (s *Server) Stop(ctx context.Context) (err error) { s.serve.GracefulStop() s.opts.logger.Info(s.ctx, "grpc server stopped") return } func New(cbs ...Option) *Server { svr := &Server{ opts: &options{ network: "tcp", logger: logger.Default(), address: ":0", }, uri: &url.URL{ Scheme: "grpc", }, } for _, cb := range cbs { cb(svr.opts) } gopts := []grpc.ServerOption{} svr.serve = grpc.NewServer(gopts...) return svr }