package srv import ( "context" "errors" "math/rand" "net/http" "sync" "time" "github.com/rs/zerolog" ) 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 ( healthChecksFailed bool errs error hcWg sync.WaitGroup ) 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() errs = errors.Join(errs, hc(ctx)) }() } hcWg.Wait() if errs != nil { healthChecksFailed = true } if healthChecksFailed { w.WriteHeader(http.StatusInternalServerError) } if errs != nil { w.Write([]byte(errs.Error())) } else { w.Write([]byte("ok")) } } } func dummyHealthCheck(ctx context.Context) error { workFor := rand.Intn(750) ticker := time.NewTicker(time.Duration(time.Duration(workFor) * time.Millisecond)) select { case <-ticker.C: return nil case <-ctx.Done(): return ctx.Err() } }