1package daemon23import (4 "context"5 "net/http"6 "time"7)89const healthProbeTimeout = 500 * time.Millisecond1011func (a *App) healthHTTP(w http.ResponseWriter, r *http.Request) {12 if r.URL.Path == "/healthz" {13 if a.isClosed() {14 writeJSON(w, http.StatusServiceUnavailable, map[string]string{"status": "shutting_down"})15 return16 }17 writeJSON(w, http.StatusOK, map[string]string{"status": "alive"})18 return19 }20 if r.URL.Path == "/readyz" {21 if err := a.ready(r.Context()); err != nil {22 writeJSON(w, http.StatusServiceUnavailable, map[string]string{"status": "unready"})23 return24 }25 writeJSON(w, http.StatusOK, map[string]string{"status": "ready"})26 return27 }28 http.NotFound(w, r)29}3031func (a *App) ready(parent context.Context) error {32 if a.isClosed() {33 return ErrTenantClosing34 }35 a.lifecycle.mu.Lock()36 started := a.lifecycle.started37 a.lifecycle.mu.Unlock()38 if !started {39 return ErrMaintenance40 }41 ctx, cancel := context.WithTimeout(parent, healthProbeTimeout)42 defer cancel()43 _, err := a.catalog.List(ctx)44 return err45}4647func (a *App) isClosed() bool {48 a.mu.Lock()49 defer a.mu.Unlock()50 return a.closed51}5253func (t *Tenant) healthHTTP(w http.ResponseWriter, r *http.Request) {54 ctx, done, err := t.beginOperation(r.Context())55 if err != nil {56 writeJSON(w, http.StatusServiceUnavailable, map[string]string{"status": "unavailable"})57 return58 }59 defer done()60 probeCtx, cancel := context.WithTimeout(ctx, healthProbeTimeout)61 defer cancel()62 if err := t.store.DB().PingContext(probeCtx); err != nil {63 writeJSON(w, http.StatusServiceUnavailable, map[string]string{"status": "unavailable"})64 return65 }66 writeJSON(w, http.StatusOK, map[string]string{"status": "ready"})67}