diff --git a/api/src/backend/queries/evaluations.py b/api/src/backend/queries/evaluations.py index 69b189f5..0d740df8 100644 --- a/api/src/backend/queries/evaluations.py +++ b/api/src/backend/queries/evaluations.py @@ -440,3 +440,13 @@ async def get_miner_hotkey_from_version_id(conn: asyncpg.Connection, version_id: FROM miner_agents WHERE version_id = $1 """, version_id) + +@db_operation +async def is_screener_running_evaluation(conn: asyncpg.Connection, validator_hotkey: str) -> bool: + """Check if a screener is running an evaluation""" + return await conn.fetchval( + """ + SELECT EXISTS(SELECT 1 FROM evaluations WHERE validator_hotkey = $1 AND status = 'running') + """, + validator_hotkey + ) \ No newline at end of file diff --git a/api/src/backend/queries/evaluations.pyi b/api/src/backend/queries/evaluations.pyi index 30d42c99..97d2075d 100644 --- a/api/src/backend/queries/evaluations.pyi +++ b/api/src/backend/queries/evaluations.pyi @@ -11,4 +11,5 @@ async def get_running_evaluation_by_miner_hotkey(miner_hotkey: str) -> Optional[ async def does_validator_have_running_evaluation(validator_hotkey: str) -> bool: ... async def get_queue_info(validator_hotkey: str, length: int = 10) -> List[Evaluation]: ... async def get_agent_name_from_version_id(version_id: str) -> Optional[str]: ... -async def get_miner_hotkey_from_version_id(version_id: str) -> Optional[str]: ... \ No newline at end of file +async def get_miner_hotkey_from_version_id(version_id: str) -> Optional[str]: ... +async def is_screener_running_evaluation(validator_hotkey: str) -> bool: ... \ No newline at end of file diff --git a/api/src/endpoints/upload.py b/api/src/endpoints/upload.py index fa6470a3..abdd9772 100644 --- a/api/src/endpoints/upload.py +++ b/api/src/endpoints/upload.py @@ -111,6 +111,17 @@ async def post_agent( status_code=503, detail="No stage 1 screeners available for agent evaluation. Please try again later." ) + + # Check is there is an evaluation in the database with the screener's hotkey that has running status + # This is to prevent the case where a screener.is_available() returns true but the screener is actually running an evaluation + from api.src.backend.queries.evaluations import is_screener_running_evaluation + is_screener_running_evaluation = await is_screener_running_evaluation(screener.hotkey) + if is_screener_running_evaluation: + logger.error(f"No available stage 1 screener for agent upload from miner {miner_hotkey} - screener {screener.hotkey} said it was available but there is an evaluation in the database with the screener's hotkey that has running status") + raise HTTPException( + status_code=409, + detail="No stage 1 screeners available for agent evaluation. Please try again later." + ) async with get_transaction() as conn: can_upload = await Evaluation.check_miner_has_no_running_evaluations(conn, miner_hotkey)