From d27ca8bf40e9668958743fd98a68c9b99e5355bb Mon Sep 17 00:00:00 2001 From: grabowski Date: Wed, 12 Aug 2026 10:58:19 +0700 Subject: [PATCH] perf: 120s TTL cache with single-flight on /api/hii/*/latest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These endpoints ran an uncached latest-per-station aggregation on every request (p50 0.6-0.9s under load, ~30% of the traffic mix) for data the collector refreshes hourly. Responses are now cached per (feed, hours) for HII_CACHE_TTL_SECONDS (default 120) with a per-feed compute lock so a cache miss runs one query regardless of concurrency; empty results are never cached so recovery is immediate. Cached hits measure ~8ms. Cache is process-local behind a single helper — the seam where a shared backend (Redis) would slot in if the deployment ever moves to multiple workers; not warranted at one. --- src/config.py | 2 ++ src/web_api.py | 37 +++++++++++++++++++++++++++++++++---- tests/test_hii_collector.py | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 4 deletions(-) diff --git a/src/config.py b/src/config.py index 97c62b4..cf53c68 100644 --- a/src/config.py +++ b/src/config.py @@ -86,6 +86,8 @@ class Config: "yes", ) HII_BASIN_CODE = int(os.getenv("HII_BASIN_CODE", "6")) # 6 = Ping Basin + # TTL for the /api/hii/*/latest response cache; source data changes hourly + HII_CACHE_TTL_SECONDS = int(os.getenv("HII_CACHE_TTL_SECONDS", "120")) # Umami analytics (self-hosted). The website id is public (it ships in the # dashboard