3 Commits

Author SHA1 Message Date
f0a699029a improve server startup 2025-03-07 17:19:42 -05:00
e178956eef improve grpc lifecycle 2025-03-07 17:04:46 -05:00
c5da5f7887 improve grpc lifecycle 2025-03-07 16:45:50 -05:00
5 changed files with 60 additions and 11 deletions

View File

@ -2,6 +2,7 @@ package app
import (
"errors"
"sync"
"github.com/rs/zerolog"
"go.opentelemetry.io/otel/attribute"
@ -26,30 +27,52 @@ func (a *App) MustRun() {
a.appDone = make(chan any)
a.HTTP.HTTPDone = make(chan any)
if !a.cfg.HTTPEnabled() && !a.cfg.GRPCEnabled() {
panic(errors.New("neither http nor grpc enabled, nothing to do"))
}
if len(a.HTTP.Funcs) < 1 {
a.l.Warn().Msg("no http funcs provided, only serving health and metrics")
}
// Start OTEL
// Registers a NO-OP provider if not enabled
a.initOTEL()
ctx, initSpan := a.tracer.Start(a.AppContext, "init")
defer initSpan.End()
var serverWG sync.WaitGroup
// Start HTTP (does not block)
if err := a.initHTTP(ctx); err != nil {
initSpan.RecordError(err)
initSpan.SetStatus(codes.Error, err.Error())
if a.cfg.HTTPEnabled() {
serverWG.Add(1)
go func() {
defer serverWG.Done()
if err := a.initHTTP(ctx); err != nil {
initSpan.RecordError(err)
initSpan.SetStatus(codes.Error, err.Error())
}
initSpan.AddEvent("http server started")
initSpan.SetAttributes(attribute.Int("http.handlers", len(a.HTTP.Funcs)))
}()
}
initSpan.AddEvent("http server started")
initSpan.SetAttributes(attribute.Int("http.handlers", len(a.HTTP.Funcs)))
// Start GRPC (does not block)
if err := a.initGRPC(ctx); err != nil {
initSpan.RecordError(err)
initSpan.SetStatus(codes.Error, err.Error())
if a.cfg.GRPCEnabled() {
serverWG.Add(1)
go func() {
defer serverWG.Done()
if err := a.initGRPC(ctx); err != nil {
initSpan.RecordError(err)
initSpan.SetStatus(codes.Error, err.Error())
}
initSpan.AddEvent("grpc server started")
initSpan.SetAttributes(attribute.Int("grpc.services", len(a.GRPC.Services)))
}()
}
initSpan.AddEvent("grpc server started")
initSpan.SetAttributes(attribute.Int("grpc.services", len(a.GRPC.Services)))
serverWG.Wait()
// Monitor app lifecycle
go a.run()

View File

@ -22,3 +22,24 @@ type AppConfig struct {
OTEL *OTELConfig `yaml:"otel,omitempty"`
GRPC *GRPCConfig `yaml:"grpc,omitempty"`
}
func (ac *AppConfig) HTTPEnabled() bool {
if ac.HTTP != nil && ac.HTTP.Enabled {
return true
}
return false
}
func (ac *AppConfig) GRPCEnabled() bool {
if ac.GRPC != nil && ac.GRPC.Enabled {
return true
}
return false
}
func (ac *AppConfig) OTELEnabled() bool {
if ac.OTEL != nil && ac.OTEL.Enabled {
return true
}
return false
}

View File

@ -44,7 +44,7 @@ func Init(ctx context.Context) (context.Context, func(context.Context) error) {
cfg := config.MustFromCtx(ctx)
// Nothing to do here if not enabled
if !cfg.OTEL.Enabled {
if !cfg.OTELEnabled() {
opentelemetry.SetMeterProvider(noopMetric.NewMeterProvider())
opentelemetry.SetTracerProvider(noop.NewTracerProvider())
// Won't function with noop providers

View File

@ -62,6 +62,8 @@ func InitGRPCServer(ctx context.Context, opts *opts.GRPCOpts) (
return nil, nil, err
}
appGRPC.logger.Debug().Msg("GRPC Server Started")
span.SetStatus(codes.Ok, "")
return appGRPC.shutdownFunc, appGRPC.doneChan, nil
}

View File

@ -56,8 +56,11 @@ func (a *appGRPCServer) getShutdownFunc() func(context.Context) error {
select {
case <-stoppedChan:
a.logger.Warn().Msg("GRPC server shut down gracefully")
return nil
case <-ctx.Done():
a.logger.Warn().Msg("GRPC server shut down hard")
a.server.Stop()
return ctx.Err()
}
}