Skip to content

Commit 2c91f65

Browse files
committed
Optimize user deletion
1 parent c9ac731 commit 2c91f65

File tree

1 file changed

+50
-45
lines changed

1 file changed

+50
-45
lines changed

gefapi/services/user_service.py

Lines changed: 50 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -761,77 +761,82 @@ def delete_user(user_id):
761761
message="User with ID " + str(user_id) + " does not exist"
762762
)
763763
try:
764-
# Import models for explicit deletion
765-
from sqlalchemy import String, cast
764+
from sqlalchemy import text
766765

767-
from gefapi.models import Execution, ExecutionLog, Script, StatusLog
768-
from gefapi.models.password_reset_token import PasswordResetToken
769-
from gefapi.models.refresh_token import RefreshToken
770-
from gefapi.models.script_log import ScriptLog
766+
user_uuid = str(user.id)
771767

772-
user_uuid = user.id
773-
774-
# Get execution IDs for this user (needed for related table deletions)
775-
execution_ids_uuid = db.session.query(Execution.id).filter(
776-
Execution.user_id == user_uuid
777-
)
778-
# Cast to string for StatusLog which uses String(36) for execution_id
779-
execution_ids_str = db.session.query(cast(Execution.id, String)).filter(
780-
Execution.user_id == user_uuid
781-
)
782-
783-
# Get script IDs for this user (needed for script log deletions)
784-
script_ids_uuid = db.session.query(Script.id).filter(
785-
Script.user_id == user_uuid
786-
)
787-
788-
# Batch delete related records for performance
789-
# Delete status logs for user's executions first
790-
# StatusLog.execution_id is String(36), so use string-cast query
768+
# Use raw SQL for maximum performance - single pass through each table
769+
# Delete status logs via JOIN to executions (StatusLog uses String FK)
791770
logger.info("[DB]: Deleting status logs for user's executions")
792-
StatusLog.query.filter(
793-
StatusLog.execution_id.in_(execution_ids_str)
794-
).delete(synchronize_session=False)
771+
db.session.execute(
772+
text("""
773+
DELETE FROM status_log
774+
WHERE execution_id IN (
775+
SELECT CAST(id AS VARCHAR)
776+
FROM execution WHERE user_id = :user_id
777+
)
778+
"""),
779+
{"user_id": user_uuid},
780+
)
795781

796-
# Delete execution logs (uses UUID foreign key)
782+
# Delete execution logs via JOIN (ExecutionLog uses UUID FK)
797783
logger.info("[DB]: Deleting execution logs for user's executions")
798-
ExecutionLog.query.filter(
799-
ExecutionLog.execution_id.in_(execution_ids_uuid)
800-
).delete(synchronize_session=False)
784+
db.session.execute(
785+
text("""
786+
DELETE FROM execution_log
787+
WHERE execution_id IN (
788+
SELECT id FROM execution WHERE user_id = :user_id
789+
)
790+
"""),
791+
{"user_id": user_uuid},
792+
)
801793

802794
# Delete executions
803795
logger.info("[DB]: Deleting executions")
804-
Execution.query.filter(Execution.user_id == user_uuid).delete(
805-
synchronize_session=False
796+
db.session.execute(
797+
text("DELETE FROM execution WHERE user_id = :user_id"),
798+
{"user_id": user_uuid},
806799
)
807800

808-
# Delete script logs for user's scripts
801+
# Delete script logs via JOIN
809802
logger.info("[DB]: Deleting script logs for user's scripts")
810-
ScriptLog.query.filter(ScriptLog.script_id.in_(script_ids_uuid)).delete(
811-
synchronize_session=False
803+
db.session.execute(
804+
text("""
805+
DELETE FROM script_log
806+
WHERE script_id IN (
807+
SELECT id FROM script WHERE user_id = :user_id
808+
)
809+
"""),
810+
{"user_id": user_uuid},
812811
)
813812

814813
# Delete scripts
815814
logger.info("[DB]: Deleting scripts")
816-
Script.query.filter(Script.user_id == user_uuid).delete(
817-
synchronize_session=False
815+
db.session.execute(
816+
text("DELETE FROM script WHERE user_id = :user_id"),
817+
{"user_id": user_uuid},
818818
)
819819

820820
# Delete password reset tokens
821821
logger.info("[DB]: Deleting password reset tokens")
822-
PasswordResetToken.query.filter(
823-
PasswordResetToken.user_id == user_uuid
824-
).delete(synchronize_session=False)
822+
db.session.execute(
823+
text("DELETE FROM password_reset_token WHERE user_id = :user_id"),
824+
{"user_id": user_uuid},
825+
)
825826

826827
# Delete refresh tokens
827828
logger.info("[DB]: Deleting refresh tokens")
828-
RefreshToken.query.filter(RefreshToken.user_id == user_uuid).delete(
829-
synchronize_session=False
829+
db.session.execute(
830+
text("DELETE FROM refresh_token WHERE user_id = :user_id"),
831+
{"user_id": user_uuid},
830832
)
831833

832834
# Now delete the user
833835
logger.info("[DB]: DELETE user")
834-
db.session.delete(user)
836+
db.session.execute(
837+
text("DELETE FROM public.user WHERE id = :user_id"),
838+
{"user_id": user_uuid},
839+
)
835840
db.session.commit()
836841
except Exception as error:
837842
db.session.rollback()

0 commit comments

Comments
 (0)