FIIWK33FEEUURH7QGHQPHGQHSVN7XXLDDPLI5CKKWRK2DGIAHLGAC
info!(
"Lock acquired: {:?} {:?}",
std::str::from_utf8(leader_key.name()),
std::str::from_utf8(leader_key.key())
);
debug!("Lock acquired {:?}", leader_key);
promote(&path).await;
let mut was_leader = {
if let Some(pool_) = pool.lock().await.take() {
let row = pool_.query_one("SELECT pg_is_in_recovery()", &[]).await?;
let is_in_recovery: bool = row.get(0);
*pool.lock().await = Some(pool_);
Some(!is_in_recovery)
} else {
None
}
};
debug!("was_leader = {:?}", was_leader);
} else if !is_leader && was_leader == Some(true) {
rewind(&path, port, &db_name, &leader).await
} else if !is_leader && was_leader != Some(false) {
let pool_ = { pool.lock().await.take() };
let recov: bool = if let Some(pool_) = pool_ {
let row = pool_.query_one("SELECT pg_is_in_recovery()", &[]).await?;
*pool.lock().await = Some(pool_);
row.get(0)
} else {
false
};
debug!("recov = {:?}", recov);
if !recov {
rewind(&path, port, &db_name, leader).await;
}
Command::new("pg_rewind")
.args([
"-D",
&path,
"-R",
"--source-server",
&format!(
"port={} user=postgres dbname={} host={}",
port, db_name, leader
),
])
.output()
.await
.expect("failed to execute process");
Command::new("systemctl")
use std::io::Write;
std::io::stdout().write_all(&out.stdout).unwrap();
std::io::stderr().write_all(&out.stderr).unwrap();
let mut success = false;
while !success {
// Waiting for source to promote.
let out = Command::new("pg_rewind")
.args([
"-D",
&path,
"-R",
"--source-server",
&format!(
"port={} user=postgres dbname={} host={}",
port, db_name, leader
),
])
.output()
.await
.expect("failed to execute process");
std::io::stdout().write_all(&out.stdout).unwrap();
std::io::stderr().write_all(&out.stderr).unwrap();
success = out.status.success();
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
}
let out = Command::new("systemctl")
Postrep uses a fixed replication strategy (streaming replication), a fixed leader election tool (Etcd 3), to achieve proper failover when the cluster leader fails.
Postrep uses a leader election tool (Etcd 3), to achieve proper failover when the cluster leader fails, in the context of PostgreSQL's streaming replication feature.
This crate solves this problem, in the particular configuration where one has an Etcd v3 server running, for example because of requirements from another server running on the same service.
Failover between the leader and replica mode of PostgreSQL isn't automatic, and requires another protocol to decide which of the replicae becomes the leader when the previous leader fails.