generated from coulomb/repo-seed
feat(summary): revision-gated cache with stale-while-revalidate (STATE-WP-0066)
Replace the fixed 15s TTL on GET /state/summary with per-table revision watermarks, stale-while-revalidate background refresh, and a progress-tail section split. SQLAlchemy write hooks invalidate core or progress sections on mutation. Adds tests, benchmark script, and operator docs.
This commit is contained in:
40
scripts/benchmark_summary_cache.py
Normal file
40
scripts/benchmark_summary_cache.py
Normal file
@@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Quick benchmark for /state/summary revision cache (STATE-WP-0066)."""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import statistics
|
||||
import sys
|
||||
import time
|
||||
import urllib.request
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--base-url", default="http://127.0.0.1:8000")
|
||||
parser.add_argument("--requests", type=int, default=10)
|
||||
args = parser.parse_args()
|
||||
|
||||
url = f"{args.base_url.rstrip('/')}/state/summary"
|
||||
timings: list[float] = []
|
||||
last_cache = ""
|
||||
|
||||
# Prime cache
|
||||
with urllib.request.urlopen(url, timeout=30) as resp:
|
||||
resp.read()
|
||||
last_cache = resp.headers.get("X-StateHub-Cache", "")
|
||||
|
||||
for _ in range(args.requests):
|
||||
started = time.perf_counter()
|
||||
with urllib.request.urlopen(url, timeout=30) as resp:
|
||||
resp.read()
|
||||
last_cache = resp.headers.get("X-StateHub-Cache", "")
|
||||
timings.append(time.perf_counter() - started)
|
||||
|
||||
p95 = statistics.quantiles(timings, n=20)[18] if len(timings) >= 2 else timings[0]
|
||||
print(f"requests={args.requests} p50={statistics.median(timings):.3f}s p95={p95:.3f}s last_cache={last_cache}")
|
||||
return 0 if last_cache == "hit-revision" else 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user