From acf66138ec3c063b52ba67bddc88ee9ccf6c5c72 Mon Sep 17 00:00:00 2001 From: "Eason(G Ray)" <30045503+Eason0729@users.noreply.github.com> Date: Wed, 21 Aug 2024 10:32:05 +0800 Subject: [PATCH] Fix bug children's foreign key not deleted --- backend/src/endpoint/contest.rs | 22 ++++++++++++++++------ backend/src/endpoint/problem.rs | 20 ++++++++++++++++---- backend/src/util/error.rs | 7 ++++--- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/backend/src/endpoint/contest.rs b/backend/src/endpoint/contest.rs index 9ba8bdf..575dcef 100644 --- a/backend/src/endpoint/contest.rs +++ b/backend/src/endpoint/contest.rs @@ -1,9 +1,9 @@ use super::*; - use crate::entity::{ contest::{Paginator, *}, - *, + problem, *, }; +use sea_orm::sea_query::Expr; use grpc::backend::contest_server::*; @@ -238,6 +238,8 @@ impl Contest for ArcServer { let (auth, req) = self.rate_limit(req).in_current_span().await?; req.get_or_insert(|req| async move { + let txn = self.db.begin().await?; + let result = Entity::delete_by_id(req.id) .with_auth(&auth) .write()? @@ -246,12 +248,20 @@ impl Contest for ArcServer { .await .map_err(Into::::into)?; + problem::Entity::update_many() + .col_expr(problem::Column::ContestId, Expr::value(Value::Int(None))) + .filter(crate::entity::testcase::Column::ProblemId.eq(req.id)) + .exec(&txn) + .instrument(info_span!("remove_child")) + .await?; + + txn.commit().await.map_err(|_| Error::Retry)?; + if result.rows_affected == 0 { - Err(Error::NotInDB) - } else { - tracing::info!(counter.contest = -1, id = req.id); - Ok(()) + return Err(Error::NotInDB); } + tracing::info!(counter.contest = -1, id = req.id); + Ok(()) }) .await .with_grpc() diff --git a/backend/src/endpoint/problem.rs b/backend/src/endpoint/problem.rs index 7aa5228..dffefd7 100644 --- a/backend/src/endpoint/problem.rs +++ b/backend/src/endpoint/problem.rs @@ -1,7 +1,8 @@ use super::*; use grpc::backend::problem_server::*; +use sea_orm::sea_query::Expr; -use crate::entity::{contest, problem::Paginator, problem::*}; +use crate::entity::{contest, problem::Paginator, problem::*, testcase}; impl<'a> From> for ProblemFullInfo { fn from(value: WithAuth<'a, Model>) -> Self { @@ -191,17 +192,28 @@ impl Problem for ArcServer { async fn remove(&self, req: Request) -> Result, Status> { let (auth, req) = self.rate_limit(req).in_current_span().await?; req.get_or_insert(|req| async move { + let txn = self.db.begin().await?; + let result = Entity::delete_by_id(req.id) .with_auth(&auth) .write()? - .exec(self.db.deref()) + .exec(&txn) .instrument(info_span!("remove").or_current()) - .await - .map_err(Into::::into)?; + .await?; + + testcase::Entity::update_many() + .col_expr(testcase::Column::ProblemId, Expr::value(Value::Int(None))) + .filter(testcase::Column::ProblemId.eq(req.id)) + .exec(&txn) + .instrument(info_span!("remove_child")) + .await?; + + txn.commit().await.map_err(|_| Error::Retry)?; if result.rows_affected == 0 { return Err(Error::NotInDB); } + tracing::info!(count.problem = -1, id = req.id); Ok(()) }) .await diff --git a/backend/src/util/error.rs b/backend/src/util/error.rs index 92461c1..9c9d449 100644 --- a/backend/src/util/error.rs +++ b/backend/src/util/error.rs @@ -33,8 +33,6 @@ pub enum Error { Unreachable(&'static str), #[error("Number too large(or small)")] NumberTooLarge, - // #[error("Buffer `{0}` too large")] - // BufferTooLarge(&'static str), #[error("`{0}` Already exist")] AlreadyExist(&'static str), #[error("require permission `{0}`")] @@ -47,6 +45,8 @@ pub enum Error { Judger(#[from] judger::Error), #[error("token error: `{0}`")] Token(#[from] token::Error), + #[error("retry later")] + Retry, } impl From for Error { @@ -103,6 +103,7 @@ impl From for Status { Error::Image(x) => report_internal!(error, "{}", x), Error::Judger(x) => x.into(), Error::Token(x) => x.into(), + Error::Retry => Status::aborted("Should retry"), } } } @@ -110,7 +111,7 @@ impl From for Status { /// Tracing information for error /// /// useful to log the tracing information to client -/// without exposing the server's internal erro +/// without exposing the server's internal error pub struct Tracing { trace_id: TraceId, span_id: SpanId,