Repository: exo-explore/exo
File: src/exo/worker/utils/net_profile.py (Python)

Code before:
import http.client
import time

from anyio import create_task_group, to_thread
from loguru import logger

from exo.shared.topology import Topology
from exo.shared.types.common import NodeId

BAD_STATUSLINE_ATTEMPTS = 3


async def check_reachability(
    target_ip: str,
    expected_node_id: NodeId,
    self_node_id: NodeId,
    out: dict[NodeId, set[str]],
) -> None:
    """Check if a node is reachable at the given IP and verify its identity."""

    # TODO: use an async http client
    def _fetch_remote_node_id(*, attempt: int = 0) -> NodeId | None:
        connection = http.client.HTTPConnection(target_ip, 52415, timeout=3)
        try:
            connection.request("GET", "/node_id")
            response = connection.getresponse()
            if response.status != 200:
                return None

            body = response.read().decode("utf-8").strip()

            # Strip quotes if present (JSON string response)
            if body.startswith('"') and body.endswith('"') and len(body) >= 2:
                body = body[1:-1]

            return NodeId(body) or None
        except OSError:
            return None
        except http.client.BadStatusLine:
            if attempt >= BAD_STATUSLINE_ATTEMPTS:
                logger.warning(
                    f"BadStatusLine from {target_ip}, after {attempt} attempts, assuming connection to {expected_node_id} has dropped"
                )
                return None
            time.sleep(1)
            return _fetch_remote_node_id(attempt=attempt + 1)
        except http.client.HTTPException:

Review comment (suggestion):
```suggestion
    def _fetch_remote_node_id(*, attempt: int = 1) -> NodeId | None:
```

This is off by one at the minute

Code after:
import http.client
import time

from anyio import create_task_group, to_thread
from loguru import logger

from exo.shared.topology import Topology
from exo.shared.types.common import NodeId

BAD_STATUSLINE_ATTEMPTS = 3


async def check_reachability(
    target_ip: str,
    expected_node_id: NodeId,
    self_node_id: NodeId,
    out: dict[NodeId, set[str]],
) -> None:
    """Check if a node is reachable at the given IP and verify its identity."""

    # TODO: use an async http client
    def _fetch_remote_node_id(*, attempt: int = 1) -> NodeId | None:
        connection = http.client.HTTPConnection(target_ip, 52415, timeout=3)
        try:
            connection.request("GET", "/node_id")
            response = connection.getresponse()
            if response.status != 200:
                return None

            body = response.read().decode("utf-8").strip()

            # Strip quotes if present (JSON string response)
            if body.startswith('"') and body.endswith('"') and len(body) >= 2:
                body = body[1:-1]

            return NodeId(body) or None
        except OSError:
            return None
        except http.client.BadStatusLine:
            if attempt >= BAD_STATUSLINE_ATTEMPTS:
                logger.warning(
                    f"BadStatusLine from {target_ip}, after {attempt} attempts, assuming connection to {expected_node_id} has dropped"
                )
                return None
            time.sleep(1)
            return _fetch_remote_node_id(attempt=attempt + 1)
        except http.client.HTTPException as e: