Skip to content

Commit ceed902

Browse files
authored
fix: adds health check for indexer (#653)
Adds a health check for the indexer service to ensure it is ready before proceeding. This change introduces a generic function to wait for a service to become ready via health check. The changes modify the LocalNet startup process to wait for both algod and indexer to be healthy before considering the LocalNet fully started.
1 parent 60d7b21 commit ceed902

20 files changed

+77
-14
lines changed

poetry.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/algokit/core/sandbox.py

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ def up(self) -> None:
202202
bad_return_code_error_message="Failed to start LocalNet",
203203
)
204204
logger.debug("AlgoKit LocalNet started, waiting for health check")
205-
if _wait_for_algod():
205+
if _wait_for_algod() and _wait_for_indexer():
206206
logger.info("Started; execute `algokit explore` to explore LocalNet in a web user interface.")
207207
else:
208208
logger.warning("AlgoKit LocalNet failed to return a successful health check")
@@ -305,34 +305,63 @@ def check_docker_compose_for_new_image_versions(self) -> None:
305305
DEFAULT_ALGOD_PORT = 4001
306306
DEFAULT_INDEXER_PORT = 8980
307307
DEFAULT_WAIT_FOR_ALGOD = 60
308+
DEFAULT_WAIT_FOR_INDEXER = 60
308309
DEFAULT_HEALTH_TIMEOUT = 1
309310
ALGOD_HEALTH_URL = f"{DEFAULT_ALGOD_SERVER}:{DEFAULT_ALGOD_PORT}/v2/status"
311+
INDEXER_HEALTH_URL = f"{DEFAULT_INDEXER_SERVER}:{DEFAULT_INDEXER_PORT}/health"
310312
INDEXER_IMAGE = "algorand/indexer:latest"
311313
ALGORAND_IMAGE = "algorand/algod:latest"
312314
CONDUIT_IMAGE = "algorand/conduit:latest"
313315

314316

315-
def _wait_for_algod() -> bool:
316-
end_time = time.time() + DEFAULT_WAIT_FOR_ALGOD
317+
def _wait_for_service(
318+
url: str,
319+
token: str,
320+
header_name: str,
321+
service_name: str,
322+
timeout: int = DEFAULT_WAIT_FOR_ALGOD,
323+
) -> bool:
324+
"""Generic function to wait for a service to become ready via health check."""
325+
end_time = time.time() + timeout
317326
last_exception: httpx.RequestError | None = None
318327
while time.time() < end_time:
319328
try:
320-
health = httpx.get(
321-
ALGOD_HEALTH_URL, timeout=DEFAULT_HEALTH_TIMEOUT, headers={"X-Algo-API-Token": DEFAULT_ALGOD_TOKEN}
322-
)
329+
health = httpx.get(url, timeout=DEFAULT_HEALTH_TIMEOUT, headers={header_name: token})
323330
except httpx.RequestError as ex:
324331
last_exception = ex
325332
else:
326333
if health.is_success:
327-
logger.debug("AlgoKit LocalNet health check successful, algod is ready")
334+
logger.debug(f"AlgoKit LocalNet health check successful, {service_name} is ready")
328335
return True
329336
logger.debug(f"AlgoKit LocalNet health check returned {health.status_code}, waiting")
330337
time.sleep(DEFAULT_HEALTH_TIMEOUT)
331338
if last_exception:
332-
logger.debug("AlgoKit LocalNet health request failed", exc_info=last_exception)
339+
logger.debug(f"AlgoKit LocalNet health request failed for {service_name}", exc_info=last_exception)
333340
return False
334341

335342

343+
def _wait_for_algod() -> bool:
344+
"""Wait for algod service to become ready."""
345+
return _wait_for_service(
346+
ALGOD_HEALTH_URL,
347+
DEFAULT_ALGOD_TOKEN,
348+
"X-Algo-API-Token",
349+
"algod",
350+
DEFAULT_WAIT_FOR_ALGOD,
351+
)
352+
353+
354+
def _wait_for_indexer() -> bool:
355+
"""Wait for indexer service to become ready."""
356+
return _wait_for_service(
357+
INDEXER_HEALTH_URL,
358+
DEFAULT_INDEXER_TOKEN,
359+
"X-Indexer-API-Token",
360+
"indexer",
361+
DEFAULT_WAIT_FOR_INDEXER,
362+
)
363+
364+
336365
def get_config_json() -> str:
337366
return (
338367
'{ "Version": 12, "GossipFanout": 1, "EndpointAddress": "0.0.0.0:8080", "DNSBootstrapID": "",'

tests/goal/test_goal.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import pytest
66
from algokit.core.sandbox import (
77
ALGOD_HEALTH_URL,
8+
INDEXER_HEALTH_URL,
89
get_algod_network_template,
910
get_config_json,
1011
get_docker_compose_yml,
@@ -28,6 +29,7 @@ def _normalize_output(output: str) -> str:
2829
@pytest.fixture()
2930
def _health_success(httpx_mock: HTTPXMock) -> None:
3031
httpx_mock.add_response(url=ALGOD_HEALTH_URL)
32+
httpx_mock.add_response(url=INDEXER_HEALTH_URL)
3133

3234

3335
@pytest.fixture()

tests/goal/test_goal.test_goal_console_algod_not_created.approved.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ DEBUG: Running '{container_engine} compose up --detach --quiet-pull --wait' in '
1313
DEBUG: AlgoKit LocalNet started, waiting for health check
1414
HTTP Request: GET http://localhost:4001/v2/status "HTTP/1.1 200 OK"
1515
DEBUG: AlgoKit LocalNet health check successful, algod is ready
16+
HTTP Request: GET http://localhost:8980/health "HTTP/1.1 200 OK"
17+
DEBUG: AlgoKit LocalNet health check successful, indexer is ready
1618
Started; execute `algokit explore` to explore LocalNet in a web user interface.
1719
Opening Bash console on the algod node; execute `exit` to return to original console
1820
DEBUG: Running '{container_engine} exec -it -w /root algokit_sandbox_algod bash' in '{current_working_directory}'

tests/localnet/conftest.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import json
22

33
import pytest
4-
from algokit.core.sandbox import ALGOD_HEALTH_URL, ALGORAND_IMAGE, INDEXER_IMAGE
4+
from algokit.core.sandbox import ALGOD_HEALTH_URL, ALGORAND_IMAGE, INDEXER_HEALTH_URL, INDEXER_IMAGE
55
from pytest_httpx import HTTPXMock
66
from pytest_mock import MockerFixture
77

@@ -12,12 +12,14 @@
1212
@pytest.fixture(autouse=True)
1313
def _algod_health_fast_timings(mocker: MockerFixture) -> None:
1414
mocker.patch("algokit.core.sandbox.DEFAULT_WAIT_FOR_ALGOD", 0.1)
15+
mocker.patch("algokit.core.sandbox.DEFAULT_WAIT_FOR_INDEXER", 0.1)
1516
mocker.patch("algokit.core.sandbox.DEFAULT_HEALTH_TIMEOUT", 0.1)
1617

1718

1819
@pytest.fixture()
1920
def _health_success(httpx_mock: HTTPXMock) -> None:
2021
httpx_mock.add_response(url=ALGOD_HEALTH_URL)
22+
httpx_mock.add_response(url=INDEXER_HEALTH_URL)
2123

2224

2325
@pytest.fixture()

tests/localnet/test_localnet_reset.test_localnet_reset_with_existing_sandbox_with_out_of_date_config.approved.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ docker: STDERR
2323
DEBUG: AlgoKit LocalNet started, waiting for health check
2424
HTTP Request: GET http://localhost:4001/v2/status "HTTP/1.1 200 OK"
2525
DEBUG: AlgoKit LocalNet health check successful, algod is ready
26+
HTTP Request: GET http://localhost:8980/health "HTTP/1.1 200 OK"
27+
DEBUG: AlgoKit LocalNet health check successful, indexer is ready
2628
Started; execute `algokit explore` to explore LocalNet in a web user interface.
2729

2830
{app_config}/sandbox/docker-compose.yml

tests/localnet/test_localnet_reset.test_localnet_reset_with_existing_sandbox_with_up_to_date_config.approved.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,6 @@ docker: STDERR
2222
DEBUG: AlgoKit LocalNet started, waiting for health check
2323
HTTP Request: GET http://localhost:4001/v2/status "HTTP/1.1 200 OK"
2424
DEBUG: AlgoKit LocalNet health check successful, algod is ready
25+
HTTP Request: GET http://localhost:8980/health "HTTP/1.1 200 OK"
26+
DEBUG: AlgoKit LocalNet health check successful, indexer is ready
2527
Started; execute `algokit explore` to explore LocalNet in a web user interface.

tests/localnet/test_localnet_reset.test_localnet_reset_with_existing_sandbox_with_up_to_date_config_with_pull.approved.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,6 @@ docker: STDERR
2020
DEBUG: AlgoKit LocalNet started, waiting for health check
2121
HTTP Request: GET http://localhost:4001/v2/status "HTTP/1.1 200 OK"
2222
DEBUG: AlgoKit LocalNet health check successful, algod is ready
23+
HTTP Request: GET http://localhost:8980/health "HTTP/1.1 200 OK"
24+
DEBUG: AlgoKit LocalNet health check successful, indexer is ready
2325
Started; execute `algokit explore` to explore LocalNet in a web user interface.

tests/localnet/test_localnet_reset.test_localnet_reset_with_named_sandbox_config.approved.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,6 @@ docker: STDERR
1616
DEBUG: AlgoKit LocalNet started, waiting for health check
1717
HTTP Request: GET http://localhost:4001/v2/status "HTTP/1.1 200 OK"
1818
DEBUG: AlgoKit LocalNet health check successful, algod is ready
19+
HTTP Request: GET http://localhost:8980/health "HTTP/1.1 200 OK"
20+
DEBUG: AlgoKit LocalNet health check successful, indexer is ready
1921
Started; execute `algokit explore` to explore LocalNet in a web user interface.

tests/localnet/test_localnet_reset.test_localnet_reset_without_existing_sandbox.approved.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ docker: STDERR
1414
DEBUG: AlgoKit LocalNet started, waiting for health check
1515
HTTP Request: GET http://localhost:4001/v2/status "HTTP/1.1 200 OK"
1616
DEBUG: AlgoKit LocalNet health check successful, algod is ready
17+
HTTP Request: GET http://localhost:8980/health "HTTP/1.1 200 OK"
18+
DEBUG: AlgoKit LocalNet health check successful, indexer is ready
1719
Started; execute `algokit explore` to explore LocalNet in a web user interface.
1820
----
1921
{app_config}/sandbox/docker-compose.yml:

0 commit comments

Comments
 (0)