bestool-postgres 1.2.0

PostgreSQL connection pool utilities for BES tooling
Documentation
//! Rendering and splicing of the managed tuning block in `postgresql.conf`.
//!
//! The block is a run of `key = value` lines bounded by a begin and end marker,
//! kept at the end of the file so its settings override any earlier occurrence.
//! Splicing is idempotent: re-applying an unchanged block leaves the file byte
//! for byte identical.

use super::Setting;

/// Opening marker of the managed block.
pub const BEGIN: &str =
	"# BEGIN PGTUNE — generated by `bestool tamanu pg-tune`, do not edit by hand";
/// Closing marker of the managed block.
pub const END: &str = "# END PGTUNE";

/// The prefix of a header left by hand-tuning before this command existed.
const LEGACY_HEADER: &str = "# PGTUNE";

/// Render a tuning set as a marker-delimited block, terminated by a newline.
pub fn render(settings: &[Setting]) -> String {
	let mut out = String::new();
	out.push_str(BEGIN);
	out.push('\n');
	for setting in settings {
		out.push_str(setting.key);
		out.push_str(" = ");
		out.push_str(&setting.value);
		out.push('\n');
	}
	out.push_str(END);
	out.push('\n');
	out
}

/// Return `existing` with `block` spliced in.
///
/// When the markers are already present, the content between them (inclusive) is
/// replaced. Otherwise, when a legacy `# PGTUNE` header is present, everything
/// from that header to the end of the file is replaced. Otherwise the block is
/// appended after a blank line.
pub fn splice(existing: &str, block: &str) -> String {
	let block_lines: Vec<&str> = block.trim_end_matches('\n').split('\n').collect();
	let lines: Vec<&str> = if existing.is_empty() {
		Vec::new()
	} else {
		existing.split('\n').collect()
	};

	let begin = lines.iter().position(|l| l.trim_end() == BEGIN);
	let end = lines.iter().position(|l| l.trim_end() == END);

	let mut result: Vec<&str> = Vec::new();
	match (begin, end) {
		(Some(b), Some(e)) if b <= e => {
			result.extend_from_slice(&lines[..b]);
			result.extend_from_slice(&block_lines);
			result.extend_from_slice(&lines[e + 1..]);
		}
		_ => {
			let cut = lines
				.iter()
				.position(|l| l.trim_start().starts_with(LEGACY_HEADER))
				.unwrap_or(lines.len());
			result.extend_from_slice(&lines[..cut]);
			trim_trailing_empty(&mut result);
			if !result.is_empty() {
				result.push("");
			}
			result.extend_from_slice(&block_lines);
		}
	}

	trim_trailing_empty(&mut result);
	let mut out = result.join("\n");
	out.push('\n');
	out
}

fn trim_trailing_empty(lines: &mut Vec<&str>) {
	while lines.last().is_some_and(|l| l.trim().is_empty()) {
		lines.pop();
	}
}

#[cfg(test)]
mod tests {
	use super::*;

	fn sample_block() -> String {
		render(&[
			Setting::new("shared_buffers", "1GB"),
			Setting::new("work_mem", "16MB"),
		])
	}

	#[test]
	fn appends_to_a_file_without_markers() {
		let existing = "listen_addresses = '*'\nport = 5432\n";
		let out = splice(existing, &sample_block());
		assert!(out.starts_with("listen_addresses = '*'\nport = 5432\n\n# BEGIN PGTUNE"));
		assert!(out.ends_with("# END PGTUNE\n"));
		assert!(out.contains("shared_buffers = 1GB"));
	}

	#[test]
	fn replaces_between_existing_markers() {
		let first = splice("port = 5432\n", &sample_block());
		let updated = render(&[Setting::new("shared_buffers", "2GB")]);
		let second = splice(&first, &updated);
		assert!(second.contains("shared_buffers = 2GB"));
		assert!(!second.contains("shared_buffers = 1GB"));
		assert!(!second.contains("work_mem"));
		// preceding content untouched, markers not duplicated
		assert!(second.starts_with("port = 5432\n"));
		assert_eq!(second.matches(BEGIN).count(), 1);
		assert_eq!(second.matches(END).count(), 1);
	}

	#[test]
	fn migrates_a_legacy_header_to_eof() {
		let existing = "port = 5432\n\n# PGTUNE https://pgtune.leopard.in.ua/\nshared_buffers = 512MB\nwork_mem = 8MB\n";
		let out = splice(existing, &sample_block());
		assert!(out.starts_with("port = 5432\n"));
		assert!(!out.contains("# PGTUNE https"));
		assert!(!out.contains("512MB"));
		assert!(out.contains("# BEGIN PGTUNE"));
		assert!(out.contains("shared_buffers = 1GB"));
		assert!(out.ends_with("# END PGTUNE\n"));
	}

	#[test]
	fn is_idempotent() {
		let block = sample_block();
		let once = splice("port = 5432\n", &block);
		let twice = splice(&once, &block);
		assert_eq!(once, twice);
	}

	#[test]
	fn empty_file_gets_only_the_block() {
		let out = splice("", &sample_block());
		assert!(out.starts_with("# BEGIN PGTUNE"));
		assert!(out.ends_with("# END PGTUNE\n"));
	}
}