diff --git a/ntpdb/dbconn.go b/ntpdb/dbconn.go index e267d3b..29f56a4 100644 --- a/ntpdb/dbconn.go +++ b/ntpdb/dbconn.go @@ -27,8 +27,8 @@ func OpenDB(configFile string) (*sql.DB, error) { dbconn := sql.OpenDB(Driver{CreateConnectorFunc: createConnector(configFile)}) dbconn.SetConnMaxLifetime(time.Minute * 3) - dbconn.SetMaxOpenConns(10) - dbconn.SetMaxIdleConns(5) + dbconn.SetMaxOpenConns(8) + dbconn.SetMaxIdleConns(3) err := dbconn.Ping() if err != nil { diff --git a/server/server.go b/server/server.go index b08666a..54ec0b7 100644 --- a/server/server.go +++ b/server/server.go @@ -8,6 +8,8 @@ import ( "log/slog" "net/http" "os" + "strconv" + "time" "golang.org/x/sync/errgroup" @@ -97,7 +99,10 @@ func (srv *Server) Run() error { }) g.Go(func() error { - return health.HealthCheckListener(ctx, 9019, log.WithGroup("health")) + hclog := log.WithGroup("health") + hc := health.NewServer(healthHandler(srv, hclog)) + hc.SetLogger(hclog) + return hc.Listen(ctx, 9019) }) e := echo.New() @@ -271,3 +276,53 @@ func (srv *Server) userCountryData(c echo.Context) error { }) } + +func healthHandler(srv *Server, log *slog.Logger) func(w http.ResponseWriter, req *http.Request) { + + return func(w http.ResponseWriter, req *http.Request) { + + ctx := req.Context() + ctx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + g, ctx := errgroup.WithContext(ctx) + + stats := srv.db.Stats() + log.InfoContext(ctx, "health requests", "url", req.URL.String(), "stats", stats) + + reset, err := strconv.ParseBool(req.URL.Query().Get("reset")) + log.InfoContext(ctx, "db reset request", "err", err, "reset", reset) + + if err == nil && reset { + log.InfoContext(ctx, "setting idle db conns to zero") + srv.db.SetMaxIdleConns(0) + srv.db.SetConnMaxLifetime(5 * time.Second) + } + + g.Go(func() error { + err := srv.ch.Scores.Ping(ctx) + if err != nil { + log.WarnContext(ctx, "ch ping", "err", err) + return err + } + return nil + }) + + g.Go(func() error { + err := srv.db.PingContext(ctx) + if err != nil { + log.WarnContext(ctx, "db ping", "err", err) + return err + } + return nil + }) + + err = g.Wait() + if err != nil { + w.WriteHeader(http.StatusServiceUnavailable) + w.Write([]byte("db ping err")) + return + } + w.WriteHeader(http.StatusOK) + w.Write([]byte("ok")) + } +}