refactor: use explicit dataclasses instead of ORM objects in service layer

Replace dict/ORM object returns with explicit dataclasses to fix
DetachedInstanceError when accessing ORM attributes after session closes.

- Add app/assets/services/schemas.py with AssetData, AssetInfoData,
  AssetDetailResult, and RegisterAssetResult dataclasses
- Update asset_management.py and ingest.py to return dataclasses
- Update manager.py to use attribute access on dataclasses
- Fix created_new to be False in create_asset_from_hash (content exists)
- Add DependencyMissingError for better blake3 missing error handling
- Update tests to use attribute access instead of dict subscripting

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Luke Mino-Altherr
2026-02-03 18:39:07 -08:00
parent 03070b1e9b
commit cff2f43bb8
8 changed files with 169 additions and 69 deletions

View File

@@ -12,6 +12,7 @@ from app.assets.api import schemas_in
from app.assets.api.schemas_in import (
AssetNotFoundError,
AssetValidationError,
DependencyMissingError,
HashMismatchError,
UploadError,
)
@@ -205,6 +206,8 @@ async def upload_asset(request: web.Request) -> web.Response:
return _build_error_response(404, "ASSET_NOT_FOUND", str(e))
except HashMismatchError as e:
return _build_error_response(400, "HASH_MISMATCH", str(e))
except DependencyMissingError as e:
return _build_error_response(503, "DEPENDENCY_MISSING", e.message)
except Exception:
logging.exception("process_upload failed for owner_id=%s", owner_id)
return _build_error_response(500, "INTERNAL", "Unexpected server error.")

View File

@@ -43,6 +43,14 @@ class HashMismatchError(Exception):
pass
class DependencyMissingError(Exception):
"""A required dependency is not installed."""
def __init__(self, message: str):
super().__init__(message)
self.message = message
@dataclass
class ParsedUpload:
"""Result of parsing a multipart upload request."""