mirror of
https://github.com/karust/openserp.git
synced 2026-08-05 16:53:54 +08:00
Add healthcheck endpoint
This commit is contained in:
@@ -19,5 +19,8 @@ FROM zenika/alpine-chrome:with-chromedriver
|
||||
COPY --from=builder /app/openserp /usr/local/bin/openserp
|
||||
ADD config.yaml /usr/src/app
|
||||
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
||||
CMD wget --no-verbose --tries=1 --spider http://localhost:7000/health || exit 1
|
||||
|
||||
ENTRYPOINT ["openserp"]
|
||||
|
||||
|
||||
@@ -3,9 +3,11 @@ package core
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/sirupsen/logrus"
|
||||
@@ -24,6 +26,7 @@ type Server struct {
|
||||
app *fiber.App
|
||||
addr string
|
||||
searchEngines []SearchEngine
|
||||
startTime time.Time
|
||||
}
|
||||
|
||||
func NewServer(host string, port int, searchEngines ...SearchEngine) *Server {
|
||||
@@ -32,8 +35,12 @@ func NewServer(host string, port int, searchEngines ...SearchEngine) *Server {
|
||||
app: fiber.New(),
|
||||
addr: addr,
|
||||
searchEngines: searchEngines,
|
||||
startTime: time.Now(),
|
||||
}
|
||||
|
||||
// Health endpoint used by orchestration probes.
|
||||
serv.app.Get("/health", serv.handleHealthCheck)
|
||||
|
||||
for _, engine := range searchEngines {
|
||||
locEngine := engine
|
||||
limiter := engine.GetRateLimiter()
|
||||
@@ -370,6 +377,69 @@ func (s *Server) deduplicateMegaResults(results []MegaSearchResult) []MegaSearch
|
||||
return deduped
|
||||
}
|
||||
|
||||
type HealthStatus struct {
|
||||
Status string `json:"status"`
|
||||
Uptime string `json:"uptime"`
|
||||
Engines []EngineHealth `json:"engines"`
|
||||
System map[string]interface{} `json:"system"`
|
||||
}
|
||||
|
||||
type EngineHealth struct {
|
||||
Name string `json:"name"`
|
||||
Initialized bool `json:"initialized"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
// handleHealthCheck returns current service and engine status.
|
||||
// Degraded state stays HTTP 200 to avoid unnecessary restarts in orchestrators.
|
||||
func (s *Server) handleHealthCheck(c *fiber.Ctx) error {
|
||||
engines := make([]EngineHealth, 0, len(s.searchEngines))
|
||||
availableEngines := 0
|
||||
|
||||
for _, engine := range s.searchEngines {
|
||||
status := "ready"
|
||||
if !engine.IsInitialized() {
|
||||
status = "not_initialized"
|
||||
} else {
|
||||
availableEngines++
|
||||
}
|
||||
|
||||
engines = append(engines, EngineHealth{
|
||||
Name: engine.Name(),
|
||||
Initialized: engine.IsInitialized(),
|
||||
Status: status,
|
||||
})
|
||||
}
|
||||
|
||||
overallStatus := "healthy"
|
||||
totalEngines := len(s.searchEngines)
|
||||
switch {
|
||||
case totalEngines == 0 || availableEngines == 0:
|
||||
overallStatus = "unhealthy"
|
||||
case availableEngines < totalEngines:
|
||||
overallStatus = "degraded"
|
||||
}
|
||||
|
||||
var memStats runtime.MemStats
|
||||
runtime.ReadMemStats(&memStats)
|
||||
|
||||
health := HealthStatus{
|
||||
Status: overallStatus,
|
||||
Uptime: time.Since(s.startTime).Round(time.Second).String(),
|
||||
Engines: engines,
|
||||
System: map[string]interface{}{
|
||||
"goroutines": runtime.NumGoroutine(),
|
||||
"memory_mb": memStats.Alloc / 1024 / 1024,
|
||||
"go_version": runtime.Version(),
|
||||
},
|
||||
}
|
||||
|
||||
if overallStatus == "unhealthy" {
|
||||
c.Status(fiber.StatusServiceUnavailable)
|
||||
}
|
||||
return c.JSON(health)
|
||||
}
|
||||
|
||||
func (s *Server) Listen() error {
|
||||
return s.app.Listen(s.addr)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user