mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-08-28 08:34:15 +00:00
perf: add TTL cache for subpaths API + build timestamp in stats/health
- Add 15s TTL cache to GetAnalyticsSubpaths with composite key (region|minLen|maxLen|limit), matching the existing cache pattern used by RF, topology, hash, channel, and distance analytics. Cache hits return instantly vs 900ms+ computation. fixes #168 - Add BuildTime to /api/stats and /api/health responses, injected via ldflags at build time. Dockerfile.go now accepts BUILD_TIME build arg. fixes #165 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
+2
-1
@@ -4,13 +4,14 @@ RUN apk add --no-cache build-base
|
||||
|
||||
ARG APP_VERSION=unknown
|
||||
ARG GIT_COMMIT=unknown
|
||||
ARG BUILD_TIME=unknown
|
||||
|
||||
# Build server
|
||||
WORKDIR /build/server
|
||||
COPY cmd/server/go.mod cmd/server/go.sum ./
|
||||
RUN go mod download
|
||||
COPY cmd/server/ ./
|
||||
RUN go build -ldflags "-X main.Version=${APP_VERSION} -X main.Commit=${GIT_COMMIT}" -o /meshcore-server .
|
||||
RUN go build -ldflags "-X main.Version=${APP_VERSION} -X main.Commit=${GIT_COMMIT} -X main.BuildTime=${BUILD_TIME}" -o /meshcore-server .
|
||||
|
||||
# Build ingestor
|
||||
WORKDIR /build/ingestor
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
// Set via -ldflags at build time
|
||||
var Version string
|
||||
var Commit string
|
||||
var BuildTime string
|
||||
|
||||
func resolveCommit() string {
|
||||
if Commit != "" {
|
||||
@@ -45,6 +46,13 @@ func resolveVersion() string {
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
func resolveBuildTime() string {
|
||||
if BuildTime != "" {
|
||||
return BuildTime
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
func main() {
|
||||
var (
|
||||
configDir string
|
||||
|
||||
@@ -26,6 +26,7 @@ type Server struct {
|
||||
perfStats *PerfStats
|
||||
version string
|
||||
commit string
|
||||
buildTime string
|
||||
}
|
||||
|
||||
// PerfStats tracks request performance.
|
||||
@@ -61,6 +62,7 @@ func NewServer(db *DB, cfg *Config, hub *Hub) *Server {
|
||||
perfStats: NewPerfStats(),
|
||||
version: resolveVersion(),
|
||||
commit: resolveCommit(),
|
||||
buildTime: resolveBuildTime(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,6 +322,7 @@ func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) {
|
||||
Engine: "go",
|
||||
Version: s.version,
|
||||
Commit: s.commit,
|
||||
BuildTime: s.buildTime,
|
||||
Uptime: int(uptime),
|
||||
UptimeHuman: fmt.Sprintf("%dh %dm", int(uptime)/3600, (int(uptime)%3600)/60),
|
||||
Memory: MemoryStats{
|
||||
@@ -374,6 +377,7 @@ func (s *Server) handleStats(w http.ResponseWriter, r *http.Request) {
|
||||
Engine: "go",
|
||||
Version: s.version,
|
||||
Commit: s.commit,
|
||||
BuildTime: s.buildTime,
|
||||
Counts: RoleCounts{
|
||||
Repeaters: counts["repeaters"],
|
||||
Rooms: counts["rooms"],
|
||||
|
||||
+25
-2
@@ -80,6 +80,7 @@ type PacketStore struct {
|
||||
hashCache map[string]*cachedResult // region → cached hash-sizes result
|
||||
chanCache map[string]*cachedResult // region → cached channels result
|
||||
distCache map[string]*cachedResult // region → cached distance result
|
||||
subpathCache map[string]*cachedResult // params → cached subpaths result
|
||||
rfCacheTTL time.Duration
|
||||
cacheHits int64
|
||||
cacheMisses int64
|
||||
@@ -111,6 +112,7 @@ func NewPacketStore(db *DB) *PacketStore {
|
||||
hashCache: make(map[string]*cachedResult),
|
||||
chanCache: make(map[string]*cachedResult),
|
||||
distCache: make(map[string]*cachedResult),
|
||||
subpathCache: make(map[string]*cachedResult),
|
||||
rfCacheTTL: 15 * time.Second,
|
||||
}
|
||||
}
|
||||
@@ -508,7 +510,7 @@ func (s *PacketStore) GetPerfStoreStats() map[string]interface{} {
|
||||
// GetCacheStats returns RF cache hit/miss statistics.
|
||||
func (s *PacketStore) GetCacheStats() map[string]interface{} {
|
||||
s.cacheMu.Lock()
|
||||
size := len(s.rfCache) + len(s.topoCache) + len(s.hashCache) + len(s.chanCache) + len(s.distCache)
|
||||
size := len(s.rfCache) + len(s.topoCache) + len(s.hashCache) + len(s.chanCache) + len(s.distCache) + len(s.subpathCache)
|
||||
hits := s.cacheHits
|
||||
misses := s.cacheMisses
|
||||
s.cacheMu.Unlock()
|
||||
@@ -531,7 +533,7 @@ func (s *PacketStore) GetCacheStats() map[string]interface{} {
|
||||
// GetCacheStatsTyped returns cache stats as a typed struct.
|
||||
func (s *PacketStore) GetCacheStatsTyped() CacheStats {
|
||||
s.cacheMu.Lock()
|
||||
size := len(s.rfCache) + len(s.topoCache) + len(s.hashCache) + len(s.chanCache) + len(s.distCache)
|
||||
size := len(s.rfCache) + len(s.topoCache) + len(s.hashCache) + len(s.chanCache) + len(s.distCache) + len(s.subpathCache)
|
||||
hits := s.cacheHits
|
||||
misses := s.cacheMisses
|
||||
s.cacheMu.Unlock()
|
||||
@@ -3518,6 +3520,27 @@ func (s *PacketStore) GetBulkHealth(limit int, region string) []map[string]inter
|
||||
// --- Subpaths Analytics ---
|
||||
|
||||
func (s *PacketStore) GetAnalyticsSubpaths(region string, minLen, maxLen, limit int) map[string]interface{} {
|
||||
cacheKey := fmt.Sprintf("%s|%d|%d|%d", region, minLen, maxLen, limit)
|
||||
|
||||
s.cacheMu.Lock()
|
||||
if cached, ok := s.subpathCache[cacheKey]; ok && time.Now().Before(cached.expiresAt) {
|
||||
s.cacheHits++
|
||||
s.cacheMu.Unlock()
|
||||
return cached.data
|
||||
}
|
||||
s.cacheMisses++
|
||||
s.cacheMu.Unlock()
|
||||
|
||||
result := s.computeAnalyticsSubpaths(region, minLen, maxLen, limit)
|
||||
|
||||
s.cacheMu.Lock()
|
||||
s.subpathCache[cacheKey] = &cachedResult{data: result, expiresAt: time.Now().Add(s.rfCacheTTL)}
|
||||
s.cacheMu.Unlock()
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *PacketStore) computeAnalyticsSubpaths(region string, minLen, maxLen, limit int) map[string]interface{} {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ type StatsResponse struct {
|
||||
Engine string `json:"engine"`
|
||||
Version string `json:"version"`
|
||||
Commit string `json:"commit"`
|
||||
BuildTime string `json:"buildTime"`
|
||||
Counts RoleCounts `json:"counts"`
|
||||
}
|
||||
|
||||
@@ -132,6 +133,7 @@ type HealthResponse struct {
|
||||
Engine string `json:"engine"`
|
||||
Version string `json:"version"`
|
||||
Commit string `json:"commit"`
|
||||
BuildTime string `json:"buildTime"`
|
||||
Uptime int `json:"uptime"`
|
||||
UptimeHuman string `json:"uptimeHuman"`
|
||||
Memory MemoryStats `json:"memory"`
|
||||
|
||||
Reference in New Issue
Block a user