diff --git a/bin/core/src/api/execute/build.rs b/bin/core/src/api/execute/build.rs index 358f06906..9e6606769 100644 --- a/bin/core/src/api/execute/build.rs +++ b/bin/core/src/api/execute/build.rs @@ -79,12 +79,21 @@ impl Resolve for State { tokio::spawn(async move { let poll = async { loop { - let build_id = tokio::select! { - _ = cancel_clone.cancelled() => return Ok(()), - id = cancel_recv.recv() => id? + let (build_id, mut update) = tokio::select! { + _ = cancel_clone.cancelled() => return Ok(()), + id = cancel_recv.recv() => id? }; if build_id == id_clone { cancel_clone.cancel(); + update.push_simple_log( + "cancel acknowledged", + "the build cancellation has been queud, it may still take some time", + ); + update.finalize(); + let id = update.id.clone(); + if let Err(e) = update_update(update).await { + warn!("failed to update Update {id} | {e:#}"); + } return Ok(()); } } @@ -224,14 +233,46 @@ impl Resolve for State { CancelBuild { build_id }: CancelBuild, user: User, ) -> anyhow::Result { - let _: Build = self + let build: Build = self .get_resource_check_permissions( &build_id, &user, PermissionLevel::Execute, ) .await?; - build_cancel_channel().sender.lock().await.send(build_id)?; + + // check if theres already an open cancel build update + if db_client() + .await + .updates + .find_one( + doc! { + "operation": "CancelBuild", + "status": "InProgress", + "target.id": &build_id, + }, + None, + ) + .await + .context("failed to query updates")? + .is_some() + { + return Err(anyhow!("Build cancel is already in progress")); + } + + let mut update = + make_update(&build, Operation::CancelBuild, &user); + + update.in_progress(); + update.id = + add_update(make_update(&build, Operation::CancelBuild, &user)) + .await?; + build_cancel_channel() + .sender + .lock() + .await + .send((build_id, update))?; + Ok(CancelBuildResponse {}) } } diff --git a/bin/core/src/helpers/channel.rs b/bin/core/src/helpers/channel.rs index d034abb0a..a51f8aaa0 100644 --- a/bin/core/src/helpers/channel.rs +++ b/bin/core/src/helpers/channel.rs @@ -1,10 +1,11 @@ use std::sync::OnceLock; -use monitor_client::entities::update::UpdateListItem; +use monitor_client::entities::update::{Update, UpdateListItem}; use tokio::sync::{broadcast, Mutex}; -pub fn build_cancel_channel() -> &'static BroadcastChannel { - static BUILD_CANCEL_CHANNEL: OnceLock> = +/// A channel sending (build_id, update_id) +pub fn build_cancel_channel() -> &'static BroadcastChannel<(String, Update)> { + static BUILD_CANCEL_CHANNEL: OnceLock> = OnceLock::new(); BUILD_CANCEL_CHANNEL.get_or_init(|| BroadcastChannel::new(100)) } diff --git a/client/core/rs/src/entities/mod.rs b/client/core/rs/src/entities/mod.rs index 3cb637477..4d5f0ebc7 100644 --- a/client/core/rs/src/entities/mod.rs +++ b/client/core/rs/src/entities/mod.rs @@ -364,6 +364,7 @@ pub enum Operation { UpdateBuild, DeleteBuild, RunBuild, + CancelBuild, // builder CreateBuilder,