add grpc support

This commit is contained in:
Ryan McGuire 2025-03-07 13:00:45 -05:00
parent 98fba4eac8
commit 2cf15a4837
4 changed files with 68 additions and 19 deletions

View File

@ -10,7 +10,9 @@ import (
srvhttp "gitea.libretechconsulting.com/rmcguire/go-app/pkg/srv/http"
)
func (a *App) initGRPC() {
// TODO: Implement
func (a *App) initGRPC(ctx context.Context) error {
return nil
}
func (a *App) initHTTP(ctx context.Context) error {

View File

@ -34,6 +34,7 @@ type GRPCService struct {
Name string // Descriptive name of service
Type *grpc.ServiceDesc // Type (from protoc generated code)
Service any // Implementation of GRPCService.Type (ptr)
grpcDone <-chan error
}
type AppHTTP struct {

View File

@ -23,11 +23,15 @@ type appGRPCServer struct {
serverOpts []grpc.ServerOption
logger *zerolog.Logger
server *grpc.Server
shutdownFunc func(context.Context) error
doneChan chan error
}
// TODO: This probably needs to pass back an error chan and a shutdown
// func like the http server does
func InitGRPCServer(ctx context.Context, opts *opts.GRPCOpts) error {
// Returns a shutdown func, a channel indicating done / error,
// and an up-front error if server fails to start
func InitGRPCServer(ctx context.Context, opts *opts.GRPCOpts) (
func(context.Context) error, <-chan error, error,
) {
appGRPC := &appGRPCServer{
ctx: ctx,
tracer: appotel.GetTracer(ctx, "grpc"),
@ -35,6 +39,7 @@ func InitGRPCServer(ctx context.Context, opts *opts.GRPCOpts) error {
opts: opts,
serverOpts: make([]grpc.ServerOption, 0),
logger: zerolog.Ctx(ctx),
doneChan: make(chan error),
}
ctx, span := appGRPC.tracer.Start(ctx, "appgrpc.init")
@ -44,23 +49,21 @@ func InitGRPCServer(ctx context.Context, opts *opts.GRPCOpts) error {
if err := appGRPC.prepGRPCServer(ctx); err != nil {
span.RecordError(err)
span.SetStatus(codes.Error, "failed to prepare GRPC Server")
return err
return nil, nil, err
}
// Load span with server info
span.SetAttributes(appGRPC.getServerAttributes()...)
// Run, returning a shutdown func and an error chan
// TODO: Implement shutdown func and error chan
err := appGRPC.runGRPCServer(ctx)
if err != nil {
span.RecordError(err)
span.SetStatus(codes.Error, "failed to start GRPC Server")
return err
return nil, nil, err
}
span.SetStatus(codes.Ok, "")
return nil
return appGRPC.shutdownFunc, appGRPC.doneChan, nil
}
// Convert grpc.ServiceInfo map to []attribute.KeyValue

View File

@ -2,7 +2,9 @@ package grpc
import (
"context"
"net"
"go.opentelemetry.io/otel/codes"
semconv "go.opentelemetry.io/otel/semconv/v1.27.0"
)
@ -17,5 +19,46 @@ func (a *appGRPCServer) runGRPCServer(spanCtx context.Context) error {
semconv.ServerAddress(a.opts.Listen),
)
a.shutdownFunc = a.getShutdownFunc()
l, err := net.Listen("tcp", a.opts.Listen)
if err != nil {
a.logger.Err(err).Send()
span.RecordError(err)
span.SetStatus(codes.Error, "failed to acquire net listener")
return err
}
span.AddEvent("network listener acquired")
// Launch GRPC Server
go func() {
if err := a.server.Serve(l); err != nil {
a.logger.Err(err).Send()
a.doneChan <- err
}
}()
span.AddEvent("grpc server goroutine launched")
span.SetStatus(codes.Ok, "")
return nil
}
func (a *appGRPCServer) getShutdownFunc() func(context.Context) error {
return func(ctx context.Context) error {
stoppedChan := make(chan any)
go func() {
a.server.GracefulStop()
stoppedChan <- nil
}()
select {
case <-stoppedChan:
return nil
case <-ctx.Done():
return ctx.Err()
}
}
}