diff --git a/bin/core/src/helpers/query.rs b/bin/core/src/helpers/query.rs index 3aec4ae84..f0e57a7f6 100644 --- a/bin/core/src/helpers/query.rs +++ b/bin/core/src/helpers/query.rs @@ -9,14 +9,18 @@ use monitor_client::entities::{ permission::PermissionLevel, server::{Server, ServerState}, tag::Tag, - update::ResourceTargetVariant, + update::{ResourceTargetVariant, Update}, user::{admin_service_user, User}, variable::Variable, + Operation, }; use mungos::{ by_id::find_one_by_id, find::find_collect, - mongodb::bson::{doc, oid::ObjectId, Document}, + mongodb::{ + bson::{doc, oid::ObjectId, Document}, + options::FindOneOptions, + }, }; use crate::{config::core_config, resource, state::db_client}; @@ -231,3 +235,25 @@ pub async fn get_variable(name: &str) -> anyhow::Result { format!("no variable found with given name: {name}") }) } + +pub async fn get_latest_update( + resource_type: ResourceTargetVariant, + id: &str, + operation: Operation, +) -> anyhow::Result> { + db_client() + .await + .updates + .find_one( + doc! { + "target.type": resource_type.as_ref(), + "target.id": id, + "operation": operation.as_ref() + }, + FindOneOptions::builder() + .sort(doc! { "start_ts": -1 }) + .build(), + ) + .await + .context("failed to query db for latest update") +} diff --git a/bin/core/src/resource/build.rs b/bin/core/src/resource/build.rs index 2c78f83b6..d0dba8520 100644 --- a/bin/core/src/resource/build.rs +++ b/bin/core/src/resource/build.rs @@ -16,11 +16,11 @@ use monitor_client::entities::{ }; use mungos::{ find::find_collect, - mongodb::{bson::doc, options::FindOneOptions, Collection}, + mongodb::{bson::doc, options::FindOptions, Collection}, }; use crate::{ - helpers::empty_or_only_spaces, + helpers::{empty_or_only_spaces, query::get_latest_update}, state::{action_states, build_state_cache, db_client}, }; @@ -205,28 +205,40 @@ async fn get_build_state(id: &String) -> BuildState { async fn get_build_state_from_db(id: &str) -> BuildState { async { - let state = db_client() - .await - .updates - .find_one( - doc! { - "target.type": "Build", - "target.id": id, - "operation": "RunBuild" - }, - FindOneOptions::builder() - .sort(doc! { "start_ts": -1 }) - .build(), - ) - .await? - .map(|u| { - if u.success { + let state = match tokio::try_join!( + latest_2_build_updates(id), + get_latest_update( + ResourceTargetVariant::Build, + id, + Operation::CancelBuild + ), + )? { + ([Some(build), second], Some(cancel)) + if cancel.start_ts > build.start_ts => + { + match second { + Some(build) => { + if build.success { + BuildState::Ok + } else { + BuildState::Failed + } + } + None => BuildState::Ok, + } + } + ([Some(build), _], _) => { + if build.success { BuildState::Ok } else { BuildState::Failed } - }) - .unwrap_or(BuildState::Ok); + } + _ => { + // No build update ever, should be fine + BuildState::Ok + } + }; anyhow::Ok(state) } .await @@ -235,3 +247,25 @@ async fn get_build_state_from_db(id: &str) -> BuildState { }) .unwrap_or(BuildState::Unknown) } + +async fn latest_2_build_updates( + id: &str, +) -> anyhow::Result<[Option; 2]> { + let mut builds = find_collect( + &db_client().await.updates, + doc! { + "target.type": "Build", + "target.id": id, + "operation": "RunBuild" + }, + FindOptions::builder() + .sort(doc! { "start_ts": -1 }) + .limit(2) + .build(), + ) + .await + .context("failed to query for latest updates")?; + let second = builds.pop(); + let first = builds.pop(); + Ok([first, second]) +} diff --git a/client/core/rs/src/entities/mod.rs b/client/core/rs/src/entities/mod.rs index fc9ab12ec..337e8731f 100644 --- a/client/core/rs/src/entities/mod.rs +++ b/client/core/rs/src/entities/mod.rs @@ -6,7 +6,7 @@ use clap::Parser; use derive_empty_traits::EmptyTraits; use serde::{Deserialize, Serialize}; use serror::Serror; -use strum::{Display, EnumString}; +use strum::{AsRefStr, Display, EnumString}; use typeshare::typeshare; /// Subtypes of [Alert][alert::Alert]. @@ -370,17 +370,18 @@ impl TryInto for Timelength { #[typeshare] #[derive( + Debug, + Clone, + Copy, + PartialEq, + Eq, + Hash, Serialize, Deserialize, - Debug, Default, Display, EnumString, - PartialEq, - Hash, - Eq, - Clone, - Copy, + AsRefStr, )] pub enum Operation { // do nothing