From b0412e201946e1ed06b993d3670a5f4d88f0f56c Mon Sep 17 00:00:00 2001 From: iliana etaoin Date: Tue, 14 Oct 2025 14:54:45 -0700 Subject: [PATCH 1/2] always move uploaded TUF repos to the replication task Fixes #9140. --- nexus/src/app/update.rs | 46 ++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/nexus/src/app/update.rs b/nexus/src/app/update.rs index 05753d5038..5f5b76fcdf 100644 --- a/nexus/src/app/update.rs +++ b/nexus/src/app/update.rs @@ -19,7 +19,6 @@ use nexus_types::deployment::{ }; use nexus_types::external_api::shared::TufSignedRootRole; use nexus_types::external_api::views; -use nexus_types::external_api::views::TufRepoUploadStatus; use nexus_types::internal_api::views as internal_views; use nexus_types::inventory::RotSlot; use omicron_common::api::external::InternalContext; @@ -93,29 +92,28 @@ impl super::Nexus { .await .map_err(HttpError::from)?; - // If we inserted a new repository, move the `ArtifactsWithPlan` (which - // carries with it the `Utf8TempDir`s storing the artifacts) into the - // artifact replication background task, then immediately activate the - // task. - if response.status == TufRepoUploadStatus::Inserted { - self.tuf_artifact_replication_tx - .send(artifacts_with_plan) - .await - .map_err(|err| { - // In theory this should never happen; `Sender::send` - // returns an error only if the receiver has hung up, and - // the receiver should live for as long as Nexus does (it - // belongs to the background task driver). - // - // If this _does_ happen, the impact is that the database - // has recorded a repository for which we no longer have - // the artifacts. - Error::internal_error(&format!( - "failed to send artifacts for replication: {err}" - )) - })?; - self.background_tasks.task_tuf_artifact_replication.activate(); - } + // Move the `ArtifactsWithPlan` (which carries with it the + // `Utf8TempDir`s storing the artifacts) into the artifact replication + // background task, then immediately activate the task. (If this repo + // was already uploaded, the artifacts should immediately be dropped by + // the task.) + self.tuf_artifact_replication_tx + .send(artifacts_with_plan) + .await + .map_err(|err| { + // In theory this should never happen; `Sender::send` + // returns an error only if the receiver has hung up, and + // the receiver should live for as long as Nexus does (it + // belongs to the background task driver). + // + // If this _does_ happen, the impact is that the database + // has recorded a repository for which we no longer have + // the artifacts. + Error::internal_error(&format!( + "failed to send artifacts for replication: {err}" + )) + })?; + self.background_tasks.task_tuf_artifact_replication.activate(); Ok(response) } From cda23bd6a3471ac119ab87056e61b7898684a64a Mon Sep 17 00:00:00 2001 From: iliana etaoin Date: Wed, 15 Oct 2025 13:15:24 -0700 Subject: [PATCH 2/2] better explain the channel send error handling --- nexus/src/app/update.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/nexus/src/app/update.rs b/nexus/src/app/update.rs index 5f5b76fcdf..fcfa71c757 100644 --- a/nexus/src/app/update.rs +++ b/nexus/src/app/update.rs @@ -101,14 +101,16 @@ impl super::Nexus { .send(artifacts_with_plan) .await .map_err(|err| { - // In theory this should never happen; `Sender::send` - // returns an error only if the receiver has hung up, and - // the receiver should live for as long as Nexus does (it - // belongs to the background task driver). + // This error can only happen while Nexus's Tokio runtime is + // shutting down; Sender::send returns an error only if the + // receiver has hung up, and the receiver should live for + // as long as Nexus does (it belongs to the background task + // driver.) // - // If this _does_ happen, the impact is that the database - // has recorded a repository for which we no longer have - // the artifacts. + // In the unlikely event that it does happen within this narrow + // window, the impact is that the database has recorded a + // repository for which we no longer have the artifacts. The fix + // would be to reupload the repository. Error::internal_error(&format!( "failed to send artifacts for replication: {err}" ))