pub mod memory;
#[cfg(feature = "postgres")]
pub mod postgres;
#[cfg(feature = "sqlite")]
pub mod sqlite;
use std::str::FromStr;
#[cfg(feature = "diesel")]
use diesel::r2d2::{ConnectionManager, Pool};
pub trait StoreFactory {
#[cfg(feature = "pike")]
fn get_grid_agent_store(&self) -> Box<dyn crate::agents::AgentStore>;
fn get_grid_commit_store(&self) -> Box<dyn crate::commits::CommitStore>;
#[cfg(feature = "pike")]
fn get_grid_organization_store(&self) -> Box<dyn crate::organizations::OrganizationStore>;
#[cfg(feature = "location")]
fn get_grid_location_store(&self) -> Box<dyn crate::locations::LocationStore>;
#[cfg(feature = "product")]
fn get_grid_product_store(&self) -> Box<dyn crate::products::ProductStore>;
#[cfg(feature = "schema")]
fn get_grid_schema_store(&self) -> Box<dyn crate::schemas::SchemaStore>;
#[cfg(feature = "track-and-trace")]
fn get_grid_track_and_trace_store(&self)
-> Box<dyn crate::track_and_trace::TrackAndTraceStore>;
}
pub fn create_store_factory(
connection_uri: &ConnectionUri,
) -> Result<Box<dyn StoreFactory>, StoreFactoryCreationError> {
match connection_uri {
ConnectionUri::Memory => Ok(Box::new(memory::MemoryStoreFactory::new())),
#[cfg(feature = "postgres")]
ConnectionUri::Postgres(url) => {
let connection_manager = ConnectionManager::<diesel::pg::PgConnection>::new(url);
let pool = Pool::builder().build(connection_manager).map_err(|err| {
StoreFactoryCreationError(format!("Failed to build connection pool: {}", err))
})?;
Ok(Box::new(postgres::PgStoreFactory::new(pool)))
}
#[cfg(feature = "sqlite")]
ConnectionUri::Sqlite(conn_str) => {
let connection_manager =
ConnectionManager::<diesel::sqlite::SqliteConnection>::new(conn_str);
let mut pool_builder = Pool::builder();
if conn_str == ":memory:" {
pool_builder = pool_builder.max_size(1);
}
let pool = pool_builder.build(connection_manager).map_err(|err| {
StoreFactoryCreationError(format!("Failed to build connection pool: {}", err))
})?;
Ok(Box::new(sqlite::SqliteStoreFactory::new(pool)))
}
}
}
#[derive(Debug)]
pub struct StoreFactoryCreationError(pub String);
impl std::error::Error for StoreFactoryCreationError {}
impl std::fmt::Display for StoreFactoryCreationError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "Unable to create store factory: {}", self.0)
}
}
#[derive(Clone)]
pub enum ConnectionUri {
Memory,
#[cfg(feature = "postgres")]
Postgres(String),
#[cfg(feature = "sqlite")]
Sqlite(String),
}
impl FromStr for ConnectionUri {
type Err = ParseConnectionUriError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"memory" => Ok(ConnectionUri::Memory),
#[cfg(feature = "postgres")]
_ if s.starts_with("postgres://") => Ok(ConnectionUri::Postgres(s.into())),
#[cfg(feature = "sqlite")]
_ => Ok(ConnectionUri::Sqlite(s.into())),
#[cfg(not(feature = "sqlite"))]
_ => Err(ParseConnectionUriError(format!(
"No compatible connection type: {}",
s
))),
}
}
}
#[derive(Debug)]
pub struct ParseConnectionUriError(pub String);
impl std::error::Error for ParseConnectionUriError {}
impl std::fmt::Display for ParseConnectionUriError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "Unable to parse connection URI from string: {}", self.0)
}
}