148 lines
4.4 KiB
Python
148 lines
4.4 KiB
Python
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
from k1link.artifact_gateway import (
|
|
ArtifactGateway,
|
|
CentralArtifactStore,
|
|
LocalArtifactCache,
|
|
)
|
|
from k1link.sessions.recording import SessionRecordingMaterializer
|
|
from k1link.web.runtime_readiness import (
|
|
BackgroundReconcilerReadiness,
|
|
build_runtime_readiness,
|
|
)
|
|
|
|
|
|
def _document(
|
|
tmp_path: Path,
|
|
*,
|
|
gateway: ArtifactGateway | None,
|
|
reconciler: BackgroundReconcilerReadiness,
|
|
) -> dict[str, object]:
|
|
return build_runtime_readiness(
|
|
version="test",
|
|
plugin_runtime_health=({"status": "ready"},),
|
|
recording_materializer=SessionRecordingMaterializer(
|
|
tmp_path / "data",
|
|
exporter=lambda _source, _destination: {},
|
|
free_space_reserve_bytes=0,
|
|
),
|
|
artifact_gateway=gateway,
|
|
map_gateway_configured=False,
|
|
ffmpeg_available=True,
|
|
ffprobe_available=True,
|
|
reconciler=reconciler,
|
|
)
|
|
|
|
|
|
def test_runtime_readiness_reports_shared_store_and_bounded_cache(
|
|
tmp_path: Path,
|
|
) -> None:
|
|
central_root = tmp_path / "central"
|
|
gateway = ArtifactGateway(
|
|
CentralArtifactStore(central_root, create=True),
|
|
LocalArtifactCache(
|
|
tmp_path / "cache",
|
|
max_bytes=1024 * 1024,
|
|
free_space_reserve_bytes=0,
|
|
),
|
|
)
|
|
reconciler = BackgroundReconcilerReadiness()
|
|
reconciler.record_success()
|
|
|
|
document = _document(tmp_path, gateway=gateway, reconciler=reconciler)
|
|
|
|
assert document["ok"] is True
|
|
assert document["status"] == "ok"
|
|
assert document["readiness"] == {
|
|
"operational": True,
|
|
"optional_shared_artifacts": {
|
|
"required": False,
|
|
"configured": True,
|
|
"ready": True,
|
|
},
|
|
}
|
|
components = document["components"]
|
|
assert isinstance(components, dict)
|
|
assert components["recording_cache"]["max_bytes"] == 8 * 1024 * 1024 * 1024
|
|
assert components["artifact_store"]["status"] == "ready"
|
|
assert components["map_gateway"]["status"] == "optional"
|
|
|
|
|
|
def test_runtime_readiness_exposes_offline_cache_only_mode(
|
|
tmp_path: Path,
|
|
) -> None:
|
|
central_root = tmp_path / "central"
|
|
gateway = ArtifactGateway(
|
|
CentralArtifactStore(central_root, create=True),
|
|
LocalArtifactCache(
|
|
tmp_path / "cache",
|
|
max_bytes=1024 * 1024,
|
|
free_space_reserve_bytes=0,
|
|
),
|
|
)
|
|
central_root.rename(tmp_path / "central-offline")
|
|
reconciler = BackgroundReconcilerReadiness()
|
|
reconciler.record_success()
|
|
|
|
document = _document(tmp_path, gateway=gateway, reconciler=reconciler)
|
|
|
|
assert document["ok"] is True
|
|
assert document["status"] == "ok"
|
|
assert document["readiness"] == {
|
|
"operational": True,
|
|
"optional_shared_artifacts": {
|
|
"required": False,
|
|
"configured": True,
|
|
"ready": False,
|
|
},
|
|
}
|
|
components = document["components"]
|
|
assert isinstance(components, dict)
|
|
assert components["artifact_store"]["status"] == "offline-cache-only"
|
|
|
|
|
|
def test_runtime_readiness_treats_standalone_as_complete_local_contour(
|
|
tmp_path: Path,
|
|
) -> None:
|
|
reconciler = BackgroundReconcilerReadiness()
|
|
reconciler.record_success()
|
|
|
|
document = _document(tmp_path, gateway=None, reconciler=reconciler)
|
|
|
|
assert document["ok"] is True
|
|
assert document["status"] == "ok"
|
|
assert document["readiness"] == {
|
|
"operational": True,
|
|
"optional_shared_artifacts": {
|
|
"required": False,
|
|
"configured": False,
|
|
"ready": False,
|
|
},
|
|
}
|
|
components = document["components"]
|
|
assert isinstance(components, dict)
|
|
assert components["artifact_store"] == {
|
|
"mode": "standalone",
|
|
"status": "not-configured",
|
|
"central_available": None,
|
|
}
|
|
|
|
|
|
def test_runtime_readiness_fails_after_repeated_reconciler_errors(
|
|
tmp_path: Path,
|
|
) -> None:
|
|
reconciler = BackgroundReconcilerReadiness()
|
|
for _ in range(3):
|
|
reconciler.record_failure(OSError("private detail"))
|
|
|
|
document = _document(tmp_path, gateway=None, reconciler=reconciler)
|
|
|
|
assert document["ok"] is False
|
|
assert document["status"] == "unavailable"
|
|
components = document["components"]
|
|
assert isinstance(components, dict)
|
|
assert components["background_reconciler"]["last_failure_type"] == "OSError"
|
|
assert "private detail" not in str(document)
|