refactor: name the modules after what they hold
This commit is contained in:
85
src/commands/postgres/server.rs
Normal file
85
src/commands/postgres/server.rs
Normal file
@@ -0,0 +1,85 @@
|
||||
use std::thread;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use anyhow::{Result, anyhow, bail};
|
||||
|
||||
use super::shape::Kind;
|
||||
use crate::cmd::{Cmd, PgIsReady, PgRestore, Ps, Psql};
|
||||
use crate::ctx::Ctx;
|
||||
use crate::project::Project;
|
||||
|
||||
const READY_TIMEOUT: Duration = Duration::from_secs(60);
|
||||
const POLL_INTERVAL: Duration = Duration::from_secs(1);
|
||||
|
||||
pub(super) struct Database {
|
||||
pub(super) service: String,
|
||||
pub(super) container: String,
|
||||
pub(super) user: String,
|
||||
pub(super) name: String,
|
||||
}
|
||||
|
||||
impl Database {
|
||||
pub(super) fn resolve(ctx: &Ctx) -> Result<Self> {
|
||||
let compose = Project::resolve(ctx)?;
|
||||
let service = compose.postgres()?;
|
||||
let (user, name) = compose.postgres_credentials(&service);
|
||||
|
||||
let container = Ps::id_of(&service).capture(ctx)?.trim().to_string();
|
||||
|
||||
if container.is_empty() {
|
||||
return Err(anyhow!("service {service} has no running container"));
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
service,
|
||||
container,
|
||||
user,
|
||||
name,
|
||||
})
|
||||
}
|
||||
|
||||
// what reads this shape of dump back in
|
||||
pub(super) fn restore_with(&self, kind: Kind) -> Box<dyn Cmd + '_> {
|
||||
match kind {
|
||||
Kind::Archive => Box::new(PgRestore::new(&self.user, &self.name)),
|
||||
Kind::Sql => Box::new(Psql::new(&self.user, &self.name).atomic()),
|
||||
Kind::Cluster => Box::new(Psql::new(&self.user, "postgres")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn wait_until_ready(ctx: &Ctx, db: &Database) -> Result<()> {
|
||||
if ctx.dry_run {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let deadline = Instant::now() + READY_TIMEOUT;
|
||||
|
||||
loop {
|
||||
let ready = PgIsReady {
|
||||
username: &db.user,
|
||||
dbname: &db.name,
|
||||
}
|
||||
.in_container(&db.container)
|
||||
.quietly_succeeds(ctx)?;
|
||||
|
||||
if ready {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if Instant::now() >= deadline {
|
||||
bail!(
|
||||
"{} did not accept connections within {} seconds",
|
||||
db.service,
|
||||
READY_TIMEOUT.as_secs()
|
||||
);
|
||||
}
|
||||
|
||||
thread::sleep(POLL_INTERVAL);
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn when_ready(ctx: &Ctx, db: &Database, command: &dyn Cmd) -> Result<()> {
|
||||
wait_until_ready(ctx, db)?;
|
||||
command.run(ctx)
|
||||
}
|
||||
Reference in New Issue
Block a user