feat(fish_api): SQLite 快照投递、日志与 watch 空闲告警
- 新增 SQLite:measure/health 快照、delivery_cursor 单消费者 pop;clear/start_fresh 可清空库 - biomass GET 仅返回约定 data 字段,X-Fish-Biomass-New 表示是否有新快照;poller 读响应头 - loguru 桥接 uvicorn,子进程 stdout 流式输出;format_json_pretty 与算法摘要日志 - measure/action watch 无新任务时限流 WARNING;watch_idle 共用逻辑 - 依赖 loguru;新增 db、logging_config、subprocess_run、watch_idle、启动脚本 FishMeasure: 更新 fish_video_weight_evaluation 与 predict_weigth_from_svo2;移除未用 refbox/segmentation 脚本 Made-with: Cursor
This commit is contained in:
@@ -2,6 +2,8 @@
|
||||
"""
|
||||
独立进程:轮询 Fish API 的两个结果接口,用 loguru 输出响应。
|
||||
|
||||
接口每次 GET 会「消费」一条未投递快照;仅当响应头 X-Fish-Biomass-New: 1(或 JSON code!=200)时打日志。
|
||||
|
||||
BIOMASS_API_BASE=http://127.0.0.1:8000 POLL_INTERVAL=5 \\
|
||||
python scripts/biomass_poller.py
|
||||
|
||||
@@ -29,24 +31,16 @@ def _fmt_body(resp: httpx.Response) -> Any:
|
||||
return resp.text
|
||||
|
||||
|
||||
_last_camera: dict | None = None
|
||||
_last_health: dict | None = None
|
||||
|
||||
|
||||
def _has_data(body: Any) -> bool:
|
||||
"""非空业务数据:code==200 且 data 里至少有一个非空字段。"""
|
||||
def _should_log(resp: httpx.Response, body: Any) -> bool:
|
||||
"""有新投递的快照(X-Fish-Biomass-New: 1)或业务错误(JSON code!=200)时打日志。"""
|
||||
if not isinstance(body, dict):
|
||||
return False
|
||||
return bool(body)
|
||||
if body.get("code") != 200:
|
||||
return True # 错误也算"新信息"
|
||||
data = body.get("data", {})
|
||||
if not isinstance(data, dict):
|
||||
return bool(data)
|
||||
return any(bool(v) for v in data.values())
|
||||
return True
|
||||
return resp.headers.get("X-Fish-Biomass-New", "").strip() == "1"
|
||||
|
||||
|
||||
async def poll_once(client: httpx.AsyncClient, base: str) -> None:
|
||||
global _last_camera, _last_health
|
||||
base = base.rstrip("/")
|
||||
camera_url = f"{base}/api/v1/biomass/real/camera/"
|
||||
health_url = f"{base}/api/v1/biomass/health/result/"
|
||||
@@ -54,14 +48,10 @@ async def poll_once(client: httpx.AsyncClient, base: str) -> None:
|
||||
r2 = await client.get(health_url)
|
||||
b1 = _fmt_body(r1)
|
||||
b2 = _fmt_body(r2)
|
||||
changed1 = b1 != _last_camera
|
||||
changed2 = b2 != _last_health
|
||||
if changed1 and _has_data(b1):
|
||||
if _should_log(r1, b1):
|
||||
logger.info("[real/camera/] HTTP {} | {}", r1.status_code, json.dumps(b1, ensure_ascii=False))
|
||||
if changed2 and _has_data(b2):
|
||||
if _should_log(r2, b2):
|
||||
logger.info("[health/result/] HTTP {} | {}", r2.status_code, json.dumps(b2, ensure_ascii=False))
|
||||
_last_camera = b1
|
||||
_last_health = b2
|
||||
|
||||
|
||||
async def poll_loop(base: str, interval: float) -> None:
|
||||
|
||||
@@ -1,20 +1,11 @@
|
||||
#!/usr/bin/env bash
|
||||
# 在「单一 Python 环境」下启动网关:FishMeasure / FishAction 子进程默认使用同一解释器。
|
||||
# 仓库根目录入口:与 fish_api/start.sh 等价
|
||||
#
|
||||
# conda activate fishserver
|
||||
# export PUBLIC_BASE_URL=http://<本机对外IP>:8001 # 可选,填 video URL 前缀
|
||||
# conda activate fishserver # 若不用 uv
|
||||
# export PUBLIC_BASE_URL=http://<本机对外IP>:8001
|
||||
# PORT=8001 bash scripts/run_fishserver.sh
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
cd "$ROOT/fish_api"
|
||||
|
||||
export PUBLIC_BASE_URL="${PUBLIC_BASE_URL:-http://127.0.0.1:8000}"
|
||||
# 单一环境:勿设置 PYTHON_FISH_MEASURE / PYTHON_FISH_ACTION,使用当前 uvicorn 的 Python
|
||||
unset PYTHON_FISH_MEASURE PYTHON_FISH_ACTION 2>/dev/null || true
|
||||
|
||||
PORT="${PORT:-8000}"
|
||||
HOST="${HOST:-0.0.0.0}"
|
||||
|
||||
exec uvicorn app.main:app --host "$HOST" --port "$PORT"
|
||||
exec bash "$ROOT/fish_api/start.sh"
|
||||
|
||||
10
scripts/start_fishapi_fresh.sh
Executable file
10
scripts/start_fishapi_fresh.sh
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
# 仓库根目录入口:删除 SQLite 库文件(及旧 JSON 状态文件)后启动 Fish API
|
||||
#
|
||||
# bash scripts/start_fishapi_fresh.sh
|
||||
# PORT=8001 bash scripts/start_fishapi_fresh.sh
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
exec bash "$ROOT/fish_api/start_fresh.sh"
|
||||
Reference in New Issue
Block a user