From a5a1cd27431730a75f86a3853076d6ddeb3d75c1 Mon Sep 17 00:00:00 2001 From: Ivo Oskamp Date: Tue, 13 Jan 2026 14:27:23 +0100 Subject: [PATCH] Auto-commit local changes before build (2026-01-13 14:27:23) --- .last-branch | 2 +- .../src/backend/app/main/routes_jobs.py | 72 +++++++++++++------ docs/changelog.md | 8 +++ 3 files changed, 58 insertions(+), 24 deletions(-) diff --git a/.last-branch b/.last-branch index 8b870e4..8e70fb3 100644 --- a/.last-branch +++ b/.last-branch @@ -1 +1 @@ -v20260113-06-overrides-error-match-modes +v20260113-07-job-delete-fix diff --git a/containers/backupchecks/src/backend/app/main/routes_jobs.py b/containers/backupchecks/src/backend/app/main/routes_jobs.py index 2c4dc54..387d2a0 100644 --- a/containers/backupchecks/src/backend/app/main/routes_jobs.py +++ b/containers/backupchecks/src/backend/app/main/routes_jobs.py @@ -423,25 +423,17 @@ def job_delete(job_id: int): job = Job.query.get_or_404(job_id) try: - # Collect run ids for FK cleanup in auxiliary tables that may not have ON DELETE CASCADE - run_ids = [] - mail_message_ids = [] + # Collect run IDs up-front for cleanup across dependent tables + run_ids = [r.id for r in JobRun.query.filter_by(job_id=job.id).all()] - for run in job.runs: - if run.id is not None: - run_ids.append(run.id) - if run.mail_message_id: - mail_message_ids.append(run.mail_message_id) + # Put any related mails back into the inbox and unlink from job + msgs = MailMessage.query.filter(MailMessage.job_id == job.id).all() + for msg in msgs: + if hasattr(msg, "location"): + msg.location = "inbox" + msg.job_id = None - # Put related mails back into the inbox and unlink from job - if mail_message_ids: - msgs = MailMessage.query.filter(MailMessage.id.in_(mail_message_ids)).all() - for msg in msgs: - if hasattr(msg, "location"): - msg.location = "inbox" - msg.job_id = None - - # Ensure run_object_links doesn't block job_runs deletion (older schemas may miss ON DELETE CASCADE) + # Clean up tables that may not have ON DELETE CASCADE in older schemas. if run_ids: db.session.execute( text("DELETE FROM run_object_links WHERE run_id IN :run_ids").bindparams( @@ -449,13 +441,47 @@ def job_delete(job_id: int): ), {"run_ids": run_ids}, ) + db.session.execute( + text("DELETE FROM job_run_review_events WHERE run_id IN :run_ids").bindparams( + bindparam("run_ids", expanding=True) + ), + {"run_ids": run_ids}, + ) + db.session.execute( + text("DELETE FROM ticket_job_runs WHERE job_run_id IN :run_ids").bindparams( + bindparam("run_ids", expanding=True) + ), + {"run_ids": run_ids}, + ) + db.session.execute( + text("DELETE FROM remark_job_runs WHERE job_run_id IN :run_ids").bindparams( + bindparam("run_ids", expanding=True) + ), + {"run_ids": run_ids}, + ) + db.session.execute( + text("DELETE FROM job_objects WHERE job_run_id IN :run_ids").bindparams( + bindparam("run_ids", expanding=True) + ), + {"run_ids": run_ids}, + ) + + # Overrides scoped to this job (object overrides) + db.session.execute(text("UPDATE overrides SET job_id = NULL WHERE job_id = :job_id"), {"job_id": job.id}) + + # Ticket/Remark scopes may reference a specific job + db.session.execute(text("UPDATE ticket_scopes SET job_id = NULL WHERE job_id = :job_id"), {"job_id": job.id}) + db.session.execute(text("UPDATE remark_scopes SET job_id = NULL WHERE job_id = :job_id"), {"job_id": job.id}) # Ensure job_object_links doesn't block jobs deletion (older schemas may miss ON DELETE CASCADE) - if job.id is not None: - db.session.execute( - text("DELETE FROM job_object_links WHERE job_id = :job_id"), - {"job_id": job.id}, - ) + db.session.execute( + text("DELETE FROM job_object_links WHERE job_id = :job_id"), + {"job_id": job.id}, + ) + + # Finally remove runs and the job itself + if run_ids: + db.session.execute(text("DELETE FROM job_runs WHERE job_id = :job_id"), {"job_id": job.id}) db.session.delete(job) db.session.commit() @@ -465,4 +491,4 @@ def job_delete(job_id: int): print(f"[jobs] Failed to delete job: {exc}") flash("Failed to delete job.", "danger") - return redirect(url_for("main.jobs")) \ No newline at end of file + return redirect(url_for("main.jobs")) diff --git a/docs/changelog.md b/docs/changelog.md index 59b241d..d60086f 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -43,6 +43,14 @@ - Extended overrides UI with a match type selector and improved edit support for existing overrides - Added database migration to create and backfill overrides.match_error_mode for existing records +--- + +## v20260113-07-job-delete-fix + +- Fixed an error that occurred when deleting a job. +- Corrected backend deletion logic to prevent exceptions during job removal. +- Ensured related records are handled safely to avoid constraint or reference errors. + *** ## v0.1.20 -- 2.45.2