Skip to content

Commit 67cc6a6

Browse files
harsh1519harsh
andauthored
fix: optimize toggle_favourite endpoint performance (#1094)
* fix: optimize toggle_favourite endpoint performance Related to #977 * fix: guard against invalid metadata JSON * fix: add docstrings and improve error handling --------- Co-authored-by: harsh <shah.ha@media.net>
1 parent 27a9c6a commit 67cc6a6

2 files changed

Lines changed: 51 additions & 8 deletions

File tree

backend/app/database/images.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Standard library imports
22
import sqlite3
33
from typing import Any, List, Mapping, Tuple, TypedDict, Union, Optional
4+
import json
5+
46
from datetime import datetime
57

68
# App-specific imports
@@ -455,6 +457,36 @@ def db_toggle_image_favourite_status(image_id: str) -> bool:
455457
finally:
456458
conn.close()
457459

460+
def db_get_image_by_id(image_id: str) -> Optional[dict]:
461+
"""
462+
Get a single image by ID with its favorite status.
463+
"""
464+
conn = _connect()
465+
cursor = conn.cursor()
466+
try:
467+
cursor.execute("""
468+
SELECT id, path, folder_id, thumbnailPath, metadata, isTagged, isFavourite
469+
FROM images
470+
WHERE id = ?
471+
""", (image_id,))
472+
row = cursor.fetchone()
473+
if not row:
474+
return None
475+
try:
476+
metadata = json.loads(row[4]) if row[4] else {}
477+
except json.JSONDecodeError:
478+
metadata = {}
479+
return {
480+
"id": row[0],
481+
"path": row[1],
482+
"folder_id": row[2],
483+
"thumbnailPath": row[3],
484+
"metadata": metadata,
485+
"isTagged": bool(row[5]),
486+
"isFavourite": bool(row[6]),
487+
}
488+
finally:
489+
conn.close()
458490

459491
# ============================================================================
460492
# MEMORIES FEATURE - Location and Time-based Queries

backend/app/routes/images.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
from app.schemas.images import ErrorResponse
55
from app.utils.images import image_util_parse_metadata
66
from pydantic import BaseModel
7-
from app.database.images import db_toggle_image_favourite_status
7+
from app.database.images import db_toggle_image_favourite_status, db_get_image_by_id
88
from app.logging.setup_logging import get_logger
99

10+
1011
# Initialize logger
1112
logger = get_logger(__name__)
1213
router = APIRouter()
@@ -97,27 +98,37 @@ class ToggleFavouriteRequest(BaseModel):
9798

9899
@router.post("/toggle-favourite")
99100
def toggle_favourite(req: ToggleFavouriteRequest):
101+
"""
102+
Toggle the favorite status of an image.
103+
"""
100104
image_id = req.image_id
101105
try:
102106
success = db_toggle_image_favourite_status(image_id)
103107
if not success:
104108
raise HTTPException(
105-
status_code=404, detail="Image not found or failed to toggle"
109+
status_code=status.HTTP_404_NOT_FOUND,
110+
detail="Image not found or failed to toggle"
106111
)
107112
# Fetch updated status to return
108-
image = next(
109-
(img for img in db_get_all_images() if img["id"] == image_id), None
110-
)
113+
image = db_get_image_by_id(image_id)
114+
if not image:
115+
raise HTTPException(
116+
status_code=status.HTTP_404_NOT_FOUND,
117+
detail="Image not found after toggle"
118+
)
111119
return {
112120
"success": True,
113121
"image_id": image_id,
114122
"isFavourite": image.get("isFavourite", False),
115123
}
116-
124+
except HTTPException:
125+
raise # Re-raise HTTPExceptions to preserve status codes
117126
except Exception as e:
118127
logger.error(f"error in /toggle-favourite route: {e}")
119-
raise HTTPException(status_code=500, detail=f"Internal server error: {e}")
120-
128+
raise HTTPException(
129+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
130+
detail=f"Internal server error: {e}"
131+
)
121132

122133
class ImageInfoResponse(BaseModel):
123134
id: str

0 commit comments

Comments
 (0)