Add library

This commit is contained in:
Bojan Serafimov
2022-08-18 12:40:14 -04:00
parent 11a1f2a1d8
commit 7bff7c4014
6 changed files with 106 additions and 85 deletions

8
Cargo.lock generated
View File

@@ -1414,6 +1414,7 @@ name = "integration_tests"
version = "0.1.0"
dependencies = [
"anyhow",
"pg_bin",
"tokio",
"tokio-postgres",
"utils",
@@ -1988,6 +1989,13 @@ dependencies = [
"indexmap",
]
[[package]]
name = "pg_bin"
version = "0.1.0"
dependencies = [
"tokio-postgres",
]
[[package]]
name = "phf"
version = "0.10.1"

View File

@@ -7,6 +7,7 @@ edition = "2021"
[dependencies]
utils = { path = "../libs/utils" }
pg_bin = { path = "../libs/pg_bin" }
tokio-postgres = { git = "https://github.com/zenithdb/rust-postgres.git", rev="d052ee8b86fff9897c77b0fe89ea9daba0e1fa38" }
tokio = { version = "1.17", features = ["macros", "rt", "rt-multi-thread"] }
anyhow = "1.0.62"

View File

@@ -1,91 +1,10 @@
use std::{fs::{File, remove_dir_all}, path::PathBuf, process::{Child, Command, Stdio}, time::Duration};
use std::io::Write;
pub trait PgProtocol {
fn conn_info(&self) -> tokio_postgres::Config;
}
type Port = u16;
pub struct LocalPostgres {
datadir: PathBuf,
pg_prefix: PathBuf,
port: Port,
running: Option<Child>,
}
impl LocalPostgres {
fn new(datadir: PathBuf, pg_prefix: PathBuf) -> Self {
LocalPostgres {
datadir,
pg_prefix,
port: 54729,
running: None,
}
}
fn start(&mut self) {
remove_dir_all(self.datadir.as_os_str()).ok();
let status = Command::new(self.pg_prefix.join("initdb"))
.arg("-D")
.arg(self.datadir.as_os_str())
.stdout(Stdio::null()) // TODO to file instead
.stderr(Stdio::null()) // TODO to file instead
.status()
.expect("failed to get status");
assert!(status.success());
// Write conf
let mut conf = File::create(self.datadir.join("postgresql.conf"))
.expect("failed to create file");
writeln!(&mut conf, "port = {}", self.port)
.expect("failed to write conf");
let out_file = File::create(self.datadir.join("pg.log")).expect("can't make file");
let err_file = File::create(self.datadir.join("pg.err")).expect("can't make file");
self.running.replace(Command::new(self.pg_prefix.join("postgres"))
.env("PGDATA", self.datadir.as_os_str())
.stdout(Stdio::from(out_file))
.stderr(Stdio::from(err_file))
.spawn()
.expect("postgres failed to spawn"));
std::thread::sleep(Duration::from_millis(300));
}
}
impl Drop for LocalPostgres {
fn drop(&mut self) {
if let Some(mut child) = self.running.take() {
child.kill().expect("failed to kill child");
}
}
}
impl PgProtocol for LocalPostgres {
fn conn_info(&self) -> tokio_postgres::Config {
// I don't like this, but idk what else to do
let whoami = Command::new("whoami").output().unwrap().stdout;
let user = String::from_utf8_lossy(&whoami);
let user = user.trim();
let mut config = tokio_postgres::Config::new();
config
.host("127.0.0.1")
.port(self.port)
.dbname("postgres")
.user(&user);
config
}
}
#[cfg(test)]
mod tests {
use tokio_postgres::NoTls;
use std::path::PathBuf;
use super::*;
use tokio_postgres::NoTls;
use pg_bin::LocalPostgres;
use pg_bin::PgProtocol;
#[tokio::test]
async fn test_postgres_select_1() -> anyhow::Result<()> {

9
libs/pg_bin/Cargo.toml Normal file
View File

@@ -0,0 +1,9 @@
[package]
name = "pg_bin"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tokio-postgres = { git = "https://github.com/zenithdb/rust-postgres.git", rev="d052ee8b86fff9897c77b0fe89ea9daba0e1fa38" }

84
libs/pg_bin/src/lib.rs Normal file
View File

@@ -0,0 +1,84 @@
//! Utils for runnig postgres binaries as subprocesses.
use std::{fs::{File, remove_dir_all}, path::PathBuf, process::{Child, Command, Stdio}, time::Duration};
use std::io::Write;
// TODO put these in a different mod
type Port = u16;
pub trait PgProtocol {
fn conn_info(&self) -> tokio_postgres::Config;
}
pub struct LocalPostgres {
datadir: PathBuf,
pg_prefix: PathBuf,
port: Port,
running: Option<Child>,
}
impl LocalPostgres {
pub fn new(datadir: PathBuf, pg_prefix: PathBuf) -> Self {
LocalPostgres {
datadir,
pg_prefix,
port: 54729,
running: None,
}
}
// TODO is this the right interface? Why not start it?
pub fn start(&mut self) {
remove_dir_all(self.datadir.as_os_str()).ok();
let status = Command::new(self.pg_prefix.join("initdb"))
.arg("-D")
.arg(self.datadir.as_os_str())
.stdout(Stdio::null()) // TODO to file instead
.stderr(Stdio::null()) // TODO to file instead
.status()
.expect("failed to get status");
assert!(status.success());
// Write conf
let mut conf = File::create(self.datadir.join("postgresql.conf"))
.expect("failed to create file");
writeln!(&mut conf, "port = {}", self.port)
.expect("failed to write conf");
// TODO check if already running
let out_file = File::create(self.datadir.join("pg.log")).expect("can't make file");
let err_file = File::create(self.datadir.join("pg.err")).expect("can't make file");
self.running.replace(Command::new(self.pg_prefix.join("postgres"))
.env("PGDATA", self.datadir.as_os_str())
.stdout(Stdio::from(out_file))
.stderr(Stdio::from(err_file))
.spawn()
.expect("postgres failed to spawn"));
std::thread::sleep(Duration::from_millis(300));
}
}
impl Drop for LocalPostgres {
fn drop(&mut self) {
if let Some(mut child) = self.running.take() {
child.kill().expect("failed to kill child");
}
}
}
impl PgProtocol for LocalPostgres {
fn conn_info(&self) -> tokio_postgres::Config {
// I don't like this, but idk what else to do
let whoami = Command::new("whoami").output().unwrap().stdout;
let user = String::from_utf8_lossy(&whoami);
let user = user.trim();
let mut config = tokio_postgres::Config::new();
config
.host("127.0.0.1")
.port(self.port)
.dbname("postgres")
.user(&user);
config
}
}

0
libs/utils/src/pg_bin.rs Normal file
View File