[Frontend]Handle audio generate engine errors consistently (#3316)

Signed-off-by: reidliu41 <reid201711@gmail.com>
Co-authored-by: SYLAR <125541396+lishunyang12@users.noreply.github.com>
This commit is contained in:
ReidandSYLAR authored and GitHub committed 2026-05-17 14:10:26 +00:00
1 parent 220db62b3f
commit 768943b879
2 files changed
+60 -3

No files matched your search

@@ -1,13 +1,16 @@
# tests/entrypoints/openai_api/test_serving_audio_generate.py
import logging
from inspect import Signature, signature
from unittest.mock import MagicMock, patch
from types import SimpleNamespace
from unittest.mock import AsyncMock, MagicMock, patch
import pytest
import torch
from fastapi import FastAPI
from fastapi import FastAPI, Request
from fastapi.testclient import TestClient
from vllm.v1.engine.exceptions import EngineGenerateError
from vllm_omni.entrypoints.omni_base import OmniEngineDeadError
from vllm_omni.entrypoints.openai import api_server as api_server_module
from vllm_omni.entrypoints.openai.protocol.audio import (
CreateAudio,
OpenAICreateAudioGenerateRequest,
@@ -106,6 +109,29 @@ def client(test_app):
return TestClient(test_app)
def _make_api_server_test_app(handler, *, request_id: str = "audio-gen-req-1"):
app = FastAPI()
app.state.openai_serving_audio_generate = handler
app.state.engine_client = SimpleNamespace(
engine=SimpleNamespace(is_alive=lambda: False),
errored=True,
)
app.state.server = SimpleNamespace()
@app.middleware("http")
async def add_request_metadata(request: Request, call_next):
request.state.request_metadata = SimpleNamespace(request_id=request_id)
return await call_next(request)
app.add_api_route(
"/v1/audio/generate",
api_server_module.create_audio_generate,
methods=["POST"],
response_model=None,
)
return app
# Request Validation (Pydantic model)
class TestRequestValidation:
"""Validate OpenAICreateAudioGenerateRequest pydantic constraints."""
@@ -472,6 +498,35 @@ class TestErrorHandling:
assert "Audio generation failed" in resp.error.message
@pytest.mark.parametrize(
("exc", "expected_message", "expected_stage_id"),
[
(OmniEngineDeadError("engine dead", error_stage_id=2), "engine dead", 2),
(EngineGenerateError("engine generate failed"), "engine generate failed", None),
],
)
def test_api_server_engine_error_response_includes_request_and_stage_id(
self,
exc,
expected_message,
expected_stage_id,
):
handler = MagicMock()
handler.create_audio_generate = AsyncMock(side_effect=exc)
app = _make_api_server_test_app(handler)
with patch.object(api_server_module, "terminate_if_errored") as terminate_mock:
with TestClient(app) as client:
response = client.post("/v1/audio/generate", json={"input": "Hello"})
assert response.status_code == 500
payload = response.json()
assert payload["error"]["message"] == expected_message
assert payload["error"]["code"] == 500
assert payload["error"]["request_id"] == "audio-gen-req-1"
assert payload["error"]["error_stage_id"] == expected_stage_id
terminate_mock.assert_called_once()
# End-to-End via TestClient
class TestAudioGenerateAPI:
@@ -1164,6 +1164,8 @@ async def create_audio_generate(request: OpenAICreateAudioGenerateRequest, raw_r
status_code=result.error.code if result.error else 400,
)
return result
except (EngineGenerateError, EngineDeadError) as exc:
return _create_engine_error_json_response(raw_request, exc)
except Exception as e:
raise HTTPException(status_code=HTTPStatus.INTERNAL_SERVER_ERROR.value, detail=str(e)) from e