mirror of
https://github.com/neondatabase/neon.git
synced 2026-01-07 05:22:56 +00:00
Merge commit 'c34d36d8a' into problame/standby-horizon-leases
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -6992,6 +6992,7 @@ dependencies = [
|
|||||||
"pageserver_api",
|
"pageserver_api",
|
||||||
"pageserver_client",
|
"pageserver_client",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
|
"safekeeper_api",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"storage_controller_client",
|
"storage_controller_client",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ impl StorageBroker {
|
|||||||
pub async fn start(&self, retry_timeout: &Duration) -> anyhow::Result<()> {
|
pub async fn start(&self, retry_timeout: &Duration) -> anyhow::Result<()> {
|
||||||
let broker = &self.env.broker;
|
let broker = &self.env.broker;
|
||||||
|
|
||||||
print!("Starting neon broker at {}", broker.client_url());
|
println!("Starting neon broker at {}", broker.client_url());
|
||||||
|
|
||||||
let mut args = Vec::new();
|
let mut args = Vec::new();
|
||||||
|
|
||||||
|
|||||||
@@ -303,7 +303,7 @@ impl PageServerNode {
|
|||||||
async fn start_node(&self, retry_timeout: &Duration) -> anyhow::Result<()> {
|
async fn start_node(&self, retry_timeout: &Duration) -> anyhow::Result<()> {
|
||||||
// TODO: using a thread here because start_process() is not async but we need to call check_status()
|
// TODO: using a thread here because start_process() is not async but we need to call check_status()
|
||||||
let datadir = self.repo_path();
|
let datadir = self.repo_path();
|
||||||
print!(
|
println!(
|
||||||
"Starting pageserver node {} at '{}' in {:?}, retrying for {:?}",
|
"Starting pageserver node {} at '{}' in {:?}, retrying for {:?}",
|
||||||
self.conf.id,
|
self.conf.id,
|
||||||
self.pg_connection_config.raw_address(),
|
self.pg_connection_config.raw_address(),
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ impl SafekeeperNode {
|
|||||||
extra_opts: &[String],
|
extra_opts: &[String],
|
||||||
retry_timeout: &Duration,
|
retry_timeout: &Duration,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
print!(
|
println!(
|
||||||
"Starting safekeeper at '{}' in '{}', retrying for {:?}",
|
"Starting safekeeper at '{}' in '{}', retrying for {:?}",
|
||||||
self.pg_connection_config.raw_address(),
|
self.pg_connection_config.raw_address(),
|
||||||
self.datadir_path().display(),
|
self.datadir_path().display(),
|
||||||
|
|||||||
@@ -660,7 +660,7 @@ impl StorageController {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("Starting storage controller");
|
println!("Starting storage controller at {scheme}://{host}:{listen_port}");
|
||||||
|
|
||||||
background_process::start_process(
|
background_process::start_process(
|
||||||
COMMAND,
|
COMMAND,
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ humantime.workspace = true
|
|||||||
pageserver_api.workspace = true
|
pageserver_api.workspace = true
|
||||||
pageserver_client.workspace = true
|
pageserver_client.workspace = true
|
||||||
reqwest.workspace = true
|
reqwest.workspace = true
|
||||||
|
safekeeper_api.workspace=true
|
||||||
serde_json = { workspace = true, features = ["raw_value"] }
|
serde_json = { workspace = true, features = ["raw_value"] }
|
||||||
storage_controller_client.workspace = true
|
storage_controller_client.workspace = true
|
||||||
tokio.workspace = true
|
tokio.workspace = true
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use pageserver_api::controller_api::{
|
|||||||
PlacementPolicy, SafekeeperDescribeResponse, SafekeeperSchedulingPolicyRequest,
|
PlacementPolicy, SafekeeperDescribeResponse, SafekeeperSchedulingPolicyRequest,
|
||||||
ShardSchedulingPolicy, ShardsPreferredAzsRequest, ShardsPreferredAzsResponse,
|
ShardSchedulingPolicy, ShardsPreferredAzsRequest, ShardsPreferredAzsResponse,
|
||||||
SkSchedulingPolicy, TenantCreateRequest, TenantDescribeResponse, TenantPolicyRequest,
|
SkSchedulingPolicy, TenantCreateRequest, TenantDescribeResponse, TenantPolicyRequest,
|
||||||
TenantShardMigrateRequest, TenantShardMigrateResponse,
|
TenantShardMigrateRequest, TenantShardMigrateResponse, TimelineSafekeeperMigrateRequest,
|
||||||
};
|
};
|
||||||
use pageserver_api::models::{
|
use pageserver_api::models::{
|
||||||
EvictionPolicy, EvictionPolicyLayerAccessThreshold, ShardParameters, TenantConfig,
|
EvictionPolicy, EvictionPolicyLayerAccessThreshold, ShardParameters, TenantConfig,
|
||||||
@@ -21,6 +21,7 @@ use pageserver_api::models::{
|
|||||||
use pageserver_api::shard::{ShardStripeSize, TenantShardId};
|
use pageserver_api::shard::{ShardStripeSize, TenantShardId};
|
||||||
use pageserver_client::mgmt_api::{self};
|
use pageserver_client::mgmt_api::{self};
|
||||||
use reqwest::{Certificate, Method, StatusCode, Url};
|
use reqwest::{Certificate, Method, StatusCode, Url};
|
||||||
|
use safekeeper_api::models::TimelineLocateResponse;
|
||||||
use storage_controller_client::control_api::Client;
|
use storage_controller_client::control_api::Client;
|
||||||
use utils::id::{NodeId, TenantId, TimelineId};
|
use utils::id::{NodeId, TenantId, TimelineId};
|
||||||
|
|
||||||
@@ -279,6 +280,23 @@ enum Command {
|
|||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
concurrency: Option<usize>,
|
concurrency: Option<usize>,
|
||||||
},
|
},
|
||||||
|
/// Locate safekeepers for a timeline from the storcon DB.
|
||||||
|
TimelineLocate {
|
||||||
|
#[arg(long)]
|
||||||
|
tenant_id: TenantId,
|
||||||
|
#[arg(long)]
|
||||||
|
timeline_id: TimelineId,
|
||||||
|
},
|
||||||
|
/// Migrate a timeline to a new set of safekeepers
|
||||||
|
TimelineSafekeeperMigrate {
|
||||||
|
#[arg(long)]
|
||||||
|
tenant_id: TenantId,
|
||||||
|
#[arg(long)]
|
||||||
|
timeline_id: TimelineId,
|
||||||
|
/// Example: --new-sk-set 1,2,3
|
||||||
|
#[arg(long, required = true, value_delimiter = ',')]
|
||||||
|
new_sk_set: Vec<NodeId>,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
@@ -1324,7 +1342,7 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
concurrency,
|
concurrency,
|
||||||
} => {
|
} => {
|
||||||
let mut path = format!(
|
let mut path = format!(
|
||||||
"/v1/tenant/{tenant_shard_id}/timeline/{timeline_id}/download_heatmap_layers",
|
"v1/tenant/{tenant_shard_id}/timeline/{timeline_id}/download_heatmap_layers",
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(c) = concurrency {
|
if let Some(c) = concurrency {
|
||||||
@@ -1335,6 +1353,41 @@ async fn main() -> anyhow::Result<()> {
|
|||||||
.dispatch::<(), ()>(Method::POST, path, None)
|
.dispatch::<(), ()>(Method::POST, path, None)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
Command::TimelineLocate {
|
||||||
|
tenant_id,
|
||||||
|
timeline_id,
|
||||||
|
} => {
|
||||||
|
let path = format!("debug/v1/tenant/{tenant_id}/timeline/{timeline_id}/locate");
|
||||||
|
|
||||||
|
let resp = storcon_client
|
||||||
|
.dispatch::<(), TimelineLocateResponse>(Method::GET, path, None)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let sk_set = resp.sk_set.iter().map(|id| id.0 as i64).collect::<Vec<_>>();
|
||||||
|
let new_sk_set = resp
|
||||||
|
.new_sk_set
|
||||||
|
.as_ref()
|
||||||
|
.map(|ids| ids.iter().map(|id| id.0 as i64).collect::<Vec<_>>());
|
||||||
|
|
||||||
|
println!("generation = {}", resp.generation);
|
||||||
|
println!("sk_set = {sk_set:?}");
|
||||||
|
println!("new_sk_set = {new_sk_set:?}");
|
||||||
|
}
|
||||||
|
Command::TimelineSafekeeperMigrate {
|
||||||
|
tenant_id,
|
||||||
|
timeline_id,
|
||||||
|
new_sk_set,
|
||||||
|
} => {
|
||||||
|
let path = format!("v1/tenant/{tenant_id}/timeline/{timeline_id}/safekeeper_migrate");
|
||||||
|
|
||||||
|
storcon_client
|
||||||
|
.dispatch::<_, ()>(
|
||||||
|
Method::POST,
|
||||||
|
path,
|
||||||
|
Some(TimelineSafekeeperMigrateRequest { new_sk_set }),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use utils::id::{NodeId, TenantId, TenantTimelineId, TimelineId};
|
|||||||
use utils::lsn::Lsn;
|
use utils::lsn::Lsn;
|
||||||
use utils::pageserver_feedback::PageserverFeedback;
|
use utils::pageserver_feedback::PageserverFeedback;
|
||||||
|
|
||||||
use crate::membership::Configuration;
|
use crate::membership::{Configuration, SafekeeperGeneration};
|
||||||
use crate::{ServerInfo, Term};
|
use crate::{ServerInfo, Term};
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
@@ -311,3 +311,12 @@ pub struct PullTimelineResponse {
|
|||||||
pub safekeeper_host: Option<String>,
|
pub safekeeper_host: Option<String>,
|
||||||
// TODO: add more fields?
|
// TODO: add more fields?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Response to a timeline locate request.
|
||||||
|
/// Storcon-only API.
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
pub struct TimelineLocateResponse {
|
||||||
|
pub generation: SafekeeperGeneration,
|
||||||
|
pub sk_set: Vec<NodeId>,
|
||||||
|
pub new_sk_set: Option<Vec<NodeId>>,
|
||||||
|
}
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ use pageserver_api::models::{SafekeeperInfo, SafekeepersInfo, TimelineInfo};
|
|||||||
use safekeeper_api::PgVersionId;
|
use safekeeper_api::PgVersionId;
|
||||||
use safekeeper_api::membership::{self, MemberSet, SafekeeperGeneration};
|
use safekeeper_api::membership::{self, MemberSet, SafekeeperGeneration};
|
||||||
use safekeeper_api::models::{
|
use safekeeper_api::models::{
|
||||||
PullTimelineRequest, TimelineMembershipSwitchRequest, TimelineMembershipSwitchResponse,
|
PullTimelineRequest, TimelineLocateResponse, TimelineMembershipSwitchRequest,
|
||||||
|
TimelineMembershipSwitchResponse,
|
||||||
};
|
};
|
||||||
use safekeeper_api::{INITIAL_TERM, Term};
|
use safekeeper_api::{INITIAL_TERM, Term};
|
||||||
use safekeeper_client::mgmt_api;
|
use safekeeper_client::mgmt_api;
|
||||||
@@ -37,13 +38,6 @@ use utils::lsn::Lsn;
|
|||||||
|
|
||||||
use super::Service;
|
use super::Service;
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize, Clone)]
|
|
||||||
pub struct TimelineLocateResponse {
|
|
||||||
pub generation: SafekeeperGeneration,
|
|
||||||
pub sk_set: Vec<NodeId>,
|
|
||||||
pub new_sk_set: Option<Vec<NodeId>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Service {
|
impl Service {
|
||||||
fn make_member_set(safekeepers: &[Safekeeper]) -> Result<MemberSet, ApiError> {
|
fn make_member_set(safekeepers: &[Safekeeper]) -> Result<MemberSet, ApiError> {
|
||||||
let members = safekeepers
|
let members = safekeepers
|
||||||
|
|||||||
Reference in New Issue
Block a user