diff --git a/Cargo.lock b/Cargo.lock index ebc2aaf..3b02d6d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2931,7 +2931,7 @@ dependencies = [ [[package]] name = "waveflow-core" version = "1.4.0" -source = "git+https://github.com/InstaZDLL/WaveFlow?rev=24ffa58ac2e2580a02e9018bc743c4fcdfdd892b#24ffa58ac2e2580a02e9018bc743c4fcdfdd892b" +source = "git+https://github.com/InstaZDLL/WaveFlow?rev=bfb899b161a5a22c8ad4b8c92001b3fbdeb86a1a#bfb899b161a5a22c8ad4b8c92001b3fbdeb86a1a" dependencies = [ "anyhow", "async-trait", diff --git a/Cargo.toml b/Cargo.toml index cfb7211..4c5d972 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ homepage = "https://waveflow.app" # build is reproducible — bump the rev in tree when picking up a new # core release. `default-features = false` because core's # default-feature set is empty; we only want the `postgres` feature. -waveflow-core = { git = "https://github.com/InstaZDLL/WaveFlow", rev = "24ffa58ac2e2580a02e9018bc743c4fcdfdd892b", default-features = false, features = ["postgres"] } +waveflow-core = { git = "https://github.com/InstaZDLL/WaveFlow", rev = "bfb899b161a5a22c8ad4b8c92001b3fbdeb86a1a", default-features = false, features = ["postgres"] } # Database. `runtime-tokio` matches our `#[tokio::main]` runtime; # `postgres` is the driver; `macros` enables `query_as!`; `migrate` diff --git a/src/api/profiles.rs b/src/api/profiles.rs index 2c1d01b..748c514 100644 --- a/src/api/profiles.rs +++ b/src/api/profiles.rs @@ -250,28 +250,14 @@ async fn update_profile( Path(id): Path, Json(req): Json, ) -> impl IntoResponse { + // `rename_for_user` now hands back the updated row via + // `UPDATE … RETURNING …` in one round-trip — no separate + // read-back, so a concurrent DELETE can no longer flip a + // successful rename into a misleading 404. let repo = PostgresProfileRepository::new(state.db.clone()); match repo.rename_for_user(id, &req.name, user_id).await { - Ok(true) => match repo.get_for_user(id, user_id).await { - Ok(Some(profile)) => { - (StatusCode::OK, Json(ProfileResponse::from(profile))).into_response() - } - Ok(None) => { - // Race: profile deleted between rename and read. - // Surface 404 — the rename committed but the row is - // gone, so reporting success would lie. - (StatusCode::NOT_FOUND, "profile not found").into_response() - } - Err(err) => { - tracing::error!(error = %err, id, user_id, "read-after-rename failed"); - ( - StatusCode::INTERNAL_SERVER_ERROR, - "read-after-rename failed", - ) - .into_response() - } - }, - Ok(false) => (StatusCode::NOT_FOUND, "profile not found").into_response(), + Ok(Some(profile)) => (StatusCode::OK, Json(ProfileResponse::from(profile))).into_response(), + Ok(None) => (StatusCode::NOT_FOUND, "profile not found").into_response(), Err(err) => { tracing::error!(error = %err, id, user_id, "rename profile failed"); (StatusCode::INTERNAL_SERVER_ERROR, "rename failed").into_response()