fix: recover failed Gaussian project builds
This commit is contained in:
@@ -10,6 +10,7 @@ import pytest
|
||||
|
||||
from k1link.simulation.gaussian_pipeline_gateway import (
|
||||
BUILD_REQUEST_SCHEMA,
|
||||
GaussianArchiveUpload,
|
||||
GaussianPipelineGateway,
|
||||
GaussianPipelineGatewayError,
|
||||
GaussianPipelineIntegrityError,
|
||||
@@ -163,6 +164,7 @@ def test_gateway_uploads_and_normalizes_archive_with_tus(tmp_path: Path) -> None
|
||||
received.extend(request.content)
|
||||
return httpx.Response(204, headers={"Upload-Offset": str(len(received))})
|
||||
if request.method == "POST" and request.url.path == "/v1/ingests":
|
||||
assert request.extensions["timeout"]["read"] == 30 * 60.0
|
||||
submitted = json.loads(request.content)
|
||||
assert submitted["archive"] == {
|
||||
"upload_id": "archive-001",
|
||||
@@ -202,6 +204,36 @@ def test_gateway_uploads_and_normalizes_archive_with_tus(tmp_path: Path) -> None
|
||||
assert source.bundle_sha256 == bundle_sha
|
||||
|
||||
|
||||
def test_gateway_surfaces_bounded_provider_rejection_detail(tmp_path: Path) -> None:
|
||||
def handler(_request: httpx.Request) -> httpx.Response:
|
||||
return httpx.Response(
|
||||
400,
|
||||
json={
|
||||
"error": "archive_link",
|
||||
"message": "archive links are not supported",
|
||||
},
|
||||
)
|
||||
|
||||
with (
|
||||
GaussianPipelineGateway(
|
||||
"http://gaussian.test",
|
||||
_token_file(tmp_path),
|
||||
transport=httpx.MockTransport(handler),
|
||||
) as gateway,
|
||||
pytest.raises(
|
||||
GaussianPipelineGatewayError,
|
||||
match=r"HTTP 400.*archive links are not supported",
|
||||
),
|
||||
):
|
||||
gateway.normalize_archive(GaussianArchiveUpload(
|
||||
upload_id="archive-001",
|
||||
archive_name="source.rar",
|
||||
format="rar",
|
||||
sha256="a" * 64,
|
||||
byte_length=128,
|
||||
))
|
||||
|
||||
|
||||
def test_gateway_rejects_incomplete_lcc_bundle(tmp_path: Path) -> None:
|
||||
bundle = tmp_path / "bundle"
|
||||
bundle.mkdir()
|
||||
|
||||
@@ -228,6 +228,37 @@ def test_service_resumes_a_persisted_provider_job_without_reupload(tmp_path: Pat
|
||||
assert provider.submit_calls == 0
|
||||
|
||||
|
||||
def test_failed_project_retries_from_retained_source_and_releases_old_job(tmp_path: Path) -> None:
|
||||
store = SimulationProjectStore(tmp_path)
|
||||
project = store.create(
|
||||
name="Retry scene",
|
||||
scene_type="outdoor",
|
||||
source_kind="folder",
|
||||
files=_folder_files(),
|
||||
)
|
||||
_upload_all(store, project)
|
||||
store.begin_build(project["project_id"])
|
||||
store.update_processing(
|
||||
project["project_id"],
|
||||
status="processing",
|
||||
provider_job_id="gsp-20260826000000-deadbeef",
|
||||
provider_state="failed",
|
||||
progress={"completed_steps": 1, "total_steps": 4},
|
||||
bundle_sha256="d" * 64,
|
||||
)
|
||||
store.fail(project["project_id"], "provider failure")
|
||||
provider = _ReadyProvider()
|
||||
service = SimulationProjectService(store, provider_factory=lambda: provider) # type: ignore[arg-type]
|
||||
|
||||
queued = service.begin_build(project["project_id"])
|
||||
|
||||
assert provider.deleted == ["gsp-20260826000000-deadbeef"]
|
||||
assert queued["status"] == "queued"
|
||||
assert queued["error"] is None
|
||||
assert queued["provider"]["job_id"] is None
|
||||
assert queued["source"]["uploaded_byte_length"] == queued["source"]["total_byte_length"]
|
||||
|
||||
|
||||
def test_api_exposes_same_origin_resumable_upload_contract(tmp_path: Path) -> None:
|
||||
store = SimulationProjectStore(tmp_path)
|
||||
service = SimulationProjectService(store, provider_factory=lambda: None)
|
||||
|
||||
Reference in New Issue
Block a user