stop service if critical task activated (#2966)

filter out union lists instead of erroring
This commit is contained in:
Aiden McClelland
2025-06-18 22:03:27 +00:00
committed by GitHub
parent 28f31be36f
commit dbf08a6cf8
10 changed files with 314 additions and 58 deletions

View File

@@ -6,7 +6,7 @@ use models::{ActionId, PackageId, ProcedureName, ReplayId};
use crate::action::{ActionInput, ActionResult};
use crate::db::model::package::{
ActionVisibility, AllowedStatuses, TaskCondition, TaskEntry, TaskInput,
ActionVisibility, AllowedStatuses, TaskCondition, TaskEntry, TaskInput, TaskSeverity,
};
use crate::prelude::*;
use crate::rpc_continuations::Guid;
@@ -78,7 +78,8 @@ pub fn update_tasks(
action_id: &ActionId,
input: &Value,
was_run: bool,
) {
) -> bool {
let mut critical_activated = false;
tasks.retain(|_, v| {
if &v.task.package_id != package_id || &v.task.action_id != action_id {
return true;
@@ -95,6 +96,9 @@ pub fn update_tasks(
}
} else {
v.active = true;
if v.task.severity == TaskSeverity::Critical {
critical_activated = true;
}
}
}
None => {
@@ -106,7 +110,8 @@ pub fn update_tasks(
} else {
!was_run
}
})
});
critical_activated
}
pub(super) struct RunAction {
@@ -125,7 +130,7 @@ impl Handler<RunAction> for ServiceActor {
id: ref action_id,
input,
}: RunAction,
_: &BackgroundJobQueue,
jobs: &BackgroundJobQueue,
) -> Self::Response {
let container = &self.0.persistent_container;
let package_id = &self.0.id;
@@ -162,7 +167,7 @@ impl Handler<RunAction> for ServiceActor {
}
let result = container
.execute::<Option<ActionResult>>(
id,
id.clone(),
ProcedureName::RunAction(action_id.clone()),
json!({
"input": input,
@@ -171,19 +176,30 @@ impl Handler<RunAction> for ServiceActor {
)
.await
.with_kind(ErrorKind::Action)?;
self.0
if self
.0
.ctx
.db
.mutate(|db| {
let mut critical_activated = false;
for (_, pde) in db.as_public_mut().as_package_data_mut().as_entries_mut()? {
pde.as_tasks_mut().mutate(|tasks| {
critical_activated |= pde.as_tasks_mut().mutate(|tasks| {
Ok(update_tasks(tasks, package_id, action_id, &input, true))
})?;
}
Ok(())
Ok(critical_activated)
})
.await
.result?;
.result?
{
<Self as Handler<super::control::Stop>>::handle(
self,
id,
super::control::Stop { wait: false },
jobs,
)
.await;
}
Ok(result)
}
}

View File

@@ -28,8 +28,8 @@ impl Service {
}
}
struct Stop {
wait: bool,
pub(super) struct Stop {
pub wait: bool,
}
impl Handler<Stop> for ServiceActor {
type Response = ();

View File

@@ -35,7 +35,7 @@ use url::Url;
use crate::context::{CliContext, RpcContext};
use crate::db::model::package::{
InstalledState, ManifestPreference, PackageDataEntry, PackageState, PackageStateMatchModelRef,
UpdatingState,
TaskSeverity, UpdatingState,
};
use crate::disk::mount::filesystem::ReadOnly;
use crate::disk::mount::guard::{GenericMountGuard, MountGuard};
@@ -526,7 +526,8 @@ impl Service {
}
}
}
ctx.db
let has_critical = ctx
.db
.mutate(|db| {
for (action_id, input) in &action_input {
for (_, pde) in db.as_public_mut().as_package_data_mut().as_entries_mut()? {
@@ -541,10 +542,12 @@ impl Service {
.as_idx_mut(&manifest.id)
.or_not_found(&manifest.id)?;
let actions = entry.as_actions().keys()?;
entry.as_tasks_mut().mutate(|t| {
Ok(t.retain(|_, v| {
let has_critical = entry.as_tasks_mut().mutate(|t| {
t.retain(|_, v| {
v.task.package_id != manifest.id || actions.contains(&v.task.action_id)
}))
});
Ok(t.iter()
.any(|(_, t)| t.active && t.task.severity == TaskSeverity::Critical))
})?;
entry
.as_state_info_mut()
@@ -553,11 +556,15 @@ impl Service {
entry.as_icon_mut().ser(&icon)?;
entry.as_registry_mut().ser(registry)?;
Ok(())
Ok(has_critical)
})
.await
.result?;
if prev_state == Some(StartStop::Start) && !has_critical {
service.start(procedure_id).await?;
}
Ok(service)
}

View File

@@ -25,7 +25,6 @@ use crate::prelude::*;
use crate::progress::{
FullProgressTracker, PhaseProgressTrackerHandle, ProgressTrackerWriter, ProgressUnits,
};
use crate::rpc_continuations::Guid;
use crate::s9pk::manifest::PackageId;
use crate::s9pk::merkle_archive::source::FileSource;
use crate::s9pk::S9pk;
@@ -344,9 +343,6 @@ impl ServiceMap {
}),
)
.await?;
if prev == Some(StartStop::Start) {
new_service.start(Guid::new()).await?;
}
*service = Some(new_service.into());
drop(service);