fix(api): /health never serves a cached result older than 4 TTLs
CI / Format & lint (push) Successful in 27s
CI / Test suite (push) Successful in 56s
Docs / Validate documentation (push) Successful in 26s
Security / Dependency vulnerabilities (push) Successful in 2m2s
Security / Static analysis (push) Successful in 21s
Security / License report (push) Successful in 1m50s
CI / Format & lint (push) Successful in 27s
CI / Test suite (push) Successful in 56s
Docs / Validate documentation (push) Successful in 26s
Security / Dependency vulnerabilities (push) Successful in 2m2s
Security / Static analysis (push) Successful in 21s
Security / License report (push) Successful in 1m50s
Stale-while-revalidate answered the first /health after a quiet night with the previous evening's state (seen after the collector cutover: 'Latest data is old: 21:00' at 13:47 while data was current). _cached_swr gains max_stale; /health uses 4 x HEALTH_CACHE_TTL_SECONDS.
This commit is contained in:
1 parent
9b910c3cbf
commit
64c5b02e06
2 files changed
+39
-2
No files matched your search
+12
-2
@@ -784,6 +784,8 @@ async def get_health():
|
||||
"health",
|
||||
Config.HEALTH_CACHE_TTL_SECONDS,
|
||||
compute,
|
||||
# never report a state older than a few TTLs: monitors poll /health
|
||||
max_stale=4 * Config.HEALTH_CACHE_TTL_SECONDS,
|
||||
)
|
||||
|
||||
return HealthResponse(**summary)
|
||||
@@ -1102,7 +1104,9 @@ _REFRESH_IN_FLIGHT: set = set()
|
||||
_REFRESH_FLAG_LOCK = Lock()
|
||||
|
||||
|
||||
async def _cached_swr(cache, cache_lock, compute_lock, key, ttl, compute):
|
||||
async def _cached_swr(
|
||||
cache, cache_lock, compute_lock, key, ttl, compute, max_stale=None
|
||||
):
|
||||
"""Stale-while-revalidate. Returns (value, served_stale).
|
||||
|
||||
fresh -> return inline; expired-but-present -> return the stale value
|
||||
@@ -1110,13 +1114,19 @@ async def _cached_swr(cache, cache_lock, compute_lock, key, ttl, compute):
|
||||
thread is parked on the single-flight lock — under stampede that parking
|
||||
exhausted the pool and timed out unrelated endpoints); absent -> cold
|
||||
single-flight compute (first request per key since startup).
|
||||
|
||||
``max_stale`` (seconds) bounds how old a served stale copy may be; older
|
||||
entries are recomputed inline. A worker that idles overnight would
|
||||
otherwise answer its first request with a result from the evening before.
|
||||
"""
|
||||
fresh = _cache_fresh(cache, cache_lock, key, ttl)
|
||||
if fresh is not None:
|
||||
return fresh, False
|
||||
with cache_lock:
|
||||
entry = cache.get(key)
|
||||
if entry is not None:
|
||||
if entry is not None and (
|
||||
max_stale is None or time.monotonic() - entry[0] <= max_stale
|
||||
):
|
||||
with _REFRESH_FLAG_LOCK:
|
||||
should_start = key not in _REFRESH_IN_FLIGHT
|
||||
if should_start:
|
||||
|
||||
Reference in new issue
Block a user