use std::path::PathBuf;
use banshee_config::BansheeConfig;
use banshee_schema::{CachedSchemaProvider, SchemaSnapshot, cache, fingerprint};
const DEFAULT_TTL_SECS: u64 = 3600;
pub fn base_dir() -> PathBuf {
std::env::current_dir().unwrap_or_else(|_| PathBuf::from("."))
}
pub fn config_fingerprint(config: &BansheeConfig) -> Option<String> {
config
.database
.resolve_url()
.map(|url| fingerprint(&url, &config.database.schema))
}
pub fn force_refresh(config: &BansheeConfig) -> anyhow::Result<Option<SchemaSnapshot>> {
let db = &config.database;
let Some(url) = db.resolve_url() else {
return Ok(None);
};
refresh_snapshot(&base_dir(), &url, db)
}
#[cfg(feature = "db")]
fn refresh_snapshot(
base: &std::path::Path,
url: &str,
db: &banshee_config::DatabaseSettings,
) -> anyhow::Result<Option<SchemaSnapshot>> {
use std::time::Duration;
let runtime = tokio::runtime::Runtime::new()?;
let snapshot = runtime.block_on(banshee_schema::introspect(
url,
&db.schema,
db.pool_size,
Duration::from_secs(db.connect_timeout_secs),
))?;
cache::save(base, &snapshot)?;
Ok(Some(snapshot))
}
#[cfg(not(feature = "db"))]
fn refresh_snapshot(
_base: &std::path::Path,
_url: &str,
_db: &banshee_config::DatabaseSettings,
) -> anyhow::Result<Option<SchemaSnapshot>> {
anyhow::bail!("schema refresh requires a build with the `db` feature");
}
pub fn resolve(config: &BansheeConfig) -> anyhow::Result<Option<CachedSchemaProvider>> {
let db = &config.database;
let Some(url) = db.resolve_url() else {
return Ok(None);
};
let fp = fingerprint(&url, &db.schema);
let base = std::env::current_dir().unwrap_or_else(|_| std::path::PathBuf::from("."));
if let Some(snap) = cache::load_fresh(&base, &fp, DEFAULT_TTL_SECS) {
return Ok(Some(CachedSchemaProvider::new(snap)));
}
refresh(&base, &url, db, &fp)
}
#[cfg(feature = "db")]
fn refresh(
base: &std::path::Path,
url: &str,
db: &banshee_config::DatabaseSettings,
_fp: &str,
) -> anyhow::Result<Option<CachedSchemaProvider>> {
use std::time::Duration;
let runtime = tokio::runtime::Runtime::new()?;
let snapshot = runtime.block_on(banshee_schema::introspect(
url,
&db.schema,
db.pool_size,
Duration::from_secs(db.connect_timeout_secs),
))?;
if let Err(e) = cache::save(base, &snapshot) {
eprintln!("warning: could not write schema cache: {e}");
}
Ok(Some(CachedSchemaProvider::new(snapshot)))
}
#[cfg(not(feature = "db"))]
fn refresh(
base: &std::path::Path,
_url: &str,
_db: &banshee_config::DatabaseSettings,
_fp: &str,
) -> anyhow::Result<Option<CachedSchemaProvider>> {
Ok(cache::load(base).map(CachedSchemaProvider::new))
}