ENEREHTW2UEXJGIOSSKZA2FQKFDLWQEIOAD6NIT2EH6BJW6E3AZQC *db_.lock().await = Some(db);let e = connection.await;eprintln!("connection ended: {:?}", e);// Ignore "normal" restarts (i.e. promotes).let db = db_.lock().await.take();if db.is_some() {lead_.send(false).unwrap();*db_.lock().await = None;} else {debug!("normal restart, reconnecting");is_normal = true;
Err(e) => {error!("{:?}", e);lead_.send(String::new()).unwrap();
let mut race = tokio::spawn(race(host.clone(), signal.clone(), is_leader.clone()));// let addr = SocketAddr::from((// [0, 0, 0, 0],// matches// .value_of("port")// .and_then(|x| x.parse().ok())// .unwrap_or(8008),// ));
let mut race = tokio::spawn(race(host.clone(), is_leader.clone()));
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);
if leader == host {info!("promoting");pool_.execute("SELECT pg_promote()", &[]).await.unwrap_or(0);// Don't replace pool_ into *pool, since the server might restart.*pool.lock().await = Some(pool_)} else {*pool.lock().await = Some(pool_)}} else {lead.send(false)?;
*pool.lock().await = Some(pool_);}if is_leader && was_leader != Some(true) {promote(&path).await} else if !is_leader && was_leader == Some(true) {rewind(&path, port, &db_name, &leader).await
async fn rewind(path: &str, port: u16, db_name: &str, leader: &str) {use tokio::process::Command;Command::new("systemctl").args(["stop", "postgresql-repl"]).output().await.expect("failed to execute process");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").args(["start", "postgresql-repl"]).output().await.expect("failed to execute process");}
### Cooperation from the OSThe same user must run the PostgreSQL server and this tool. If that user is called `postgres`, here is a possible PolicyKit rule to make it work:``` jspolkit.addRule(function(action, subject) {if (action.id == "org.freedesktop.systemd1.manage-units" &&action.lookup("unit") == "postgresql-repl.service" &&subject.user == "postgres"){return polkit.Result.YES;}});```