功能:完善加氢站导航详情与缓存刷新
This commit is contained in:
@@ -31,6 +31,8 @@ STATION_CACHE_SECONDS = int(os.getenv("STATION_NAVIGATION_CACHE_SECONDS", "120")
|
||||
VEHICLE_MAP_INTERNAL_BASE_URL = os.getenv("VEHICLE_MAP_INTERNAL_BASE_URL", "http://127.0.0.1:20800").rstrip("/")
|
||||
_cache_lock = threading.Lock()
|
||||
_cache = {}
|
||||
_cache_load_locks = {}
|
||||
_cache_refreshing = set()
|
||||
|
||||
|
||||
def _static_asset_version():
|
||||
@@ -80,16 +82,51 @@ def _post_open_platform(path, body):
|
||||
return payload.get("data") or []
|
||||
|
||||
|
||||
def _refresh_cached_value(key, loader):
|
||||
try:
|
||||
value = loader()
|
||||
except Exception as exc:
|
||||
print("{} cache background refresh deferred: {}".format(key, exc))
|
||||
else:
|
||||
with _cache_lock:
|
||||
_cache[key] = (time.time(), value)
|
||||
finally:
|
||||
with _cache_lock:
|
||||
_cache_refreshing.discard(key)
|
||||
|
||||
|
||||
def _start_cache_refresh(key, loader):
|
||||
threading.Thread(target=_refresh_cached_value, args=(key, loader), daemon=True).start()
|
||||
|
||||
|
||||
def _cached(key, ttl_seconds, loader):
|
||||
now = time.time()
|
||||
refresh_in_background = False
|
||||
with _cache_lock:
|
||||
cached = _cache.get(key)
|
||||
if cached and now - cached[0] < ttl_seconds:
|
||||
return cached[1]
|
||||
value = loader()
|
||||
with _cache_lock:
|
||||
_cache[key] = (now, value)
|
||||
return value
|
||||
if cached:
|
||||
if key not in _cache_refreshing:
|
||||
_cache_refreshing.add(key)
|
||||
refresh_in_background = True
|
||||
stale_value = cached[1]
|
||||
else:
|
||||
stale_value = None
|
||||
load_lock = _cache_load_locks.setdefault(key, threading.Lock())
|
||||
if cached:
|
||||
if refresh_in_background:
|
||||
_start_cache_refresh(key, loader)
|
||||
return stale_value
|
||||
with load_lock:
|
||||
with _cache_lock:
|
||||
cached = _cache.get(key)
|
||||
if cached:
|
||||
return _cached(key, ttl_seconds, loader)
|
||||
value = loader()
|
||||
with _cache_lock:
|
||||
_cache[key] = (time.time(), value)
|
||||
return value
|
||||
|
||||
|
||||
def _load_station_directory():
|
||||
@@ -137,7 +174,7 @@ class StationNavigationHandler(SimpleHTTPRequestHandler):
|
||||
return
|
||||
if path == "/api/stations":
|
||||
try:
|
||||
self._write_json(200, _cached("station-directory", STATION_CACHE_SECONDS, _load_station_directory))
|
||||
payload = _cached("station-directory", STATION_CACHE_SECONDS, _load_station_directory)
|
||||
except Exception as exc:
|
||||
self.log_error("station directory refresh failed: %s", exc)
|
||||
self._write_json(502, {
|
||||
@@ -145,6 +182,8 @@ class StationNavigationHandler(SimpleHTTPRequestHandler):
|
||||
"code": "UPSTREAM_UNAVAILABLE",
|
||||
"message": "加氢站数据暂时不可用,请稍后重试",
|
||||
})
|
||||
return
|
||||
self._write_json(200, payload)
|
||||
return
|
||||
if path == "/assets/logo_light.svg":
|
||||
self._serve_logo()
|
||||
@@ -213,7 +252,10 @@ class StationNavigationHandler(SimpleHTTPRequestHandler):
|
||||
self.send_header("Cache-Control", "no-store")
|
||||
self.send_header("Content-Length", str(len(body)))
|
||||
self.end_headers()
|
||||
self.wfile.write(body)
|
||||
try:
|
||||
self.wfile.write(body)
|
||||
except (BrokenPipeError, ConnectionResetError):
|
||||
self.log_message("client disconnected before JSON response completed")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user