mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-16 14:32:34 +00:00
fix(dashboard): keep status responsive when session db locks
This commit is contained in:
parent
09693cd3a3
commit
a3454dd15d
2 changed files with 80 additions and 16 deletions
|
|
@ -1100,6 +1100,8 @@ except (ValueError, TypeError):
|
|||
)
|
||||
_GATEWAY_HEALTH_TIMEOUT = 3.0
|
||||
|
||||
_STATUS_ACTIVE_SESSIONS_TIMEOUT = 0.75
|
||||
|
||||
# DEPRECATED (scheduled for removal): GATEWAY_HEALTH_URL / GATEWAY_HEALTH_TIMEOUT.
|
||||
# Cross-container / cross-host gateway liveness detection will be folded into a
|
||||
# first-class dashboard config key so it's no longer Docker-adjacent lore buried
|
||||
|
|
@ -1150,6 +1152,45 @@ def _probe_gateway_health() -> tuple[bool, dict | None]:
|
|||
return False, None
|
||||
|
||||
|
||||
def _count_status_active_sessions() -> int:
|
||||
"""Return the dashboard status active-session count.
|
||||
|
||||
This is best-effort status garnish, not a critical path. Use a read-only
|
||||
connection so /api/status never tries to initialise or migrate state.db
|
||||
while another Hermes process is writing to it.
|
||||
"""
|
||||
from hermes_state import SessionDB
|
||||
|
||||
db = SessionDB(read_only=True)
|
||||
try:
|
||||
sessions = db.list_sessions_rich(limit=50)
|
||||
now = time.time()
|
||||
return sum(
|
||||
1 for s in sessions
|
||||
if s.get("ended_at") is None
|
||||
and (now - s.get("last_active", s.get("started_at", 0))) < 300
|
||||
)
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
|
||||
async def _status_active_sessions() -> int:
|
||||
loop = asyncio.get_running_loop()
|
||||
try:
|
||||
return await asyncio.wait_for(
|
||||
loop.run_in_executor(None, _count_status_active_sessions),
|
||||
timeout=_STATUS_ACTIVE_SESSIONS_TIMEOUT,
|
||||
)
|
||||
except asyncio.TimeoutError:
|
||||
_log.debug(
|
||||
"/api/status active session count exceeded %.2fs; returning 0",
|
||||
_STATUS_ACTIVE_SESSIONS_TIMEOUT,
|
||||
)
|
||||
except Exception as exc:
|
||||
_log.debug("/api/status active session count unavailable: %s", exc)
|
||||
return 0
|
||||
|
||||
|
||||
# Image MIME types this endpoint will serve. Extension-allowlisted so an
|
||||
# authenticated caller can't pull non-image files through it.
|
||||
_MEDIA_CONTENT_TYPES = {
|
||||
|
|
@ -2264,22 +2305,7 @@ async def get_status(profile: Optional[str] = None):
|
|||
if gateway_running and gateway_state is None and remote_health_body is not None:
|
||||
gateway_state = "running"
|
||||
|
||||
active_sessions = 0
|
||||
try:
|
||||
from hermes_state import SessionDB
|
||||
db = SessionDB()
|
||||
try:
|
||||
sessions = db.list_sessions_rich(limit=50)
|
||||
now = time.time()
|
||||
active_sessions = sum(
|
||||
1 for s in sessions
|
||||
if s.get("ended_at") is None
|
||||
and (now - s.get("last_active", s.get("started_at", 0))) < 300
|
||||
)
|
||||
finally:
|
||||
db.close()
|
||||
except Exception:
|
||||
pass
|
||||
active_sessions = await _status_active_sessions()
|
||||
|
||||
# Busy/drainable readout (NAS lifecycle-safety gate). active_agents is
|
||||
# the in-flight gateway-turn count the gateway now persists at every
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue