use crate::RelationalBackend;
use crate::conformance::Leaf;
use crate::contract;
use crate::speed::{SpeedTable, Workload};
use persistant_core::Config;
pub use persistant_core::choose::{
Candidate, Choice, Declared, Durability, Entry, Excluded, Need, NoneEligible, Unmeasured, Why,
};
pub fn declared_durability(backend: &str) -> Option<Declared> {
let d = |class, basis| {
Some(Declared {
class,
basis,
verified: None,
})
};
match backend {
"sqlite" => d(
Durability::Process,
"SQLite WAL file; sqlx's default synchronous=FULL is documented but not asserted or tested here",
),
"postgres" => d(
Durability::Machine,
"PostgreSQL defaults (fsync=on, synchronous_commit=on); documented, no power-loss test",
),
"mysql" => d(
Durability::Machine,
"InnoDB defaults (innodb_flush_log_at_trx_commit=1); documented, no power-loss test",
),
_ => None,
}
}
pub fn need(
leaves: &[Leaf],
min_durability: Durability,
rank_by: Workload,
environment: impl Into<String>,
) -> Need {
Need {
leaves: leaves.iter().map(|l| l.id().to_string()).collect(),
min_durability,
rank_by: rank_by.id().to_string(),
environment: environment.into(),
}
}
pub fn choose(
candidates: &[Candidate],
need: &Need,
speed: &SpeedTable,
) -> Result<Choice, NoneEligible> {
persistant_core::choose::choose(candidates, need, speed, &declared_durability)
}
pub async fn candidate<R: RelationalBackend>(
target: &R,
config: &Config,
leaves: &[Leaf],
) -> Candidate {
Candidate {
backend: target.backend().to_string(),
version: target.version().to_string(),
config: config.clone(),
eligibility: contract::check(target, leaves).await,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn no_relational_backend_is_marked_verified_and_an_unknown_one_is_unknown() {
for b in ["sqlite", "postgres", "mysql"] {
assert!(declared_durability(b).expect(b).verified.is_none(), "{b}");
}
assert!(declared_durability("some-other-db").is_none());
}
}