chore: update bundled packages only after cluster launch (#849)
This commit is contained in:
parent
43108bc8bc
commit
c7f3fdc52b
6 changed files with 6 additions and 180 deletions
|
|
@ -1373,13 +1373,9 @@ impl Actions {
|
|||
|
||||
spawn_forever(async move {
|
||||
|
||||
let synced = match state.bundles.sync(&state.services.content()).await {
|
||||
Ok(_) => true,
|
||||
Err(err) => {
|
||||
tracing::error!("bundle catalog sync failed: {err:#}");
|
||||
false
|
||||
}
|
||||
};
|
||||
if let Err(err) = state.bundles.sync(&state.services.content()).await {
|
||||
tracing::error!("bundle catalog sync failed: {err:#}");
|
||||
}
|
||||
if let Err(err) = oneclient_core::clusters::apply_remote_migrations(&state).await {
|
||||
tracing::error!("cluster migrations failed: {err:#}");
|
||||
}
|
||||
|
|
@ -1387,37 +1383,6 @@ impl Actions {
|
|||
tracing::error!("bundle cluster provisioning failed: {err:#}");
|
||||
}
|
||||
|
||||
// One grouped session for the batch so all downloads surface as a
|
||||
// single notification `detach` lets it be converted in place
|
||||
let session = oneclient_events::GroupedProgressSession::start(
|
||||
&state.services.events,
|
||||
"Updating mods",
|
||||
);
|
||||
let changed = oneclient_content::bundles::sync_all_cluster_bundles(
|
||||
state.bundles.as_ref(),
|
||||
&state.services.content(),
|
||||
Some(&session),
|
||||
)
|
||||
.await;
|
||||
let session_id = session.detach();
|
||||
|
||||
if synced
|
||||
&& let Ok(clusters) = state.clusters.list().await
|
||||
{
|
||||
let unsettled: std::collections::HashSet<i64> = changed
|
||||
.iter()
|
||||
.filter(|(_, result)| !result.settled())
|
||||
.map(|(cluster_id, _)| *cluster_id)
|
||||
.collect();
|
||||
|
||||
actions.record_bundle_checks(
|
||||
clusters
|
||||
.iter()
|
||||
.map(|cluster| cluster.id)
|
||||
.filter(|cluster_id| !unsettled.contains(cluster_id)),
|
||||
);
|
||||
}
|
||||
|
||||
actions
|
||||
.station
|
||||
.clone()
|
||||
|
|
@ -1425,12 +1390,6 @@ impl Actions {
|
|||
.launcher
|
||||
.syncing_bundles = false;
|
||||
super::invalidate_cluster_queries().await;
|
||||
|
||||
let spec = crate::install::combined_cluster_update_spec(&changed, &state.services).await;
|
||||
actions.with_engine(|app| {
|
||||
app.notifications
|
||||
.finish_grouped_as_actions(&mut app.inbox, session_id, spec);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1451,8 +1410,6 @@ impl Actions {
|
|||
return;
|
||||
}
|
||||
|
||||
let mode = self.cluster_update_mode(state, cluster_id).await;
|
||||
|
||||
self.station
|
||||
.clone()
|
||||
.write_channel(AppChannel::Launcher)
|
||||
|
|
@ -1486,15 +1443,8 @@ impl Actions {
|
|||
.launcher
|
||||
.syncing_bundles = false;
|
||||
|
||||
// No prompt for bundles the package manager's markers carry them instead
|
||||
if !matches!(mode, PackageUpdateMode::Automatic) {
|
||||
tracing::debug!(cluster_id, "bundle updates left for the user to apply");
|
||||
if synced {
|
||||
self.record_bundle_checks([cluster_id]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Bundle content is forced, so the update mode never gates it and the
|
||||
// modal never lists it
|
||||
let result = match oneclient_core::apply_bundle_updates(
|
||||
cluster_id,
|
||||
state.bundles.as_ref(),
|
||||
|
|
@ -1533,12 +1483,6 @@ impl Actions {
|
|||
}
|
||||
|
||||
super::invalidate_cluster_queries().await;
|
||||
|
||||
if let Some(spec) =
|
||||
crate::install::cluster_update_notification(cluster_id, &result, &state.services).await
|
||||
{
|
||||
self.push_notification(spec);
|
||||
}
|
||||
}
|
||||
|
||||
/// The check runs and the cache is written whatever the mode says keeping
|
||||
|
|
|
|||
|
|
@ -168,60 +168,6 @@ pub async fn cluster_update_notification(
|
|||
})
|
||||
}
|
||||
|
||||
/// All clusters share one "View changes" action so the notification keeps exactly two buttons
|
||||
pub async fn combined_cluster_update_spec(
|
||||
changed: &[(i64, oneclient_core::ApplyBundleUpdatesResult)],
|
||||
services: &oneclient_core::LauncherServices,
|
||||
) -> Option<NotificationSpec> {
|
||||
let mut summaries = Vec::new();
|
||||
let mut total_changes = 0usize;
|
||||
|
||||
for (cluster_id, result) in changed {
|
||||
if let Some(summary) = cluster_update_summary(*cluster_id, result, services).await {
|
||||
total_changes += summary.total();
|
||||
summaries.push(summary);
|
||||
}
|
||||
}
|
||||
|
||||
if summaries.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let cluster_count = summaries.len();
|
||||
let (title, body) = if total_changes == 0 {
|
||||
let offers: usize = summaries.iter().map(|s| s.optional.len()).sum();
|
||||
(
|
||||
"Optional mods available",
|
||||
format!(
|
||||
"{offers} optional mod{} across {cluster_count} cluster{}",
|
||||
if offers == 1 { "" } else { "s" },
|
||||
if cluster_count == 1 { "" } else { "s" }
|
||||
),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
"Mods updated",
|
||||
format!(
|
||||
"{total_changes} package{} updated across {cluster_count} cluster{}",
|
||||
if total_changes == 1 { "" } else { "s" },
|
||||
if cluster_count == 1 { "" } else { "s" }
|
||||
),
|
||||
)
|
||||
};
|
||||
|
||||
Some(NotificationSpec {
|
||||
title: title.to_string(),
|
||||
body,
|
||||
level: Level::Info,
|
||||
icon: Some(IconType::DownloadCloud02),
|
||||
progress: None,
|
||||
actions: vec![NotificationAction {
|
||||
label: "View changes".to_string(),
|
||||
kind: NotificationActionKind::OpenClusterUpdate(summaries),
|
||||
}],
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn pending_optional_group(
|
||||
cluster_id: i64,
|
||||
pending: &[oneclient_core::PendingOptionalMod],
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ mod manifest;
|
|||
mod optional;
|
||||
mod overrides;
|
||||
mod polymrpack;
|
||||
mod runtime;
|
||||
mod types;
|
||||
mod updates;
|
||||
|
||||
|
|
@ -25,7 +24,6 @@ pub use optional::{
|
|||
PendingOptionalMod, pending_optional_mods, resolve_optional_mods, skip_optional_mods,
|
||||
};
|
||||
pub use manifest::BundleManifest as RemoteBundleManifest;
|
||||
pub use runtime::{is_bundle_syncing, sync_all_cluster_bundles};
|
||||
pub use types::{
|
||||
ApplyBundleUpdatesResult, BundleArchive, BundleFile, BundleFileKind, BundleOptionalPackage,
|
||||
BundleManifest, BundlePackageAddition, BundlePackageRemoval, BundlePackageUpdate,
|
||||
|
|
|
|||
|
|
@ -1,34 +0,0 @@
|
|||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
|
||||
use crate::bundles::manager::BundlesManager;
|
||||
use crate::bundles::ApplyBundleUpdatesResult;
|
||||
use crate::bundles::updates::apply_bundle_updates_for_all_clusters;
|
||||
use oneclient_events::GroupedProgressSession;
|
||||
use crate::ctx::ContentCtx;
|
||||
|
||||
static BUNDLE_SYNCING: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
pub fn is_bundle_syncing() -> bool {
|
||||
BUNDLE_SYNCING.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// `session` when given groups every cluster's downloads into one notification
|
||||
#[tracing::instrument(skip_all)]
|
||||
pub async fn sync_all_cluster_bundles(
|
||||
bundles: &BundlesManager,
|
||||
ctx: &ContentCtx,
|
||||
session: Option<&GroupedProgressSession>,
|
||||
) -> Vec<(i64, ApplyBundleUpdatesResult)> {
|
||||
tracing::info!("syncing all cluster bundles");
|
||||
BUNDLE_SYNCING.store(true, Ordering::Relaxed);
|
||||
let changed = match apply_bundle_updates_for_all_clusters(bundles, ctx, session).await {
|
||||
Ok(changed) => changed,
|
||||
Err(err) => {
|
||||
tracing::error!("failed to apply bundle updates for clusters: {err:#}");
|
||||
Vec::new()
|
||||
}
|
||||
};
|
||||
BUNDLE_SYNCING.store(false, Ordering::Relaxed);
|
||||
changed
|
||||
}
|
||||
|
|
@ -902,34 +902,6 @@ pub async fn get_bundles_with_update_status(
|
|||
Ok(results)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip_all)]
|
||||
pub async fn apply_bundle_updates_for_all_clusters(
|
||||
bundles: &BundlesManager,
|
||||
ctx: &ContentCtx,
|
||||
session: Option<&oneclient_events::GroupedProgressSession>,
|
||||
) -> ContentResult<Vec<(i64, ApplyBundleUpdatesResult)>> {
|
||||
let mut changed = Vec::new();
|
||||
for cluster in cluster_dao::list_all(&ctx.db).await? {
|
||||
match apply_bundle_updates_with(cluster.id, bundles, ctx, session, None).await {
|
||||
Ok(result) => {
|
||||
if !result.updates_applied.is_empty()
|
||||
|| !result.additions_applied.is_empty()
|
||||
|| !result.removals_applied.is_empty()
|
||||
|| !result.optional_available.is_empty()
|
||||
{
|
||||
changed.push((cluster.id, result));
|
||||
}
|
||||
}
|
||||
Err(err) => tracing::warn!(
|
||||
cluster_id = cluster.id,
|
||||
error = %err,
|
||||
"bundle update apply failed for cluster"
|
||||
),
|
||||
}
|
||||
}
|
||||
Ok(changed)
|
||||
}
|
||||
|
||||
fn bundle_package_key(
|
||||
bundle_pkg: &BundleTrackedArtifactRow,
|
||||
linked: &HashMap<String, &LinkedArtifactInfo>,
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ pub use oneclient_content::bundles::{
|
|||
cluster_has_bundle_content, effective_enabled,
|
||||
install_bundle,
|
||||
install_cluster_bundles,
|
||||
install_package_from_bundle, is_bundle_syncing, list_cluster_bundle_overrides,
|
||||
install_package_from_bundle, list_cluster_bundle_overrides,
|
||||
pending_optional_mods, resolve_optional_mods, skip_optional_mods, PendingOptionalMod,
|
||||
set_bundle_package_enabled, set_bundle_package_opt_in, set_bundle_package_override,
|
||||
set_bundle_package_overrides,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue