chore: Remove Alembic migration files and configuration

This commit deletes the Alembic migration files and configuration, including the alembic.ini file, env.py, and various migration scripts. This cleanup is part of the transition to a new database management approach, ensuring that outdated migration artifacts do not interfere with future development. The requirements.txt file has also been updated to remove the Alembic dependency. No functional changes to the application are introduced in this commit.
This commit is contained in:
tanyar09
2025-11-10 13:36:51 -05:00
parent ea3d06a3d5
commit ac07932e14
18 changed files with 244 additions and 647 deletions
+24 -7
View File
@@ -52,6 +52,11 @@ def get_job(job_id: str) -> JobResponse:
message = job.meta.get("message", "") if job.meta else ""
# Check if job was cancelled
if job.meta and job.meta.get("cancelled", False):
job_status = JobStatus.FAILURE
message = job.meta.get("message", "Cancelled by user")
# If job failed, include error message
if rq_status == "failed" and job.exc_info:
# Extract error message from exception info
@@ -95,16 +100,28 @@ def stream_job_progress(job_id: str):
"failed": JobStatus.FAILURE,
}
job_status = status_map.get(job.get_status(), JobStatus.PENDING)
progress = 0
if job_status == JobStatus.STARTED or job_status == JobStatus.PROGRESS:
# Check if job was cancelled first
if job.meta and job.meta.get("cancelled", False):
job_status = JobStatus.FAILURE
message = job.meta.get("message", "Cancelled by user")
progress = job.meta.get("progress", 0) if job.meta else 0
elif job_status == JobStatus.SUCCESS:
progress = 100
elif job_status == JobStatus.FAILURE:
else:
progress = 0
if job_status == JobStatus.STARTED:
# Job is running - show progress if available
progress = job.meta.get("progress", 0) if job.meta else 0
# Map to PROGRESS status if we have actual progress
if progress > 0:
job_status = JobStatus.PROGRESS
elif job_status == JobStatus.PROGRESS:
progress = job.meta.get("progress", 0) if job.meta else 0
elif job_status == JobStatus.SUCCESS:
progress = 100
elif job_status == JobStatus.FAILURE:
progress = 0
message = job.meta.get("message", "") if job.meta else ""
message = job.meta.get("message", "") if job.meta else ""
# Only send event if progress or message changed
if progress != last_progress or message != last_message:
+8 -4
View File
@@ -44,12 +44,12 @@ def list_people(
@router.get("/with-faces", response_model=PeopleWithFacesListResponse)
def list_people_with_faces(
last_name: str | None = Query(None, description="Filter by last name (case-insensitive)"),
last_name: str | None = Query(None, description="Filter by last name or maiden name (case-insensitive)"),
db: Session = Depends(get_db),
) -> PeopleWithFacesListResponse:
"""List all people with face counts, sorted by last_name, first_name.
Optionally filter by last_name if provided (case-insensitive search).
Optionally filter by last_name or maiden_name if provided (case-insensitive search).
Only returns people who have at least one face.
"""
# Query people with face counts
@@ -64,8 +64,12 @@ def list_people_with_faces(
)
if last_name:
# Case-insensitive search on last_name
query = query.filter(func.lower(Person.last_name).contains(func.lower(last_name)))
# Case-insensitive search on both last_name and maiden_name
search_term = last_name.lower()
query = query.filter(
(func.lower(Person.last_name).contains(search_term)) |
((Person.maiden_name.isnot(None)) & (func.lower(Person.maiden_name).contains(search_term)))
)
results = query.order_by(Person.last_name.asc(), Person.first_name.asc()).all()
+28 -34
View File
@@ -338,7 +338,7 @@ def process_photo_faces(
try:
pose_faces = pose_detector.detect_pose_faces(face_detection_path)
if pose_faces:
print(f"[FaceService] Pose detection: found {len(pose_faces)} faces with pose data")
print(f"[FaceService] Pose detection for {photo.filename}: found {len(pose_faces)} faces with pose data")
except Exception as e:
print(f"[FaceService] ⚠️ Pose detection failed for {photo.filename}: {e}, using defaults")
pose_faces = []
@@ -348,7 +348,7 @@ def process_photo_faces(
pose_detector_local = PoseDetector()
pose_faces = pose_detector_local.detect_pose_faces(face_detection_path)
if pose_faces:
print(f"[FaceService] Pose detection: found {len(pose_faces)} faces with pose data")
print(f"[FaceService] Pose detection for {photo.filename}: found {len(pose_faces)} faces with pose data")
except Exception as e:
print(f"[FaceService] ⚠️ Pose detection failed for {photo.filename}: {e}, using defaults")
pose_faces = []
@@ -1058,14 +1058,19 @@ def process_unprocessed_photos(
if check_cancelled():
print(f"[FaceService] Job cancelled at photo {idx}/{total}")
if update_progress:
update_progress(
idx - 1,
total,
"Cancelled by user",
total_faces_detected,
total_faces_stored,
)
break
try:
update_progress(
idx - 1,
total,
"Cancelled by user",
total_faces_detected,
total_faces_stored,
)
except KeyboardInterrupt:
# Expected when cancellation is detected
pass
# Raise KeyboardInterrupt to signal cancellation to the task handler
raise KeyboardInterrupt("Job cancelled by user")
try:
# Update progress before processing each photo
@@ -1102,28 +1107,8 @@ def process_unprocessed_photos(
first_photo_time = time.time() - first_photo_start
print(f"[FaceService] First photo completed in {first_photo_time:.2f}s")
# Check for cancellation AFTER finishing the current photo completely
# This allows the current photo to complete (including pose detection and DB commit),
# then stops before the next one
if check_cancelled():
print(f"[FaceService] Job cancelled after finishing photo {idx}/{total}")
# Update progress to show cancellation status
if update_progress:
try:
update_progress(
idx,
total,
"Cancelled by user - finished current photo",
total_faces_detected,
total_faces_stored,
)
except KeyboardInterrupt:
# If update_progress raises KeyboardInterrupt, that's expected
# The cancellation check already happened, so we're good
pass
break
# Update progress only if NOT cancelled (to avoid unnecessary KeyboardInterrupt)
# Update progress to show completion (including pose detection)
# This happens AFTER the entire photo processing is complete
if update_progress:
try:
update_progress(
@@ -1134,12 +1119,21 @@ def process_unprocessed_photos(
total_faces_stored,
)
except KeyboardInterrupt:
# If cancellation was detected during update_progress, check again and break
# If cancellation was detected during update_progress, check again
if check_cancelled():
print(f"[FaceService] Job cancelled during progress update after photo {idx}/{total}")
break
# Raise KeyboardInterrupt to signal cancellation to the task handler
raise KeyboardInterrupt("Job cancelled by user after completing current photo")
# Re-raise if it wasn't a cancellation
raise
# Check for cancellation AFTER updating progress (photo is fully complete)
# This ensures the entire photo processing is done (including pose detection and DB commit),
# and the progress shows "Completed", then stops before the next one
if check_cancelled():
print(f"[FaceService] Job cancelled after completing photo {idx}/{total} (including pose detection)")
# Raise KeyboardInterrupt to signal cancellation to the task handler
raise KeyboardInterrupt("Job cancelled by user after completing current photo")
except KeyboardInterrupt:
# Cancellation was requested - stop processing gracefully
print(f"[FaceService] Job cancelled during processing of photo {idx}/{total}")
+6 -1
View File
@@ -211,8 +211,13 @@ def process_faces_task(
try:
job.meta = job.meta or {}
job.meta.update({
"message": "Cancelled by user",
"progress": job.meta.get("progress", 0),
"message": "Cancelled by user - finished current photo",
"cancelled": True,
"processed": job.meta.get("processed", photos_processed),
"total": job.meta.get("total", 0),
"faces_detected": job.meta.get("faces_detected", total_faces_detected),
"faces_stored": job.meta.get("faces_stored", total_faces_stored),
})
job.save_meta()
except Exception: