Added app package and health check funcs
This commit is contained in:
		@@ -29,7 +29,7 @@ type HTTPFunc struct {
 | 
			
		||||
	HandlerFunc http.HandlerFunc
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func prepHTTPServer(ctx context.Context, handleFuncs ...HTTPFunc) *http.Server {
 | 
			
		||||
func prepHTTPServer(ctx context.Context, handleFuncs []HTTPFunc, hcFuncs ...HealthCheckFunc) *http.Server {
 | 
			
		||||
	var (
 | 
			
		||||
		cfg = config.MustFromCtx(ctx)
 | 
			
		||||
		l   = zerolog.Ctx(ctx)
 | 
			
		||||
@@ -43,8 +43,9 @@ func prepHTTPServer(ctx context.Context, handleFuncs ...HTTPFunc) *http.Server {
 | 
			
		||||
		mux.Handle(pattern, handler) // Associate pattern with handler
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	otelHandleFunc("/health", handleHealthCheckFunc(ctx))
 | 
			
		||||
	otelHandleFunc("/", handleHealthCheckFunc(ctx))
 | 
			
		||||
	healthChecks := handleHealthCheckFunc(ctx, hcFuncs...)
 | 
			
		||||
	otelHandleFunc("/health", healthChecks)
 | 
			
		||||
	otelHandleFunc("/", healthChecks)
 | 
			
		||||
 | 
			
		||||
	for _, f := range handleFuncs {
 | 
			
		||||
		otelHandleFunc(f.Path, f.HandlerFunc)
 | 
			
		||||
@@ -85,8 +86,10 @@ func prepHTTPServer(ctx context.Context, handleFuncs ...HTTPFunc) *http.Server {
 | 
			
		||||
 | 
			
		||||
// Returns a shutdown func and a done channel if the
 | 
			
		||||
// server aborts abnormally. Panics on error.
 | 
			
		||||
func MustInitHTTPServer(ctx context.Context, funcs ...HTTPFunc) (func(context.Context) error, <-chan interface{}) {
 | 
			
		||||
	shutdownFunc, doneChan, err := InitHTTPServer(ctx, funcs...)
 | 
			
		||||
func MustInitHTTPServer(ctx context.Context, funcs []HTTPFunc, hcFuncs ...HealthCheckFunc) (
 | 
			
		||||
	func(context.Context) error, <-chan interface{},
 | 
			
		||||
) {
 | 
			
		||||
	shutdownFunc, doneChan, err := InitHTTPServer(ctx, funcs, hcFuncs...)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
@@ -95,7 +98,9 @@ func MustInitHTTPServer(ctx context.Context, funcs ...HTTPFunc) (func(context.Co
 | 
			
		||||
 | 
			
		||||
// Returns a shutdown func and a done channel if the
 | 
			
		||||
// server aborts abnormally. Returns error on failure to start
 | 
			
		||||
func InitHTTPServer(ctx context.Context, funcs ...HTTPFunc) (func(context.Context) error, <-chan interface{}, error) {
 | 
			
		||||
func InitHTTPServer(ctx context.Context, funcs []HTTPFunc, hcFuncs ...HealthCheckFunc) (
 | 
			
		||||
	func(context.Context) error, <-chan interface{}, error,
 | 
			
		||||
) {
 | 
			
		||||
	l := zerolog.Ctx(ctx)
 | 
			
		||||
	doneChan := make(chan interface{})
 | 
			
		||||
 | 
			
		||||
@@ -104,7 +109,7 @@ func InitHTTPServer(ctx context.Context, funcs ...HTTPFunc) (func(context.Contex
 | 
			
		||||
	httpMeter = otel.GetMeter(ctx, "http")
 | 
			
		||||
	httpTracer = otel.GetTracer(ctx, "http")
 | 
			
		||||
 | 
			
		||||
	server = prepHTTPServer(ctx, funcs...)
 | 
			
		||||
	server = prepHTTPServer(ctx, funcs, hcFuncs...)
 | 
			
		||||
 | 
			
		||||
	go func() {
 | 
			
		||||
		l.Debug().Msg("HTTP Server Started")
 | 
			
		||||
 
 | 
			
		||||
@@ -7,39 +7,47 @@ import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/rs/zerolog"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func handleHealthCheckFunc(_ context.Context) func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
type HealthCheckFunc func(context.Context) error
 | 
			
		||||
 | 
			
		||||
func handleHealthCheckFunc(ctx context.Context, hcFuncs ...HealthCheckFunc) func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
	// Return http handle func
 | 
			
		||||
	return func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
		var err error
 | 
			
		||||
		var healthChecksFailed bool
 | 
			
		||||
		var (
 | 
			
		||||
			healthChecksFailed bool
 | 
			
		||||
			errs               error
 | 
			
		||||
			hcWg               sync.WaitGroup
 | 
			
		||||
		)
 | 
			
		||||
 | 
			
		||||
		// TODO: Insert useful health checks here
 | 
			
		||||
		// For multiple checks, perform concurrently
 | 
			
		||||
		// Consider using errors.Join() for multiple checks
 | 
			
		||||
		var hcWg sync.WaitGroup
 | 
			
		||||
		for range 5 {
 | 
			
		||||
			hcWg.Add(1)
 | 
			
		||||
		if len(hcFuncs) < 1 {
 | 
			
		||||
			zerolog.Ctx(ctx).Warn().Msg("no health checks given responding with dummy 200")
 | 
			
		||||
			hcFuncs = append(hcFuncs, dummyHealthCheck)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Run all health check funcs concurrently
 | 
			
		||||
		// log all errors
 | 
			
		||||
		hcWg.Add(len(hcFuncs))
 | 
			
		||||
		for _, hc := range hcFuncs {
 | 
			
		||||
			go func() {
 | 
			
		||||
				defer hcWg.Done()
 | 
			
		||||
				err = errors.Join(err, dummyHealthCheck(r.Context()))
 | 
			
		||||
				errs = errors.Join(errs, hc(ctx))
 | 
			
		||||
			}()
 | 
			
		||||
		}
 | 
			
		||||
		hcWg.Wait()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
 | 
			
		||||
		if errs != nil {
 | 
			
		||||
			healthChecksFailed = true
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// TODO: Friendly reminder...
 | 
			
		||||
		err = errors.New("WARNING: Unimplemented health-check")
 | 
			
		||||
 | 
			
		||||
		if healthChecksFailed {
 | 
			
		||||
			w.WriteHeader(http.StatusInternalServerError)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			w.Write([]byte(err.Error()))
 | 
			
		||||
		if errs != nil {
 | 
			
		||||
			w.Write([]byte(errs.Error()))
 | 
			
		||||
		} else {
 | 
			
		||||
			w.Write([]byte("ok"))
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user