diff --git a/pigway_frame_flow/api/app.py b/pigway_frame_flow/api/app.py index b964b28..f1e3924 100644 --- a/pigway_frame_flow/api/app.py +++ b/pigway_frame_flow/api/app.py @@ -124,7 +124,7 @@ def create_app(settings=None, start_worker=True): app = FastAPI( title="Pigway Frame Flow API", docs_url=None, - version="0.1.2", + version="0.1.3", lifespan=lifespan, responses=error_responses, ) @@ -1000,7 +1000,7 @@ def create_app(settings=None, start_worker=True): ) def settings_view(): return SettingsView( - version="0.1.2", + version="0.1.3", mock=settings.mock, write_enabled=settings.write_enabled, api_key_configured=bool(settings.api_key) diff --git a/pigway_frame_flow/display/service.py b/pigway_frame_flow/display/service.py index 2337492..b55fe46 100644 --- a/pigway_frame_flow/display/service.py +++ b/pigway_frame_flow/display/service.py @@ -442,7 +442,7 @@ class DisplayService: "code": exc.code, "message": exc.message, "request_id": op["request_id"], - "details": {}, + "details": exc.details, } self.update( op["id"], "UNKNOWN" if uncertain else "FAILED", error=error @@ -861,7 +861,20 @@ class DisplayService: self.update( id, "COMPLETED" if confirmed else "FAILED", - {"image_id": device.current_content.id}, + op["result"], + error=None + if confirmed + else { + "code": E.DISPLAY_NOT_CONFIRMED + if op["action"] == "display" + else E.WRITE_RESULT_UNKNOWN, + "message": "Manually closed unconfirmed write; no write replayed", + "request_id": op["request_id"], + "details": { + "observed_image_id": device.current_content.id, + "previous_error": op["error"], + }, + }, ) resolved = True if confirmed and op["action"] == "display": diff --git a/pigway_frame_flow/drivers/kokonna/client.py b/pigway_frame_flow/drivers/kokonna/client.py index 55911a5..1e7c3d6 100644 --- a/pigway_frame_flow/drivers/kokonna/client.py +++ b/pigway_frame_flow/drivers/kokonna/client.py @@ -51,13 +51,30 @@ class SafeTransport: timeout=(5, 120 if endpoint == "/upload" else 30), allow_redirects=False, ) - except requests.RequestException: + except requests.RequestException as exc: + # Persist only fixed categories: exception text and download URLs may + # contain credentials. Unknown writes must still never be replayed. + category = next( + ( + label + for kind, label in ( + (requests.ConnectTimeout, "connect_timeout"), + (requests.ReadTimeout, "read_timeout"), + (requests.exceptions.SSLError, "tls_error"), + (requests.ConnectionError, "connection_error"), + (requests.Timeout, "timeout"), + ) + if isinstance(exc, kind) + ), + "request_error", + ) raise FlowError( E.WRITE_RESULT_UNKNOWN if write else E.CLOUD_UNAVAILABLE, "Cloud write outcome is unknown" if write else "Device cloud is unavailable", 502, + details={"transport_error": category}, ) from None if response.status_code != 200: code = ( @@ -73,6 +90,7 @@ class SafeTransport: code, "Device cloud request failed", 429 if code == E.RATE_LIMITED else 502, + details={"http_status": response.status_code}, ) if binary: if len(response.content) > 20 * 1024 * 1024: diff --git a/pigway_frame_flow/errors.py b/pigway_frame_flow/errors.py index ff10431..85785eb 100644 --- a/pigway_frame_flow/errors.py +++ b/pigway_frame_flow/errors.py @@ -23,6 +23,7 @@ class ErrorCode(StrEnum): class FlowError(Exception): - def __init__(self, code: ErrorCode, message: str, status: int = 400): + def __init__(self, code: ErrorCode, message: str, status: int = 400, details=None): self.code, self.message, self.status = code, message, status + self.details = details or {} super().__init__(message) diff --git a/pigway_frame_flow/models.py b/pigway_frame_flow/models.py index 04a86bf..cd0647a 100644 --- a/pigway_frame_flow/models.py +++ b/pigway_frame_flow/models.py @@ -336,7 +336,7 @@ class SettingsView(BaseModel): class Health(BaseModel): status: str - version: str = "0.1.2" + version: str = "0.1.3" class Readiness(BaseModel): @@ -366,7 +366,7 @@ class RestoreRequest(StrictModel): class Version(BaseModel): product: str = "Pigway Frame Flow" - version: str = "0.1.2" + version: str = "0.1.3" api_version: str = "v1" commit: str = "development" build_time: str = "unknown" diff --git a/pigway_frame_flow/web/index.html b/pigway_frame_flow/web/index.html index 5320e66..8f9698e 100644 --- a/pigway_frame_flow/web/index.html +++ b/pigway_frame_flow/web/index.html @@ -1,3 +1,3 @@