Keep ambiguous or failed-transport canceljob responses retriable 🟩

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Daniel Roth 2026-07-07 15:36:15 +00:00
parent 157f9fc4b4
commit 007e561af5

View file

@ -172,6 +172,76 @@ def test_abandon_job_returns_rejection_from_the_shared_failure_envelope(
)
# --- abandon_job: ambiguous responses are retriable, never success or rejection ---
def test_abandon_job_raises_retriable_parse_error_on_a_malformed_response_body(
client: AbriClient, mock_session: MagicMock
) -> None:
# Arrange
mock_session.post.return_value.content = b"not xml at all <<<"
# Act / Assert
with pytest.raises(AbriResponseParseError):
client.abandon_job(_spec_example_abandon_request())
@pytest.mark.parametrize(
"body",
[
# A cancellation collection with no JobCancelled and no ErrorDetails:
# genuinely ambiguous, so a dead job never churns as success/rejection.
b"<Root><CancelJobs /></Root>",
b"<Root></Root>",
# JobCancelled present but missing its job_no.
b"<Root><CancelJobs><JobCancelled /></CancelJobs></Root>",
# ErrorDetails present but missing code or message.
b'<Root><CancelJobs /><ErrorDetails message="x" /></Root>',
b'<Root><CancelJobs /><ErrorDetails code="RelayError" /></Root>',
# The shared envelope, but not a failure document.
b"<response><success>true</success></response>",
b"<unexpected />",
],
)
def test_abandon_job_raises_retriable_parse_error_on_an_unexpectedly_shaped_response(
client: AbriClient, mock_session: MagicMock, body: bytes
) -> None:
# Arrange
mock_session.post.return_value.content = body
# Act / Assert
with pytest.raises(AbriResponseParseError):
client.abandon_job(_spec_example_abandon_request())
# --- abandon_job: transport failures ---
def test_abandon_job_raises_transport_error_on_http_error_status(
client: AbriClient, mock_session: MagicMock
) -> None:
# Arrange
mock_session.post.return_value.content = b"<html>Server Error</html>"
mock_session.post.return_value.raise_for_status.side_effect = requests.HTTPError(
"500 Server Error"
)
# Act / Assert
with pytest.raises(AbriTransportError):
client.abandon_job(_spec_example_abandon_request())
def test_abandon_job_raises_transport_error_when_the_relay_is_unreachable(
client: AbriClient, mock_session: MagicMock
) -> None:
# Arrange
mock_session.post.side_effect = requests.ConnectionError("connection refused")
# Act / Assert
with pytest.raises(AbriTransportError):
client.abandon_job(_spec_example_abandon_request())
# --- log_job: rejection ---