fix(node.http): avoid exhausting ephemeral ports in backfill logic

This commit is contained in:
⟣ €₥ℵ∪ℓ ⟢ 2026-04-23 16:47:36 -04:00
parent 44043b8c1a
commit 2a780a4435
No known key found for this signature in database
GPG Key ID: F57D7381FBAFD773
3 changed files with 20 additions and 21 deletions

View File

@ -84,7 +84,7 @@ B <--> D["Database<br/>(SQLite)"]
2. Run the block explorer:
```bash
uv run python -m main
PYTHONPATH=src uv run python -m main
```
By default, this will try to connect to a local Node running on port 18080.
@ -95,7 +95,7 @@ By default, this will try to connect to a local Node running on port 18080.
- If you want to run the Explorer without a Node, make sure to set the `NBE_NODE_API` environment variable to `fake`:
1. ```bash
NBE_NODE_API=fake uv run python -m main
PYTHONPATH=src NBE_NODE_API=fake uv run python -m main
```
2. ```bash
docker run -e NBE_NODE_API=fake -p 8000:8000 nomos-block-explorer

View File

@ -78,25 +78,22 @@ class HttpNodeApi(NodeApi):
async def get_block_by_hash(self, block_hash: str) -> Optional[BlockSerializer]:
url = urljoin(self.base_url, self.ENDPOINT_BLOCK_BY_HASH)
response = requests.post(
url,
auth=self.authentication,
timeout=60,
json=block_hash,
)
if response.status_code == 404:
return None
response.raise_for_status()
json_data = response.json()
if json_data is None:
logger.warning(f"Block {block_hash} returned null from API")
return None
block = BlockSerializer.model_validate(json_data)
# The storage endpoint doesn't include the block hash in the response,
# so we set it from the request body
if not block.header.hash:
block.header.hash = bytes.fromhex(block_hash)
return block
auth = self.authentication.map(lambda _auth: _auth.for_httpx()).unwrap_or(None)
async with httpx.AsyncClient(timeout=60, auth=auth) as client:
response = await client.post(url, json=block_hash)
if response.status_code == 404:
return None
response.raise_for_status()
json_data = response.json()
if json_data is None:
logger.warning(f"Block {block_hash} returned null from API")
return None
block = BlockSerializer.model_validate(json_data)
# The storage endpoint doesn't include the block hash in the response,
# so we set it from the request body
if not block.header.hash:
block.header.hash = bytes.fromhex(block_hash)
return block
async def get_blocks_stream(self) -> AsyncIterator[BlockSerializer]:
url = urljoin(self.base_url, self.ENDPOINT_BLOCKS_STREAM)

View File

@ -31,6 +31,7 @@ async def backfill_to_lib(app: "NBE") -> None:
info = await app.state.node_api.get_info()
logger.info(f"Node info: LIB={info.lib}, tip={info.tip}, slot={info.slot}, height={info.height}")
logger.debug(f"Block {info.lib}...")
await backfill_chain_from_hash(app, info.lib)
return
@ -51,6 +52,7 @@ async def backfill_chain_from_hash(app: "NBE", block_hash: str) -> None:
while True:
# Check if we already have this block
logger.debug(f"Block {current_hash}...")
existing = await app.state.block_repository.get_by_hash(bytes.fromhex(current_hash))
if existing.is_some:
logger.debug(f"Block {current_hash[:16]}... already exists, stopping chain walk")