updated execpetion handling

This commit is contained in:
SwiftyOS
2024-11-11 09:13:27 +01:00
parent aa5d304a2e
commit e8eda51b27
5 changed files with 92 additions and 64 deletions

View File

@@ -1,12 +1,12 @@
import logging
import backend.server.v2.store.exceptions
import backend.server.v2.store.model
import prisma.enums
import prisma.errors
import prisma.models
import prisma.types
import backend.server.v2.store.model
logger = logging.getLogger(__name__)
@@ -84,7 +84,7 @@ async def get_store_agents(
)
except Exception as e:
logger.error(f"Error getting store agents: {str(e)}")
raise
raise backend.server.v2.store.exceptions.DatabaseError("Failed to fetch store agents") from e
async def get_store_agent_details(
@@ -99,7 +99,7 @@ async def get_store_agent_details(
if not agent:
logger.warning(f"Agent not found: {username}/{agent_name}")
raise prisma.errors.RecordNotFoundError("Agent not found")
raise backend.server.v2.store.exceptions.AgentNotFoundError(f"Agent {username}/{agent_name} not found")
logger.debug(f"Found agent details for {username}/{agent_name}")
return backend.server.v2.store.model.StoreAgentDetails(
@@ -116,9 +116,11 @@ async def get_store_agent_details(
rating=agent.rating,
versions=agent.versions,
)
except backend.server.v2.store.exceptions.AgentNotFoundError:
raise
except Exception as e:
logger.error(f"Error getting store agent details: {str(e)}")
raise
raise backend.server.v2.store.exceptions.DatabaseError("Failed to fetch agent details") from e
async def get_store_creators(
@@ -197,7 +199,7 @@ async def get_store_creators(
)
except Exception as e:
logger.error(f"Error getting store creators: {str(e)}")
raise
raise backend.server.v2.store.exceptions.DatabaseError("Failed to fetch store creators") from e
async def get_store_creator_details(
@@ -213,7 +215,7 @@ async def get_store_creator_details(
if not creator:
logger.warning(f"Creator not found: {username}")
raise prisma.errors.RecordNotFoundError(f"Creator {username} not found")
raise backend.server.v2.store.exceptions.CreatorNotFoundError(f"Creator {username} not found")
logger.debug(f"Found creator details for {username}")
return backend.server.v2.store.model.CreatorDetails(
@@ -226,9 +228,11 @@ async def get_store_creator_details(
agent_runs=creator.agent_runs,
top_categories=creator.top_categories,
)
except backend.server.v2.store.exceptions.CreatorNotFoundError:
raise
except Exception as e:
logger.error(f"Error getting store creator details: {str(e)}")
raise
raise backend.server.v2.store.exceptions.DatabaseError("Failed to fetch creator details") from e
async def get_store_submissions(
@@ -335,7 +339,7 @@ async def create_store_submission(
logger.warning(
f"Agent not found for user {user_id}: {agent_id} v{agent_version}"
)
raise prisma.errors.RecordNotFoundError("Agent not found for this user")
raise backend.server.v2.store.exceptions.AgentNotFoundError("Agent not found for this user")
listing = await prisma.models.StoreListing.prisma().find_first(
where=prisma.types.StoreListingWhereInput(
@@ -344,7 +348,7 @@ async def create_store_submission(
)
if listing is not None:
logger.warning(f"Listing already exists for agent {agent_id}")
raise Exception("Listing already exists")
raise backend.server.v2.store.exceptions.ListingExistsError("Listing already exists for this agent")
# Create the store listing
listing = await prisma.models.StoreListing.prisma().create(
@@ -380,9 +384,11 @@ async def create_store_submission(
rating=0.0,
)
except (backend.server.v2.store.exceptions.AgentNotFoundError, backend.server.v2.store.exceptions.ListingExistsError):
raise
except prisma.errors.PrismaError as e:
logger.error(f"Database error creating store submission: {str(e)}")
raise Exception("Failed to create store submission")
raise backend.server.v2.store.exceptions.DatabaseError("Failed to create store submission") from e
async def update_profile(
@@ -449,7 +455,7 @@ async def update_profile(
)
if updated_profile is None:
logger.error(f"Failed to update profile for user {user_id}")
raise Exception("Failed to update profile")
raise backend.server.v2.store.exceptions.DatabaseError("Failed to update profile")
return backend.server.v2.store.model.CreatorDetails(
name=updated_profile.name,
@@ -464,4 +470,4 @@ async def update_profile(
except prisma.errors.PrismaError as e:
logger.error(f"Database error updating profile: {str(e)}")
raise Exception("Failed to update profile")
raise backend.server.v2.store.exceptions.DatabaseError("Failed to update profile") from e

View File

@@ -1,12 +1,11 @@
from datetime import datetime
import backend.server.v2.store.db as db
import prisma.errors
import prisma.models
import pytest
from prisma import Prisma, register
import backend.server.v2.store.db as db
from backend.server.v2.store.model import CreatorDetails
from prisma import Prisma, register
@pytest.fixture(autouse=True)

View File

@@ -0,0 +1,58 @@
class MediaUploadError(Exception):
"""Base exception for media upload errors"""
pass
class InvalidFileTypeError(MediaUploadError):
"""Raised when file type is not supported"""
pass
class FileSizeTooLargeError(MediaUploadError):
"""Raised when file size exceeds maximum limit"""
pass
class FileReadError(MediaUploadError):
"""Raised when there's an error reading the file"""
pass
class StorageConfigError(MediaUploadError):
"""Raised when storage configuration is invalid"""
pass
class StorageUploadError(MediaUploadError):
"""Raised when upload to storage fails"""
pass
class StoreError(Exception):
"""Base exception for store-related errors"""
pass
class AgentNotFoundError(StoreError):
"""Raised when an agent is not found"""
pass
class CreatorNotFoundError(StoreError):
"""Raised when a creator is not found"""
pass
class ListingExistsError(StoreError):
"""Raised when trying to create a listing that already exists"""
pass
class DatabaseError(StoreError):
"""Raised when there is an error interacting with the database"""
pass

View File

@@ -2,6 +2,7 @@ import logging
import os
import uuid
import backend.server.v2.store.exceptions
import fastapi
import supabase
@@ -12,49 +13,13 @@ ALLOWED_VIDEO_TYPES = {"video/mp4", "video/webm"}
MAX_FILE_SIZE = 50 * 1024 * 1024 # 50MB
class MediaUploadError(Exception):
"""Base exception for media upload errors"""
pass
class InvalidFileTypeError(MediaUploadError):
"""Raised when file type is not supported"""
pass
class FileSizeTooLargeError(MediaUploadError):
"""Raised when file size exceeds maximum limit"""
pass
class FileReadError(MediaUploadError):
"""Raised when there's an error reading the file"""
pass
class StorageConfigError(MediaUploadError):
"""Raised when storage configuration is invalid"""
pass
class StorageUploadError(MediaUploadError):
"""Raised when upload to storage fails"""
pass
async def upload_media(user_id: str, file: fastapi.UploadFile) -> str:
try:
supabase_url = os.environ["SUPABASE_URL"]
supabase_key = os.environ["SUPABASE_KEY"]
except KeyError as e:
logger.error(f"Missing required environment variable: {str(e)}")
raise StorageConfigError("Missing storage configuration") from e
raise backend.server.v2.store.exceptions.StorageConfigError("Missing storage configuration") from e
try:
# Validate file type
@@ -64,7 +29,7 @@ async def upload_media(user_id: str, file: fastapi.UploadFile) -> str:
and content_type not in ALLOWED_VIDEO_TYPES
):
logger.warning(f"Invalid file type attempted: {content_type}")
raise InvalidFileTypeError(
raise backend.server.v2.store.exceptions.InvalidFileTypeError(
f"File type not supported. Must be jpeg, png, gif, webp, mp4 or webm. Content type: {content_type}"
)
@@ -77,12 +42,12 @@ async def upload_media(user_id: str, file: fastapi.UploadFile) -> str:
file_size += len(chunk)
if file_size > MAX_FILE_SIZE:
logger.warning(f"File size too large: {file_size} bytes")
raise FileSizeTooLargeError("File too large. Maximum size is 50MB")
except FileSizeTooLargeError:
raise backend.server.v2.store.exceptions.FileSizeTooLargeError("File too large. Maximum size is 50MB")
except backend.server.v2.store.exceptions.FileSizeTooLargeError:
raise
except Exception as e:
logger.error(f"Error reading file chunks: {str(e)}")
raise FileReadError("Failed to read uploaded file") from e
raise backend.server.v2.store.exceptions.FileReadError("Failed to read uploaded file") from e
# Reset file pointer
await file.seek(0)
@@ -115,10 +80,10 @@ async def upload_media(user_id: str, file: fastapi.UploadFile) -> str:
except Exception as e:
logger.error(f"Supabase storage error: {str(e)}")
raise StorageUploadError("Failed to upload file to storage") from e
raise backend.server.v2.store.exceptions.StorageUploadError("Failed to upload file to storage") from e
except MediaUploadError:
except backend.server.v2.store.exceptions.MediaUploadError:
raise
except Exception as e:
logger.exception("Unexpected error in upload_media")
raise MediaUploadError("Unexpected error during media upload") from e
raise backend.server.v2.store.exceptions.MediaUploadError("Unexpected error during media upload") from e

View File

@@ -1,12 +1,12 @@
import io
import unittest.mock
import backend.server.v2.store.exceptions
import backend.server.v2.store.media
import fastapi
import pytest
import starlette.datastructures
import backend.server.v2.store.media
@pytest.fixture
def mock_env_vars(monkeypatch):
@@ -54,7 +54,7 @@ async def test_upload_media_invalid_type(mock_env_vars, mock_supabase):
headers=starlette.datastructures.Headers({"content-type": "text/plain"}),
)
with pytest.raises(backend.server.v2.store.media.InvalidFileTypeError):
with pytest.raises(backend.server.v2.store.exceptions.InvalidFileTypeError):
await backend.server.v2.store.media.upload_media("test-user", test_file)
mock_bucket = mock_supabase.storage.from_.return_value
@@ -68,7 +68,7 @@ async def test_upload_media_missing_credentials():
headers=starlette.datastructures.Headers({"content-type": "image/jpeg"}),
)
with pytest.raises(backend.server.v2.store.media.StorageConfigError):
with pytest.raises(backend.server.v2.store.exceptions.StorageConfigError):
await backend.server.v2.store.media.upload_media("test-user", test_file)