fix: retry _poll_task on transient 599 instead of aborting immediately
DirSize for large directories (e.g. /docker, 8441 folders, 46832 files) takes ~800ms to compute. While running, status returns intermediate progress (finished=false). But on the very first poll the task can return 599 transiently (task just started, not yet available). Previously _poll_task caught any SynologyError and returned immediately, making dir_size always fail on the first 599. Fix: treat 599 as a transient condition and continue polling. Give up only after 5 consecutive 599 responses. All other error codes remain immediately fatal. Investigation confirmed with test_dirsize_md5.py: - /test-mcp (2937 B): finished=true at 0ms - /docker (3.9 GB, 46832 files): finished=false at 35ms, finished=true at 789ms Tests: 2 new cases (retry-succeeds, 5x-599-gives-up) → 95 total Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1610,6 +1610,49 @@ async def test_dir_size_empty_path(config: AppConfig) -> None:
|
||||
client.request.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_dir_size_retries_on_transient_599(config: AppConfig) -> None:
|
||||
"""dir_size retries up to 4 times on code-599 then succeeds on 5th status call."""
|
||||
client = MagicMock()
|
||||
call_count = {"status": 0}
|
||||
|
||||
async def _request(api, method, version=None, params=None, **kwargs):
|
||||
if method == "start":
|
||||
return {"taskid": "FileStation_dirsize_599"}
|
||||
call_count["status"] += 1
|
||||
if call_count["status"] < 4:
|
||||
raise SynologyError("DSM error code 599", code=599)
|
||||
return {"finished": True, "num_dir": 2, "num_file": 10, "total_size": 1024}
|
||||
|
||||
client.request = AsyncMock(side_effect=_request)
|
||||
tools = _make_mcp_and_tools(config, client)
|
||||
|
||||
with patch("asyncio.sleep", new_callable=AsyncMock):
|
||||
result = await tools["dir_size"](path="/data")
|
||||
|
||||
assert "Total Size" in result
|
||||
assert call_count["status"] == 4
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_dir_size_fails_after_5_consecutive_599(config: AppConfig) -> None:
|
||||
"""dir_size gives up and returns Error: after 5 consecutive 599 responses."""
|
||||
client = MagicMock()
|
||||
|
||||
async def _request(api, method, version=None, params=None, **kwargs):
|
||||
if method == "start":
|
||||
return {"taskid": "FileStation_dirsize_dead"}
|
||||
raise SynologyError("DSM error code 599", code=599)
|
||||
|
||||
client.request = AsyncMock(side_effect=_request)
|
||||
tools = _make_mcp_and_tools(config, client)
|
||||
|
||||
with patch("asyncio.sleep", new_callable=AsyncMock):
|
||||
result = await tools["dir_size"](path="/dead")
|
||||
|
||||
assert result.startswith("Error:")
|
||||
|
||||
|
||||
# ──────────────────────────────────────────────────────────────────────────
|
||||
# get_md5
|
||||
# ──────────────────────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user