diff --git a/storage_controller/migrations/2025-01-15-000118_safekeeper_timelines/down.sql b/storage_controller/migrations/2025-01-22-000118_safekeeper_timelines/down.sql similarity index 100% rename from storage_controller/migrations/2025-01-15-000118_safekeeper_timelines/down.sql rename to storage_controller/migrations/2025-01-22-000118_safekeeper_timelines/down.sql diff --git a/storage_controller/migrations/2025-01-15-000118_safekeeper_timelines/up.sql b/storage_controller/migrations/2025-01-22-000118_safekeeper_timelines/up.sql similarity index 65% rename from storage_controller/migrations/2025-01-15-000118_safekeeper_timelines/up.sql rename to storage_controller/migrations/2025-01-22-000118_safekeeper_timelines/up.sql index cd30f25519..5947a18300 100644 --- a/storage_controller/migrations/2025-01-15-000118_safekeeper_timelines/up.sql +++ b/storage_controller/migrations/2025-01-22-000118_safekeeper_timelines/up.sql @@ -4,9 +4,9 @@ CREATE TABLE timelines ( PRIMARY KEY(tenant_id, timeline_id), generation INTEGER NOT NULL, sk_set BIGINT[] NOT NULL, - new_sk_set BIGINT[] NOT NULL, cplane_notified_generation INTEGER NOT NULL, status_kind VARCHAR NOT NULL, - status VARCHAR NOT NULL + status VARCHAR NOT NULL, + deleted_at timestamptz ); -CREATE INDEX timelines_idx ON timelines(status_kind, tenant_id, timeline_id); +CREATE INDEX timelines_idx ON timelines(status_kind, deleted_at, tenant_id, timeline_id); diff --git a/storage_controller/src/persistence.rs b/storage_controller/src/persistence.rs index 8e194935bb..200df30f8c 100644 --- a/storage_controller/src/persistence.rs +++ b/storage_controller/src/persistence.rs @@ -1257,6 +1257,40 @@ impl Persistence { ) .await } + pub(crate) async fn update_timeline_status_deleted( + &self, + tenant_id: TenantId, + timeline_id: TimelineId, + ) -> DatabaseResult<()> { + use crate::schema::timelines; + + let now = chrono::offset::Utc::now(); + self.with_measured_conn( + DatabaseOperation::InsertTimeline, + move |conn| -> DatabaseResult<()> { + let inserted_updated = diesel::update(timelines::table) + .filter(timelines::tenant_id.eq(tenant_id.to_string())) + .filter(timelines::timeline_id.eq(timeline_id.to_string())) + .filter(timelines::status_kind.eq(String::from(TimelineStatusKind::Deleting))) + .set(( + timelines::status_kind.eq(String::from(TimelineStatusKind::Deleted)), + timelines::status.eq("{}"), + timelines::deleted_at.eq(now), + )) + .execute(conn)?; + + if inserted_updated != 1 { + return Err(DatabaseError::Logical(format!( + "unexpected number of rows ({})", + inserted_updated + ))); + } + + Ok(()) + }, + ) + .await + } /// Obtains the timeline, returns None if not present pub(crate) async fn get_timeline( @@ -1585,7 +1619,6 @@ pub(crate) struct TimelinePersistence { pub(crate) timeline_id: String, pub(crate) generation: i32, pub(crate) sk_set: Vec, - pub(crate) new_sk_set: Vec, pub(crate) cplane_notified_generation: i32, pub(crate) status_kind: String, pub(crate) status: String, @@ -1598,10 +1631,11 @@ pub(crate) struct TimelineFromDb { pub(crate) timeline_id: String, pub(crate) generation: i32, pub(crate) sk_set: Vec>, - pub(crate) new_sk_set: Vec>, pub(crate) cplane_notified_generation: i32, pub(crate) status_kind: String, pub(crate) status: String, + #[allow(unused)] + pub(crate) deleted_at: Option>, } impl TimelineFromDb { @@ -1611,7 +1645,6 @@ impl TimelineFromDb { timeline_id: self.timeline_id, generation: self.generation, sk_set: self.sk_set.into_iter().flatten().collect(), - new_sk_set: self.new_sk_set.into_iter().flatten().collect(), cplane_notified_generation: self.cplane_notified_generation, status_kind: self.status_kind, status: self.status, diff --git a/storage_controller/src/schema.rs b/storage_controller/src/schema.rs index 9b43143c99..645279758c 100644 --- a/storage_controller/src/schema.rs +++ b/storage_controller/src/schema.rs @@ -64,10 +64,10 @@ diesel::table! { timeline_id -> Varchar, generation -> Int4, sk_set -> Array>, - new_sk_set -> Array>, cplane_notified_generation -> Int4, status_kind -> Varchar, status -> Varchar, + deleted_at -> Nullable, } } diff --git a/storage_controller/src/service.rs b/storage_controller/src/service.rs index ed96591801..258662bc89 100644 --- a/storage_controller/src/service.rs +++ b/storage_controller/src/service.rs @@ -3592,7 +3592,6 @@ impl Service { timeline_id: timeline_id.to_string(), generation: 0, sk_set: sks_persistence.clone(), - new_sk_set: sks_persistence.clone(), cplane_notified_generation: 0, status_kind: String::from(TimelineStatusKind::Creating), status, @@ -4260,7 +4259,7 @@ impl Service { if new_status_kind == TimelineStatusKind::Deleted { self.persistence - .update_timeline_status(tenant_id, timeline_id, new_status_kind, "{}".to_owned()) + .update_timeline_status_deleted(tenant_id, timeline_id) .await?; } Ok(())