From ea04b57dcea011a7bbfc8ecd8d631b66676f4ff0 Mon Sep 17 00:00:00 2001 From: aradhyacp Date: Tue, 30 Dec 2025 11:48:05 +0530 Subject: [PATCH 1/7] Refactor upload_image function to streamline submission and image handling logic --- aperisolve/app.py | 116 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 86 insertions(+), 30 deletions(-) diff --git a/aperisolve/app.py b/aperisolve/app.py index e81de53..9705156 100644 --- a/aperisolve/app.py +++ b/aperisolve/app.py @@ -112,21 +112,26 @@ def upload_image() -> tuple[Response, int]: submission_hash = hashlib.md5(submission_data).hexdigest() submission_path = RESULT_FOLDER / img_hash / submission_hash - # If submission already exists, return submission hash - if submission_path.exists(): - submission: Submission = Submission.query.filter_by( - hash=submission_hash - ).first() - return jsonify({"submission_hash": submission.hash}), 200 + submission: Submission = Submission.query.filter_by( + hash=submission_hash + ).first() - # If image is new, create a new Image entry + if submission_path.exists() and submission is not None: + return jsonify({"submission_hash": submission.hash}),200 + new_img_path = RESULT_FOLDER / img_hash / image_name - if not new_img_path.parent.exists(): - new_img_path.parent.mkdir(parents=True, exist_ok=True) - with open(new_img_path, "wb") as f: # Write file to disk - f.write(image_data) - new_img = Image( + sub_img = Image.query.filter_by( + hash=img_hash + ).first() + + if sub_img is None: + if not new_img_path.parent.exists() or not new_img_path.exists(): + new_img_path.parent.mkdir(parents=True, exist_ok=True) + with open(new_img_path,"wb") as f: + f.write(image_data) + + sub_img = Image( file=str(new_img_path), hash=img_hash, size=len(image_data), @@ -134,31 +139,82 @@ def upload_image() -> tuple[Response, int]: first_submission_date=datetime.now(timezone.utc), last_submission_date=datetime.now(timezone.utc), ) - db.session.add(new_img) # pylint: disable=no-member - db.session.commit() # pylint: disable=no-member + db.session.add(sub_img) + db.session.commit() - sub_img = Image.query.filter_by(hash=img_hash).first() # type: ignore + sub_img.upload_count += 1 - db.session.commit() # pylint: disable=no-member + db.session.commit() - # Create new Submission entry 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 - # Start the analysis jobs + 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() + queue.enqueue("aperisolve.workers.analyze_image", submission.hash, job_timeout=300) - return jsonify({"submission_hash": submission.hash}), 200 + return jsonify({"submission_hash": submission.hash}), 20 + + + + + # # If submission already exists, return submission hash + # if submission_path.exists(): + # submission: Submission = Submission.query.filter_by( + # hash=submission_hash + # ).first() + # 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 + # if not new_img_path.parent.exists(): + # new_img_path.parent.mkdir(parents=True, exist_ok=True) + # with open(new_img_path, "wb") as f: # Write file to disk + # f.write(image_data) + + # new_img = Image( + # file=str(new_img_path), + # hash=img_hash, + # size=len(image_data), + # upload_count=0, + # first_submission_date=datetime.now(timezone.utc), + # last_submission_date=datetime.now(timezone.utc), + # ) + # db.session.add(new_img) # pylint: disable=no-member + # db.session.commit() # pylint: disable=no-member + + # sub_img = Image.query.filter_by(hash=img_hash).first() # type: ignore + # sub_img.upload_count += 1 + # db.session.commit() # pylint: disable=no-member + + # # Create new Submission entry + # 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 + # # Start the analysis jobs + # queue.enqueue("aperisolve.workers.analyze_image", submission.hash, job_timeout=300) + + # return jsonify({"submission_hash": submission.hash}), 200 @app.route("/status/", methods=["GET"]) From 8e72911f54beec57b3abf04a9641e3b220808b38 Mon Sep 17 00:00:00 2001 From: aradhyacp Date: Tue, 30 Dec 2025 11:48:20 +0530 Subject: [PATCH 2/7] Fix upload_image response status code from 20 to 200 --- aperisolve/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aperisolve/app.py b/aperisolve/app.py index 9705156..94b3f54 100644 --- a/aperisolve/app.py +++ b/aperisolve/app.py @@ -163,7 +163,7 @@ def upload_image() -> tuple[Response, int]: queue.enqueue("aperisolve.workers.analyze_image", submission.hash, job_timeout=300) - return jsonify({"submission_hash": submission.hash}), 20 + return jsonify({"submission_hash": submission.hash}), 200 From 4a380d277e883163ae304f83d152810af2de76c6 Mon Sep 17 00:00:00 2001 From: aradhyacp Date: Tue, 30 Dec 2025 11:59:02 +0530 Subject: [PATCH 3/7] simple documentation comments --- aperisolve/app.py | 65 ++++++++++------------------------------------- 1 file changed, 14 insertions(+), 51 deletions(-) diff --git a/aperisolve/app.py b/aperisolve/app.py index 94b3f54..0ebc831 100644 --- a/aperisolve/app.py +++ b/aperisolve/app.py @@ -112,25 +112,33 @@ def upload_image() -> tuple[Response, int]: submission_hash = hashlib.md5(submission_data).hexdigest() submission_path = RESULT_FOLDER / img_hash / submission_hash + # Check if hash is present on the DB submission: Submission = Submission.query.filter_by( hash=submission_hash ).first() + # Only return if BOTH the file exists AND the DB entry exists if submission_path.exists() and submission is not None: return jsonify({"submission_hash": submission.hash}),200 + + # Self-Healing Logic new_img_path = RESULT_FOLDER / img_hash / image_name + # Try to find image in DB by hash sub_img = Image.query.filter_by( hash=img_hash ).first() + # If DB entry is missing (even if file exists on disk), create it! if sub_img is None: if not new_img_path.parent.exists() or not new_img_path.exists(): new_img_path.parent.mkdir(parents=True, exist_ok=True) with open(new_img_path,"wb") as f: f.write(image_data) + + # Recreate the missing Database Entry sub_img = Image( file=str(new_img_path), hash=img_hash, @@ -142,12 +150,15 @@ def upload_image() -> tuple[Response, int]: db.session.add(sub_img) db.session.commit() - + # Recreate the missing Database Entry sub_img.upload_count += 1 db.session.commit() + # Create new Submission entry submission_path.mkdir(parents=True, exist_ok=True) + # Only create a new submission if it does not already exist + # New submission for new image if not submission: submission = Submission( filename=image.filename, @@ -161,62 +172,14 @@ def upload_image() -> tuple[Response, int]: db.session.add(submission) db.session.commit() + # Start the analysis jobs queue.enqueue("aperisolve.workers.analyze_image", submission.hash, job_timeout=300) + # Return submission identifier return jsonify({"submission_hash": submission.hash}), 200 - - # # If submission already exists, return submission hash - # if submission_path.exists(): - # submission: Submission = Submission.query.filter_by( - # hash=submission_hash - # ).first() - # 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 - # if not new_img_path.parent.exists(): - # new_img_path.parent.mkdir(parents=True, exist_ok=True) - # with open(new_img_path, "wb") as f: # Write file to disk - # f.write(image_data) - - # new_img = Image( - # file=str(new_img_path), - # hash=img_hash, - # size=len(image_data), - # upload_count=0, - # first_submission_date=datetime.now(timezone.utc), - # last_submission_date=datetime.now(timezone.utc), - # ) - # db.session.add(new_img) # pylint: disable=no-member - # db.session.commit() # pylint: disable=no-member - - # sub_img = Image.query.filter_by(hash=img_hash).first() # type: ignore - # sub_img.upload_count += 1 - # db.session.commit() # pylint: disable=no-member - - # # Create new Submission entry - # 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 - # # Start the analysis jobs - # queue.enqueue("aperisolve.workers.analyze_image", submission.hash, job_timeout=300) - - # return jsonify({"submission_hash": submission.hash}), 200 - - @app.route("/status/", methods=["GET"]) def get_status(hash_val: str) -> Response: """Get the processing status of a submission.""" From a0c616bc78622d4e4ee572d307e90af0a97994d5 Mon Sep 17 00:00:00 2001 From: Aradhya C P <135510032+aradhyacp@users.noreply.github.com> Date: Tue, 30 Dec 2025 13:00:05 +0530 Subject: [PATCH 4/7] Update aperisolve/app.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- aperisolve/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aperisolve/app.py b/aperisolve/app.py index 0ebc831..55f321f 100644 --- a/aperisolve/app.py +++ b/aperisolve/app.py @@ -150,7 +150,7 @@ def upload_image() -> tuple[Response, int]: db.session.add(sub_img) db.session.commit() - # Recreate the missing Database Entry + # Increment upload count for the image sub_img.upload_count += 1 db.session.commit() From 9f21ac429dceb403cf19314a2e66a37ca055d6d9 Mon Sep 17 00:00:00 2001 From: Aradhya C P <135510032+aradhyacp@users.noreply.github.com> Date: Tue, 30 Dec 2025 13:00:12 +0530 Subject: [PATCH 5/7] Update aperisolve/app.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- aperisolve/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aperisolve/app.py b/aperisolve/app.py index 55f321f..f820226 100644 --- a/aperisolve/app.py +++ b/aperisolve/app.py @@ -134,7 +134,7 @@ def upload_image() -> tuple[Response, int]: if sub_img is None: if not new_img_path.parent.exists() or not new_img_path.exists(): new_img_path.parent.mkdir(parents=True, exist_ok=True) - with open(new_img_path,"wb") as f: + with open(new_img_path, "wb") as f: f.write(image_data) From 87df3cc629be451e7afb2cc17f447ee4a99480f2 Mon Sep 17 00:00:00 2001 From: Aradhya C P <135510032+aradhyacp@users.noreply.github.com> Date: Tue, 30 Dec 2025 13:00:31 +0530 Subject: [PATCH 6/7] Update aperisolve/app.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- aperisolve/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aperisolve/app.py b/aperisolve/app.py index f820226..75359d2 100644 --- a/aperisolve/app.py +++ b/aperisolve/app.py @@ -119,7 +119,7 @@ def upload_image() -> tuple[Response, int]: # Only return if BOTH the file exists AND the DB entry exists if submission_path.exists() and submission is not None: - return jsonify({"submission_hash": submission.hash}),200 + return jsonify({"submission_hash": submission.hash}), 200 # Self-Healing Logic From b15dca9c537d418dba39567761b38198207ed5d1 Mon Sep 17 00:00:00 2001 From: Zeecka Date: Tue, 30 Dec 2025 16:57:08 +0100 Subject: [PATCH 7/7] Fix with fs remove --- aperisolve/app.py | 80 ++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 43 deletions(-) diff --git a/aperisolve/app.py b/aperisolve/app.py index 75359d2..f9e2ff9 100644 --- a/aperisolve/app.py +++ b/aperisolve/app.py @@ -6,6 +6,7 @@ import os import time from datetime import datetime, timezone from pathlib import Path +from shutil import rmtree from typing import Any, Optional from flask import Flask, Response, abort, jsonify, render_template, request, send_file @@ -112,34 +113,33 @@ def upload_image() -> tuple[Response, int]: submission_hash = hashlib.md5(submission_data).hexdigest() submission_path = RESULT_FOLDER / img_hash / submission_hash - # Check if hash is present on the DB - submission: Submission = Submission.query.filter_by( - hash=submission_hash - ).first() + # If submission already exists, return submission hash + if submission_path.exists(): + submission: Submission = Submission.query.filter_by( + hash=submission_hash + ).first() - # Only return if BOTH the file exists AND the DB entry exists - if submission_path.exists() and submission is not None: - return jsonify({"submission_hash": submission.hash}), 200 - + if submission is not None: # File exist but not in DB (should not happen), + rmtree(submission_path) # Removing file and continue processing as new + db.session.delete(submission) # pylint: disable=no-member + db.session.commit() # pylint: disable=no-member + else: + return jsonify({"submission_hash": submission.hash}), 200 - # Self-Healing Logic + # If image is new, create a new Image entry new_img_path = RESULT_FOLDER / img_hash / image_name + sub_img = Image.query.filter_by(hash=img_hash).first() # type: ignore - # Try to find image in DB by hash - sub_img = Image.query.filter_by( - hash=img_hash - ).first() + if new_img_path.parent.exists() and sub_img is None: + # Inconsistent state: image file exists but no DB entry + rmtree(new_img_path.parent) # Remove the existing files and continue - # If DB entry is missing (even if file exists on disk), create it! - if sub_img is None: - if not new_img_path.parent.exists() or not new_img_path.exists(): - new_img_path.parent.mkdir(parents=True, exist_ok=True) - with open(new_img_path, "wb") as f: - f.write(image_data) + if not new_img_path.parent.exists(): + new_img_path.parent.mkdir(parents=True, exist_ok=True) + with open(new_img_path, "wb") as f: # Write file to disk + f.write(image_data) - - # Recreate the missing Database Entry - sub_img = Image( + new_img = Image( file=str(new_img_path), hash=img_hash, size=len(image_data), @@ -147,39 +147,33 @@ def upload_image() -> tuple[Response, int]: first_submission_date=datetime.now(timezone.utc), last_submission_date=datetime.now(timezone.utc), ) - db.session.add(sub_img) - db.session.commit() + db.session.add(new_img) # pylint: disable=no-member + db.session.commit() # pylint: disable=no-member - # Increment upload count for the image + sub_img = Image.query.filter_by(hash=img_hash).first() # type: ignore sub_img.upload_count += 1 - db.session.commit() + db.session.commit() # pylint: disable=no-member # Create new Submission entry 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 - # 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() - + db.session.commit() # pylint: disable=no-member # Start the analysis jobs queue.enqueue("aperisolve.workers.analyze_image", submission.hash, job_timeout=300) - # Return submission identifier return jsonify({"submission_hash": submission.hash}), 200 - @app.route("/status/", methods=["GET"]) def get_status(hash_val: str) -> Response: """Get the processing status of a submission."""