diff --git a/pageserver/src/tenant/remote_timeline_client.rs b/pageserver/src/tenant/remote_timeline_client.rs index 6fedf781d4..622f9b1b9e 100644 --- a/pageserver/src/tenant/remote_timeline_client.rs +++ b/pageserver/src/tenant/remote_timeline_client.rs @@ -901,9 +901,27 @@ impl RemoteTimelineClient { .await .context("list prefixes")?; - let remaining: Vec = remaining + // We will delete the current index_part object last, since it acts as a deletion + // marker via its deleted_at attribute + let latest_index = remaining + .iter() + .filter(|p| { + p.object_name() + .map(|n| n.starts_with(IndexPart::FILE_NAME)) + .unwrap_or(false) + }) + .filter_map(|path| parse_remote_index_path(path.clone()).map(|gen| (path, gen))) + .max_by_key(|i| i.1) + .map(|i| i.0.clone()) + .unwrap_or( + // No generation-suffixed indices, assume we are dealing with + // a legacy index. + remote_index_path(&self.tenant_id, &self.timeline_id, Generation::none()), + ); + + let remaining_layers: Vec = remaining .into_iter() - .filter(|p| p.object_name() != Some(IndexPart::FILE_NAME)) + .filter(|p| p!= &latest_index) .inspect(|path| { if let Some(name) = path.object_name() { info!(%name, "deleting a file not referenced from index_part.json"); @@ -913,9 +931,11 @@ impl RemoteTimelineClient { }) .collect(); - let not_referenced_count = remaining.len(); - if !remaining.is_empty() { - self.deletion_queue_client.push_immediate(remaining).await?; + let not_referenced_count = remaining_layers.len(); + if !remaining_layers.is_empty() { + self.deletion_queue_client + .push_immediate(remaining_layers) + .await?; } fail::fail_point!("timeline-delete-before-index-delete", |_| { @@ -924,11 +944,9 @@ impl RemoteTimelineClient { ))? }); - let index_file_path = timeline_storage_path.join(Utf8Path::new(IndexPart::FILE_NAME)); - debug!("enqueuing index part deletion"); self.deletion_queue_client - .push_immediate([index_file_path].to_vec()) + .push_immediate([latest_index].to_vec()) .await?; // Timeline deletion is rare and we have probably emitted a reasonably number of objects: wait