fix(dolt): A2 review — subprocess timeouts, stronger initial gate, HASHOF
Addresses the A2 review:
1. Every dolt subprocess is now bounded by a hard timeout
(dolt_command_timeout_seconds, default 600s); on expiry the process is killed
and DoltError raised — a hung pull/sql can no longer pin the import
connection and advisory lock indefinitely. Tested (timeout + non-zero exit).
2. Initial-load validate is stronger: besides zero-future, an initial load now
requires a real forward horizon (>= 21d, under the ~35d observed on the
clone) AND universe coverage >= 50% (a broken symbol join can't seed a hollow
calendar). Subsequent runs keep the 50% collapse gate.
3. Revision uses DOLT_HASHOF('HEAD') — formally HEAD, not dolt_log-by-timestamp.
4. Free-disk floor raised 2 GB -> 5 GB (safe headroom over the ~1.7 GB clone).
Full suite 702 passed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
"""Tests for the async dolt subprocess wrapper's failure handling.
|
||||
|
||||
Uses the Python interpreter as a stand-in subprocess (cross-platform, no dolt
|
||||
needed) to prove a non-zero exit and a hung command both raise DoltError — the
|
||||
latter is what stops a hung pull from pinning the import connection + advisory
|
||||
lock forever.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from app.services import dolt_client
|
||||
from app.services.dolt_client import DoltError
|
||||
|
||||
|
||||
async def test_run_raises_on_nonzero_exit():
|
||||
with pytest.raises(DoltError) as exc:
|
||||
await dolt_client._run(
|
||||
sys.executable, ["-c", "import sys; sys.exit(3)"], cwd=Path.cwd(), timeout=30
|
||||
)
|
||||
assert "3" in str(exc.value)
|
||||
|
||||
|
||||
async def test_run_times_out_and_kills():
|
||||
start = time.monotonic()
|
||||
with pytest.raises(DoltError) as exc:
|
||||
await dolt_client._run(
|
||||
sys.executable,
|
||||
["-c", "import time; time.sleep(30)"],
|
||||
cwd=Path.cwd(),
|
||||
timeout=0.5,
|
||||
)
|
||||
elapsed = time.monotonic() - start
|
||||
assert "timed out" in str(exc.value)
|
||||
assert elapsed < 10 # killed promptly, not waited out
|
||||
|
||||
|
||||
async def test_run_returns_stdout_on_success():
|
||||
out = await dolt_client._run(
|
||||
sys.executable, ["-c", "print('hello')"], cwd=Path.cwd(), timeout=30
|
||||
)
|
||||
assert out.strip() == "hello"
|
||||
Reference in New Issue
Block a user