feat(map): add cached public station navigation
This commit is contained in:
@@ -37,8 +37,8 @@ python3 server.py
|
||||
本服务提供:
|
||||
|
||||
- `GET /api/health`:进程及配置状态;
|
||||
- `GET /api/dashboard`:面向前端的公开聚合数据,默认缓存5秒;加氢站缓存1小时。
|
||||
- `GET /api/dashboard`:面向前端的公开聚合数据,默认缓存 2 分钟;加氢站目录同样缓存 2 分钟。服务启动后会后台预热缓存,避免首位访问者等待上游数据请求。
|
||||
|
||||
全国视图按车辆最新 GPS 坐标落入省级行政区,不按车牌归属地推断;没有有效实时坐标的车辆会单独计入“无实时位置”,不会伪造省份归属。页面每15秒刷新一次。
|
||||
全国视图按车辆最新 GPS 坐标落入省级行政区,不按车牌归属地推断;没有有效实时坐标的车辆会单独计入“无实时位置”,不会伪造省份归属。页面每 15 秒请求一次,但服务端最多每 2 分钟刷新一次上游快照,以换取更快、更稳定的首屏加载。
|
||||
|
||||
车辆地图按缩放级别逐级下钻:全国视角(小于7级)按省聚合,7–9.5级按市聚合,9.5–12级按区县聚合,12级及以上显示当前视野内的单车真实位置。点击省、市、区县气泡会自动进入下一级。
|
||||
|
||||
+15
-2
@@ -31,8 +31,8 @@ PORT = int(os.getenv("VEHICLE_MAP_PORT", "20800"))
|
||||
OPEN_PLATFORM_BASE_URL = os.getenv("OPEN_PLATFORM_BASE_URL", "https://open.d.lnoneos.com").rstrip("/")
|
||||
OPEN_PLATFORM_APP_KEY = os.getenv("OPEN_PLATFORM_APP_KEY", "").strip()
|
||||
UPSTREAM_TIMEOUT_SECONDS = float(os.getenv("UPSTREAM_TIMEOUT_SECONDS", "15"))
|
||||
DASHBOARD_CACHE_SECONDS = int(os.getenv("DASHBOARD_CACHE_SECONDS", "5"))
|
||||
STATION_CACHE_SECONDS = int(os.getenv("STATION_CACHE_SECONDS", "3600"))
|
||||
DASHBOARD_CACHE_SECONDS = int(os.getenv("DASHBOARD_CACHE_SECONDS", "120"))
|
||||
STATION_CACHE_SECONDS = int(os.getenv("STATION_CACHE_SECONDS", "120"))
|
||||
_cache_lock = threading.Lock()
|
||||
_cache = {}
|
||||
|
||||
@@ -149,6 +149,18 @@ def _load_dashboard():
|
||||
}
|
||||
|
||||
|
||||
def _prewarm_dashboard_cache():
|
||||
"""Warm the first dashboard snapshot after a process restart.
|
||||
|
||||
A warm snapshot lets the first visitor receive the cached response instead
|
||||
of waiting for the three upstream requests to complete.
|
||||
"""
|
||||
try:
|
||||
_cached("dashboard", DASHBOARD_CACHE_SECONDS, _load_dashboard)
|
||||
except Exception as exc: # A later request can retry; startup must stay available.
|
||||
print(f"vehicle map cache warmup deferred: {exc}")
|
||||
|
||||
|
||||
class VehicleMapHandler(SimpleHTTPRequestHandler):
|
||||
server_version = "LingniuVehicleMap/1.0"
|
||||
|
||||
@@ -215,6 +227,7 @@ class VehicleMapHandler(SimpleHTTPRequestHandler):
|
||||
|
||||
if __name__ == "__main__":
|
||||
server = ThreadingHTTPServer((HOST, PORT), VehicleMapHandler)
|
||||
threading.Thread(target=_prewarm_dashboard_cache, daemon=True).start()
|
||||
print(f"Lingniu Vehicle Map listening on http://{HOST}:{PORT}")
|
||||
try:
|
||||
server.serve_forever()
|
||||
|
||||
@@ -47,5 +47,17 @@ class DashboardTest(unittest.TestCase):
|
||||
index_template = (Path(__file__).parents[1] / "index.html").read_text(encoding="utf-8")
|
||||
self.assertEqual(index_template.count("__ASSET_VERSION__"), 2)
|
||||
|
||||
def test_default_cache_window_is_two_minutes(self):
|
||||
self.assertEqual(server.DASHBOARD_CACHE_SECONDS, 120)
|
||||
self.assertEqual(server.STATION_CACHE_SECONDS, 120)
|
||||
|
||||
def test_cache_reuses_dashboard_snapshot_within_window(self):
|
||||
calls = []
|
||||
with patch.object(server, "_cache", {}):
|
||||
first = server._cached("dashboard", 120, lambda: calls.append("load") or {"version": 1})
|
||||
second = server._cached("dashboard", 120, lambda: calls.append("load") or {"version": 2})
|
||||
self.assertEqual(calls, ["load"])
|
||||
self.assertEqual(first, second)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user