From c8b7376c2bd1e36ec8210bf343a4c645ed3819b9 Mon Sep 17 00:00:00 2001 From: Anartz Nuin Date: Thu, 19 Oct 2023 17:14:29 +0100 Subject: [PATCH] Retry on protocol error (#73) Retry request in batch client in the event of a httpx.ProtocolError exception. Prevents failures in rare events in which the server response causes httpx to raise protocol error --- CHANGELOG.md | 1 + requirements.txt | 1 + speechmatics/batch_client.py | 17 +++++++++++++---- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c93e75e..aa76bdb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] - Improve upload speeds for files submitted with the batch client +- Retry requests in batch client on httpx.ProtocolError ## [1.11.0] - 2023-08-25 diff --git a/requirements.txt b/requirements.txt index f211815..81777f3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ websockets>=10 httpx[http2]~=0.23 polling2~=0.5 toml~=0.10.2 +tenacity~=8.2.3 diff --git a/speechmatics/batch_client.py b/speechmatics/batch_client.py index 5e0f440..a8958ff 100644 --- a/speechmatics/batch_client.py +++ b/speechmatics/batch_client.py @@ -12,6 +12,7 @@ import httpx from polling2 import poll +from tenacity import retry, retry_if_exception_type, stop_after_attempt from speechmatics.exceptions import JobNotFoundException, TranscriptionError from speechmatics.helpers import get_version @@ -166,11 +167,19 @@ def send_request(self, method: str, path: str, **kwargs) -> httpx.Response: :raises httpx.HTTPError: When a request fails, raises an HTTPError """ + # pylint: disable=no-member - with self.api_client.stream(method, path, **kwargs) as response: - response.read() - response.raise_for_status() - return response + @retry( + stop=stop_after_attempt(2), + retry=retry_if_exception_type(httpx.RemoteProtocolError), + ) + def send(): + with self.api_client.stream(method, path, **kwargs) as response: + response.read() + response.raise_for_status() + return response + + return send() def list_jobs(self) -> List[Dict[str, Any]]: """