diff --git a/Cargo.lock b/Cargo.lock index 86787b8f6a..10b6f26b29 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -850,6 +850,7 @@ dependencies = [ "serde", "serde_json", "serde_with", + "utils", "workspace_hack", ] diff --git a/compute_tools/src/compute.rs b/compute_tools/src/compute.rs index 6ddfcf86c2..2204d620a3 100644 --- a/compute_tools/src/compute.rs +++ b/compute_tools/src/compute.rs @@ -256,26 +256,36 @@ impl ComputeNode { self.create_pgdata()?; config::write_postgres_conf(&pgdata_path.join("postgresql.conf"), &pspec.spec)?; - info!("starting safekeepers syncing"); - let lsn = self - .sync_safekeepers(pspec.storage_auth_token.clone()) - .with_context(|| "failed to sync safekeepers")?; - info!("safekeepers synced at LSN {}", lsn); + let start_lsn = if let Some(lsn) = pspec.spec.start_lsn { + lsn + } else { + info!("starting safekeepers syncing"); + let last_lsn = self + .sync_safekeepers(pspec.storage_auth_token.clone()) + .with_context(|| "failed to sync safekeepers")?; + info!("safekeepers synced at LSN {}", last_lsn); + last_lsn + }; info!( "getting basebackup@{} from pageserver {}", - lsn, &pspec.pageserver_connstr + start_lsn, &pspec.pageserver_connstr ); - self.get_basebackup(compute_state, lsn).with_context(|| { - format!( - "failed to get basebackup@{} from pageserver {}", - lsn, &pspec.pageserver_connstr - ) - })?; + self.get_basebackup(compute_state, start_lsn) + .with_context(|| { + format!( + "failed to get basebackup@{} from pageserver {}", + start_lsn, &pspec.pageserver_connstr + ) + })?; // Update pg_hba.conf received with basebackup. update_pg_hba(pgdata_path)?; + if pspec.spec.standby { + std::fs::File::create(pgdata_path.join("standby.signal"))?; + } + Ok(()) } @@ -416,7 +426,9 @@ impl ComputeNode { let pg = self.start_postgres(spec.storage_auth_token.clone())?; - self.apply_config(&compute_state)?; + if !spec.spec.standby { + self.apply_config(&compute_state)?; + } let startup_end_time = Utc::now(); { diff --git a/libs/compute_api/Cargo.toml b/libs/compute_api/Cargo.toml index 533a091207..428d031a93 100644 --- a/libs/compute_api/Cargo.toml +++ b/libs/compute_api/Cargo.toml @@ -11,4 +11,5 @@ serde.workspace = true serde_with.workspace = true serde_json.workspace = true +utils = { path = "../utils" } workspace_hack.workspace = true diff --git a/libs/compute_api/src/spec.rs b/libs/compute_api/src/spec.rs index f771910329..a38a625d75 100644 --- a/libs/compute_api/src/spec.rs +++ b/libs/compute_api/src/spec.rs @@ -4,7 +4,9 @@ //! all the information needed to start up the right version of PostgreSQL, //! and connect it to the storage nodes. use serde::Deserialize; +use serde_with::{serde_as, DisplayFromStr}; use std::collections::HashMap; +use utils::lsn::Lsn; /// String type alias representing Postgres identifier and /// intended to be used for DB / role names. @@ -12,6 +14,7 @@ pub type PgIdent = String; /// Cluster spec or configuration represented as an optional number of /// delta operations + final cluster state description. +#[serde_as] #[derive(Clone, Debug, Default, Deserialize)] pub struct ComputeSpec { pub format_version: f32, @@ -24,6 +27,17 @@ pub struct ComputeSpec { pub cluster: Cluster, pub delta_operations: Option>, + // If 'lsn' is set, start the compute at the given LSN. + // If 'lsn' is not set, compute_ctl performs "sync safekeepers" step first, + // and uses the last LSN on the timeline as the starting point. + #[serde_as(as = "Option")] + pub start_lsn: Option, + + // If standy == true, a standby.signal file is created, putting Postgres + // into standby mode. + #[serde(default)] + pub standby: bool, + pub storage_auth_token: Option, pub startup_tracing_context: Option>,