From 063dd6c51c31958d30da6d9efa5ee96cbcc6670b Mon Sep 17 00:00:00 2001 From: Tom Carman Date: Mon, 4 May 2026 23:03:08 +0100 Subject: [PATCH] fix: reduce complexity of caching, no go routine needed --- core/api.go | 6 +- core/cached-stats.go | 69 +++++++------------- core/core.go | 7 +- migrations/000008_add_cached_stats.up.sql | 1 - web/src/components/MetricAircraftSeen.svelte | 5 ++ web/src/components/MetricFlightsSeen.svelte | 5 ++ 6 files changed, 38 insertions(+), 55 deletions(-) diff --git a/core/api.go b/core/api.go index 86547f9..c86b072 100644 --- a/core/api.go +++ b/core/api.go @@ -1502,12 +1502,14 @@ func (s *APIServer) getRecentSeenMetrics(c *gin.Context) { func (s *APIServer) getTotalSeenMetrics(c *gin.Context) { stats := gin.H{} - totalFlights, err := s.cachedStats.GetCachedStat("total_flights") + var totalFlights int + err := s.pg.db.QueryRow(context.Background(), + "SELECT COUNT(*) FROM aircraft_data").Scan(&totalFlights) if err == nil { stats["total_flights"] = totalFlights } - totalAircraft, err := s.cachedStats.GetCachedStat("total_aircraft") + totalAircraft, err := s.cachedStats.GetCachedTotalAircraft() if err == nil { stats["total_aircraft"] = totalAircraft } diff --git a/core/cached-stats.go b/core/cached-stats.go index 8731849..0145823 100644 --- a/core/cached-stats.go +++ b/core/cached-stats.go @@ -15,14 +15,7 @@ func NewCachedStatsService(pg *postgres) *CachedStatsService { return &CachedStatsService{pg: pg} } -func (s *CachedStatsService) GetCachedStat(key string) (int, error) { - var value int - err := s.pg.db.QueryRow(context.Background(), - "SELECT stat_value FROM cached_stats WHERE stat_key = $1", key).Scan(&value) - return value, err -} - -func (s *CachedStatsService) UpdateCachedStat(key string, value int) error { +func (s *CachedStatsService) updateCachedStat(key string, value int) error { _, err := s.pg.db.Exec(context.Background(), `INSERT INTO cached_stats (stat_key, stat_value, last_updated) VALUES ($1, $2, NOW()) @@ -32,59 +25,41 @@ func (s *CachedStatsService) UpdateCachedStat(key string, value int) error { return err } -func (s *CachedStatsService) RefreshAllTotals() error { - log.Info().Msg("Refreshing cached all-time statistics...") - - // Update total flights - var totalFlights int +func (s *CachedStatsService) GetCachedTotalAircraft() (int, error) { + var value int + var lastUpdated time.Time err := s.pg.db.QueryRow(context.Background(), - "SELECT COUNT(*) FROM aircraft_data").Scan(&totalFlights) - if err != nil { - log.Error().Err(err).Msg("Failed to count total flights") - return err - } - err = s.UpdateCachedStat("total_flights", totalFlights) - if err != nil { - log.Error().Err(err).Msg("Failed to update cached total_flights") - return err + `SELECT stat_value, last_updated FROM cached_stats + WHERE stat_key = 'total_aircraft'`).Scan(&value, &lastUpdated) + + if err == nil && time.Since(lastUpdated) < 24*time.Hour { + log.Debug(). + Int("total_aircraft", value). + Dur("cache_age", time.Since(lastUpdated)). + Msg("Returning cached total_aircraft") + return value, nil } - // Update total aircraft + log.Info().Msg("Cache stale or missing, recalculating total_aircraft...") + var totalAircraft int err = s.pg.db.QueryRow(context.Background(), "SELECT COUNT(DISTINCT hex) FROM aircraft_data").Scan(&totalAircraft) if err != nil { log.Error().Err(err).Msg("Failed to count total aircraft") - return err + return 0, err } - err = s.UpdateCachedStat("total_aircraft", totalAircraft) + + // Update cache + err = s.updateCachedStat("total_aircraft", totalAircraft) if err != nil { log.Error().Err(err).Msg("Failed to update cached total_aircraft") - return err + return totalAircraft, nil } log.Info(). - Int("total_flights", totalFlights). Int("total_aircraft", totalAircraft). - Msg("Successfully refreshed cached statistics") - - return nil -} - -func (s *CachedStatsService) StartPeriodicRefresh(interval time.Duration) { - go func() { - // Initial refresh on startup - if err := s.RefreshAllTotals(); err != nil { - log.Error().Err(err).Msg("Initial cache refresh failed") - } - - ticker := time.NewTicker(interval) - defer ticker.Stop() + Msg("Successfully recalculated and cached total_aircraft") - for range ticker.C { - if err := s.RefreshAllTotals(); err != nil { - log.Error().Err(err).Msg("Periodic cache refresh failed") - } - } - }() + return totalAircraft, nil } diff --git a/core/core.go b/core/core.go index 9434e3d..ce4b1c6 100644 --- a/core/core.go +++ b/core/core.go @@ -93,13 +93,10 @@ func main() { os.Exit(1) } - apiServer := NewAPIServer(pg) - - log.Info().Msg("Starting cached statistics refresh service") - apiServer.cachedStats.StartPeriodicRefresh(24 * time.Hour) - // Start API server in a separate goroutine log.Info().Msg("Starting API server") + apiServer := NewAPIServer(pg) + go func() { apiServer.Start() }() diff --git a/migrations/000008_add_cached_stats.up.sql b/migrations/000008_add_cached_stats.up.sql index b346ecc..3fe5ea3 100644 --- a/migrations/000008_add_cached_stats.up.sql +++ b/migrations/000008_add_cached_stats.up.sql @@ -8,5 +8,4 @@ CREATE TABLE cached_stats ( -- Insert initial values for all-time totals INSERT INTO cached_stats (stat_key, stat_value, last_updated) VALUES - ('total_flights', (SELECT COUNT(*) FROM aircraft_data), NOW()), ('total_aircraft', (SELECT COUNT(DISTINCT hex) FROM aircraft_data), NOW()); diff --git a/web/src/components/MetricAircraftSeen.svelte b/web/src/components/MetricAircraftSeen.svelte index 39fc4e3..e007d29 100644 --- a/web/src/components/MetricAircraftSeen.svelte +++ b/web/src/components/MetricAircraftSeen.svelte @@ -9,6 +9,7 @@ let loading = true; let error = null; let recentInterval = null; + let totalInterval = null; async function fetchRecentData() { try { @@ -45,12 +46,16 @@ fetchRecentData(); fetchTotalData(); recentInterval = setInterval(fetchRecentData, 2000); + totalInterval = setInterval(fetchTotalData, 60000); }) onDestroy(() => { if (recentInterval) { clearInterval(recentInterval); } + if (totalInterval) { + clearInterval(totalInterval); + } }); {#if loading} diff --git a/web/src/components/MetricFlightsSeen.svelte b/web/src/components/MetricFlightsSeen.svelte index e8d0ebe..a3fa90a 100644 --- a/web/src/components/MetricFlightsSeen.svelte +++ b/web/src/components/MetricFlightsSeen.svelte @@ -9,6 +9,7 @@ let loading = true; let error = null; let recentInterval = null; + let totalInterval = null; async function fetchRecentData() { try { @@ -45,12 +46,16 @@ fetchRecentData(); fetchTotalData(); recentInterval = setInterval(fetchRecentData, 2000); + totalInterval = setInterval(fetchTotalData, 60000); }) onDestroy(() => { if (recentInterval) { clearInterval(recentInterval); } + if (totalInterval) { + clearInterval(totalInterval); + } }); {#if loading}