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:
+24
-7
@@ -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:
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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}")
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user