@@ -88,6 +88,11 @@ def test_get_exception() -> None:
8888 assert RequestHandler ._get_exception (422 ) == exceptions .ObjectUnprocessable
8989 assert RequestHandler ._get_exception (500 ) == exceptions .ServerError
9090 assert RequestHandler ._get_exception (503 ) == exceptions .ServiceUnavailable
91+ assert RequestHandler ._get_exception (501 ) == exceptions .ServerError
92+ assert RequestHandler ._get_exception (502 ) == exceptions .ServerError
93+ assert RequestHandler ._get_exception (504 ) == exceptions .ServerError
94+ assert RequestHandler ._get_exception (599 ) == exceptions .ServerError
95+ assert RequestHandler ._get_exception (418 ) == exceptions .TypesenseClientError
9196 assert RequestHandler ._get_exception (999 ) == exceptions .TypesenseClientError
9297
9398
@@ -460,6 +465,33 @@ def test_selects_next_available_node_on_timeout(
460465 assert len (respx .calls ) == 3
461466
462467
468+ @pytest .mark .parametrize ("status_code" , [500 , 502 , 503 , 504 ])
469+ def test_selects_next_available_node_on_5xx (
470+ fake_api_call : ApiCall ,
471+ status_code : int ,
472+ ) -> None :
473+ """Test that a 5xx response marks the node unhealthy and retries on the next one."""
474+ with respx .mock :
475+ respx .get ("http://nearest:8108/test" ).mock (
476+ return_value = httpx .Response (status_code , text = "Bad Gateway" )
477+ )
478+ respx .get ("http://node0:8108/test" ).mock (
479+ return_value = httpx .Response (200 , json = {"key" : "value" })
480+ )
481+
482+ response = fake_api_call .get (
483+ "/test" ,
484+ as_json = True ,
485+ entity_type = typing .Dict [str , str ],
486+ )
487+
488+ assert response == {"key" : "value" }
489+ assert respx .calls [0 ].request .url == "http://nearest:8108/test"
490+ assert respx .calls [1 ].request .url == "http://node0:8108/test"
491+ assert len (respx .calls ) == 2
492+ assert fake_api_call .config .nearest_node .healthy is False
493+
494+
463495def test_get_node_no_healthy_nodes (
464496 fake_api_call : ApiCall ,
465497 mocker : MockFixture ,
0 commit comments