Skip to content

Commit 3aff410

Browse files
authored
ensure director has started before getting services (#2609)
1 parent 6e67a44 commit 3aff410

File tree

4 files changed

+27
-14
lines changed

4 files changed

+27
-14
lines changed

services/catalog/src/simcore_service_catalog/core/background_tasks.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,9 @@ async def sync_registry_task(app: FastAPI) -> None:
211211
"Unexpected error while syncing registry entries, restarting now..."
212212
)
213213
# wait a bit before retrying, so it does not block everything until the director is up
214-
await asyncio.sleep(app.state.settings.BACKGROUND_TASK_WAIT_AFTER_FAILURE)
214+
await asyncio.sleep(
215+
app.state.settings.CATALOG_BACKGROUND_TASK_WAIT_AFTER_FAILURE
216+
)
215217

216218

217219
async def start_registry_sync_task(app: FastAPI) -> None:

services/catalog/src/simcore_service_catalog/services/director.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,30 @@
66
import httpx
77
from fastapi import FastAPI, HTTPException
88
from starlette import status
9-
from tenacity import retry
9+
from tenacity._asyncio import AsyncRetrying
1010
from tenacity.before_sleep import before_sleep_log
1111
from tenacity.wait import wait_random
1212

1313
logger = logging.getLogger(__name__)
1414

1515
director_statup_retry_policy = dict(
16-
wait=wait_random(5, 10),
16+
wait=wait_random(1, 10),
1717
before_sleep=before_sleep_log(logger, logging.WARNING),
1818
reraise=True,
1919
)
2020

2121

22-
@retry(**director_statup_retry_policy)
2322
async def setup_director(app: FastAPI) -> None:
2423
if settings := app.state.settings.CATALOG_DIRECTOR:
2524
# init client-api
2625
logger.debug("Setup director at %s...", settings.base_url)
2726
director_client = DirectorApi(base_url=settings.base_url, app=app)
2827
# check that the director is accessible
29-
await director_client.is_responsive()
28+
async for attempt in AsyncRetrying(**director_statup_retry_policy):
29+
with attempt:
30+
if not await director_client.is_responsive():
31+
raise ValueError("Director-v0 is not responsive")
32+
logger.info("Connection with director-v0 established")
3033
app.state.director_api = director_client
3134

3235

@@ -130,9 +133,10 @@ async def put(self, path: str, body: Dict) -> Optional[Dict]:
130133

131134
async def is_responsive(self) -> bool:
132135
try:
136+
logger.debug("checking director-v0 is responsive")
133137
health_check_path: str = "/"
134-
result = await self.client.head(health_check_path)
138+
result = await self.client.head(health_check_path, timeout=1.0)
135139
result.raise_for_status()
136140
return True
137-
except (httpx.HTTPStatusError, httpx.RequestError):
141+
except (httpx.HTTPStatusError, httpx.RequestError, httpx.TimeoutException):
138142
return False

services/catalog/tests/unit/test_services_director.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66

77
import asyncio
8-
from typing import Dict, Iterator
8+
from typing import Dict, Iterable, Iterator
99

1010
import pytest
1111
import respx
@@ -28,10 +28,15 @@ def minimal_app(
2828

2929
app = init_app()
3030

31+
yield app
32+
33+
34+
@pytest.fixture()
35+
def client(minimal_app: FastAPI) -> Iterable[TestClient]:
3136
# NOTE: this way we ensure the events are run in the application
3237
# since it starts the app on a test server
33-
with TestClient(app):
34-
yield app
38+
with TestClient(minimal_app) as client:
39+
yield client
3540

3641

3742
@pytest.fixture
@@ -41,6 +46,7 @@ def mocked_director_service_api(minimal_app: FastAPI) -> MockRouter:
4146
assert_all_called=False,
4247
assert_all_mocked=True,
4348
) as respx_mock:
49+
respx_mock.head("/", name="healthcheck").respond(200, json={"health": "OK"})
4450
respx_mock.get("/services", name="list_services").respond(
4551
200, json={"data": ["one", "two"]}
4652
)
@@ -50,8 +56,9 @@ def mocked_director_service_api(minimal_app: FastAPI) -> MockRouter:
5056

5157
async def test_director_client_setup(
5258
loop: asyncio.AbstractEventLoop,
53-
minimal_app: FastAPI,
5459
mocked_director_service_api: MockRouter,
60+
minimal_app: FastAPI,
61+
client: TestClient,
5562
):
5663

5764
# gets director client as used in handlers

services/catalog/tests/unit/with_dbs/conftest.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import itertools
77
import random
8-
from typing import Any, Callable, Dict, Iterator, List, Tuple
8+
from typing import Any, Callable, Dict, Iterable, Iterator, List, Tuple
99

1010
import pytest
1111
import respx
@@ -34,14 +34,14 @@ def app(
3434
service_test_environ: None,
3535
postgres_db: sa.engine.Engine,
3636
postgres_host_config: Dict[str, str],
37-
) -> FastAPI:
37+
) -> Iterable[FastAPI]:
3838
monkeypatch.setenv("CATALOG_TRACING", "null")
3939
app = init_app()
4040
yield app
4141

4242

4343
@pytest.fixture
44-
def client(app: FastAPI) -> TestClient:
44+
def client(app: FastAPI) -> Iterable[TestClient]:
4545
with TestClient(app) as cli:
4646
# Note: this way we ensure the events are run in the application
4747
yield cli

0 commit comments

Comments
 (0)