Refactor upload_image function to improve submission handling and self-healing logic

This commit is contained in:
aradhyacp
2025-12-31 00:11:24 +05:30
parent 9b83623d07
commit bb50df8926
+45 -38
View File
@@ -6,7 +6,6 @@ import os
import time import time
from datetime import datetime, timezone from datetime import datetime, timezone
from pathlib import Path from pathlib import Path
from shutil import rmtree
from typing import Any, Optional from typing import Any, Optional
from flask import Flask, Response, abort, jsonify, render_template, request, send_file from flask import Flask, Response, abort, jsonify, render_template, request, send_file
@@ -113,33 +112,32 @@ def upload_image() -> tuple[Response, int]:
submission_hash = hashlib.md5(submission_data).hexdigest() submission_hash = hashlib.md5(submission_data).hexdigest()
submission_path = RESULT_FOLDER / img_hash / submission_hash submission_path = RESULT_FOLDER / img_hash / submission_hash
# If submission already exists, return submission hash # Check if hash is present on the DB
if submission_path.exists(): submission: Submission = Submission.query.filter_by(
submission: Submission = Submission.query.filter_by( hash=submission_hash
hash=submission_hash ).first()
).first()
if submission is not None: # File exist but not in DB (should not happen), # Only return if BOTH the file exists AND the DB entry exists
rmtree(submission_path) # Removing file and continue processing as new if submission_path.exists() and submission is not None:
db.session.delete(submission) # pylint: disable=no-member return jsonify({"submission_hash": submission.hash}), 200
db.session.commit() # pylint: disable=no-member
else: # Self-Healing Logic
return jsonify({"submission_hash": submission.hash}), 200
# If image is new, create a new Image entry
new_img_path = RESULT_FOLDER / img_hash / image_name new_img_path = RESULT_FOLDER / img_hash / image_name
sub_img = Image.query.filter_by(hash=img_hash).first() # type: ignore
if new_img_path.parent.exists() and sub_img is None: # This fixes the "Ghost File" issue (DB exists, but file is missing)
# Inconsistent state: image file exists but no DB entry if not new_img_path.exists():
rmtree(new_img_path.parent) # Remove the existing files and continue
if not new_img_path.parent.exists():
new_img_path.parent.mkdir(parents=True, exist_ok=True) new_img_path.parent.mkdir(parents=True, exist_ok=True)
with open(new_img_path, "wb") as f: # Write file to disk with open(new_img_path, "wb") as f:
f.write(image_data) f.write(image_data)
# Try to find image in DB by hash
sub_img = Image.query.filter_by(
hash=img_hash
).first()
new_img = Image( # If DB entry is missing (even if file exists on disk), create it!
if sub_img is None:
sub_img = Image(
file=str(new_img_path), file=str(new_img_path),
hash=img_hash, hash=img_hash,
size=len(image_data), size=len(image_data),
@@ -147,30 +145,39 @@ def upload_image() -> tuple[Response, int]:
first_submission_date=datetime.now(timezone.utc), first_submission_date=datetime.now(timezone.utc),
last_submission_date=datetime.now(timezone.utc), last_submission_date=datetime.now(timezone.utc),
) )
db.session.add(new_img) # pylint: disable=no-member db.session.add(sub_img)
db.session.commit() # pylint: disable=no-member db.session.commit()
sub_img = Image.query.filter_by(hash=img_hash).first() # type: ignore # Increment upload count for the image
sub_img.upload_count += 1 sub_img.upload_count += 1
db.session.commit() # pylint: disable=no-member db.session.commit()
# Create new Submission entry # Create new Submission entry
submission_path.mkdir(parents=True, exist_ok=True) submission_path.mkdir(parents=True, exist_ok=True)
submission = Submission(
filename=image.filename,
password=password,
deep_analysis=deep_analysis,
hash=submission_hash,
status="pending",
date=time.time(),
image_hash=sub_img.hash, # type: ignore
)
db.session.add(submission) # pylint: disable=no-member
db.session.commit() # pylint: disable=no-member # Only create a new submission if it does not already exist
# New submission for new image
if not submission:
submission = Submission(
filename=image.filename,
password=password,
deep_analysis=deep_analysis,
hash=submission_hash,
status="pending",
date=time.time(),
image_hash=sub_img.hash,
)
db.session.add(submission)
db.session.commit()
# Re-analysis case to prevent early return
submission.status = "pending"
db.session.commit()
# Start the analysis jobs # Start the analysis jobs
queue.enqueue("aperisolve.workers.analyze_image", submission.hash, job_timeout=300) queue.enqueue("aperisolve.workers.analyze_image", submission.hash, job_timeout=300)
# Return submission identifier
return jsonify({"submission_hash": submission.hash}), 200 return jsonify({"submission_hash": submission.hash}), 200