From e216f3a3834cd62c24a74e0b14859c977e9b2534 Mon Sep 17 00:00:00 2001 From: Aidar Date: Thu, 4 Apr 2024 20:33:14 +0300 Subject: [PATCH] Use backoff in wait scripts (#56) --- async_api/poetry.lock | 13 +++++++++++- async_api/pyproject.toml | 1 + .../tests/functional/utils/wait_for_api.py | 18 ++++++++--------- .../utils/wait_for_elasticsearch.py | 20 ++++++++++++------- .../tests/functional/utils/wait_for_redis.py | 15 ++++++++------ 5 files changed, 43 insertions(+), 24 deletions(-) diff --git a/async_api/poetry.lock b/async_api/poetry.lock index 68693db..ef1edc3 100644 --- a/async_api/poetry.lock +++ b/async_api/poetry.lock @@ -173,6 +173,17 @@ files = [ [package.dependencies] cryptography = "*" +[[package]] +name = "backoff" +version = "2.2.1" +description = "Function decoration for backoff and retry" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8"}, + {file = "backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba"}, +] + [[package]] name = "black" version = "24.3.0" @@ -2184,4 +2195,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "74e30cadfea42f56bf503b8195a54a947c4941e5175c0e089552e287e65f6fc6" +content-hash = "34d3f3e64752a7b94c24d519557b773c9de47f97f47acef71da176a81e4ae0c4" diff --git a/async_api/pyproject.toml b/async_api/pyproject.toml index aea7dc0..cecf537 100644 --- a/async_api/pyproject.toml +++ b/async_api/pyproject.toml @@ -33,6 +33,7 @@ coverage = "^7.4.4" httpx = "^0.27.0" polyfactory = "^2.15.0" faker = "^24.4.0" +backoff = "^2.2.1" [tool.black] # https://black.readthedocs.io/en/stable/usage_and_configuration/the_basics.html#configuration-via-a-file target-version = ["py312"] diff --git a/async_api/tests/functional/utils/wait_for_api.py b/async_api/tests/functional/utils/wait_for_api.py index dbe7eb3..d202e32 100644 --- a/async_api/tests/functional/utils/wait_for_api.py +++ b/async_api/tests/functional/utils/wait_for_api.py @@ -1,6 +1,6 @@ import logging -import time +import backoff import httpx from tests.functional.settings import settings @@ -9,17 +9,15 @@ logger = logging.getLogger(__name__) +@backoff.on_exception(backoff.expo, httpx.HTTPError, max_time=60) +def check_api_health(): + response = httpx.get(f"{settings.api_url}/health", timeout=1) + response.raise_for_status() + + def wait_for_api(): logger.info("Waiting for API: %s", settings.api_url) - while True: - try: - response = httpx.get(f"{settings.api_url}/health", timeout=1) - except httpx.HTTPError: - time.sleep(1) - continue - if response.status_code == 200: - break - time.sleep(1) + check_api_health() logger.info("API is ready") diff --git a/async_api/tests/functional/utils/wait_for_elasticsearch.py b/async_api/tests/functional/utils/wait_for_elasticsearch.py index cff1a5a..20aea13 100644 --- a/async_api/tests/functional/utils/wait_for_elasticsearch.py +++ b/async_api/tests/functional/utils/wait_for_elasticsearch.py @@ -1,21 +1,27 @@ import logging -import time -from elasticsearch import Elasticsearch +import backoff + +from elastic_transport import TransportError +from elasticsearch import ApiError, Elasticsearch from tests.functional.settings import settings from tests.functional.utils.logger import setup_logger +logging.getLogger("elastic_transport.transport").setLevel(logging.CRITICAL) + logger = logging.getLogger(__name__) -def wait_for_elasticsearch(): +@backoff.on_exception(backoff.expo, (ApiError, TransportError), max_time=60) +def check_elasticsearch_health(): es_client = Elasticsearch(settings.elasticsearch_host, request_timeout=1) + es_client.info() + + +def wait_for_elasticsearch(): logger.info("Waiting for elasticsearch: %s", settings.elasticsearch_host) - while True: - if es_client.ping(): - break - time.sleep(1) + check_elasticsearch_health() logger.info("Elasticsearch is ready") diff --git a/async_api/tests/functional/utils/wait_for_redis.py b/async_api/tests/functional/utils/wait_for_redis.py index e0a8c6f..a1c8fc9 100644 --- a/async_api/tests/functional/utils/wait_for_redis.py +++ b/async_api/tests/functional/utils/wait_for_redis.py @@ -1,5 +1,6 @@ import logging -import time + +import backoff from redis import Redis @@ -9,13 +10,15 @@ logger = logging.getLogger(__name__) -def wait_for_redis(): +@backoff.on_predicate(backoff.expo, max_time=60) +def check_redis_health(): redis = Redis.from_url(str(settings.redis_url), socket_timeout=1) + return redis.ping() + + +def wait_for_redis(): logger.info("Waiting for redis: %s", settings.redis_url) - while True: - if redis.ping(): - break - time.sleep(1) + check_redis_health() logger.info("Redis is ready")