use std::fmt;
use kmp_domain::PortError;
pub(crate) mod redb;
#[cfg(feature = "sqlite")]
pub(crate) mod sqlite;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub(crate) enum Table {
Nodes,
Relations,
RelationsByTarget,
Details,
Anchors,
EventLog,
Aggregates,
Idempotency,
Processed,
Checkpoints,
Snapshots,
Migrations,
}
impl Table {
pub(crate) const fn key_shape(self) -> KeyShape {
match self {
Table::Nodes
| Table::Details
| Table::Anchors
| Table::Aggregates
| Table::Idempotency
| Table::Migrations => KeyShape::Str,
Table::Processed | Table::Checkpoints | Table::Snapshots => KeyShape::Str2,
Table::Relations | Table::RelationsByTarget => KeyShape::Str3,
Table::EventLog => KeyShape::U64,
}
}
}
impl fmt::Display for Table {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Table::Nodes => "nodes",
Table::Relations => "relations_by_source",
Table::RelationsByTarget => "relations_by_target",
Table::Details => "details",
Table::Anchors => "memory_anchors",
Table::EventLog => "event_log",
Table::Aggregates => "aggregates",
Table::Idempotency => "idempotency",
Table::Processed => "processed_events",
Table::Checkpoints => "projection_checkpoints",
Table::Snapshots => "snapshots",
Table::Migrations => "store_migrations",
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum KeyShape {
Str,
Str2,
Str3,
U64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum Key<'a> {
Str(&'a str),
Str2(&'a str, &'a str),
Str3(&'a str, &'a str, &'a str),
U64(u64),
}
impl Key<'_> {
pub(crate) const fn shape(&self) -> KeyShape {
match self {
Key::Str(_) => KeyShape::Str,
Key::Str2(..) => KeyShape::Str2,
Key::Str3(..) => KeyShape::Str3,
Key::U64(_) => KeyShape::U64,
}
}
}
pub(crate) type StrRow = (String, Vec<u8>);
pub(crate) type Str3Row = ((String, String, String), Vec<u8>);
pub(crate) type U64Row = (u64, Vec<u8>);
pub(crate) trait ReadTx {
fn get(&self, table: Table, key: Key<'_>) -> Result<Option<Vec<u8>>, PortError>;
fn scan_str(&self, table: Table) -> Result<Vec<StrRow>, PortError>;
fn scan_str3_by_first(&self, table: Table, first: &str) -> Result<Vec<Str3Row>, PortError>;
fn scan_u64(&self, table: Table) -> Result<Vec<U64Row>, PortError>;
fn last_u64(&self, table: Table) -> Result<Option<U64Row>, PortError>;
fn count(&self, table: Table) -> Result<u64, PortError>;
}
pub(crate) trait WriteTx: ReadTx {
fn insert(&mut self, table: Table, key: Key<'_>, value: &[u8]) -> Result<(), PortError>;
fn remove(&mut self, table: Table, key: Key<'_>) -> Result<(), PortError>;
fn clear(&mut self, table: Table) -> Result<(), PortError>;
fn commit(self: Box<Self>) -> Result<(), PortError>;
}
pub(crate) trait Engine: fmt::Debug + Send + Sync {
fn begin_read(&self) -> Result<Box<dyn ReadTx + '_>, PortError>;
fn begin_write(&self) -> Result<Box<dyn WriteTx + '_>, PortError>;
}
pub(crate) fn key_shape_mismatch(table: Table, key: KeyShape) -> PortError {
PortError::InvalidState(format!(
"embedded engine: table `{table}` is keyed by {:?}, called with a {key:?} key",
table.key_shape()
))
}
pub(crate) fn scan_shape_mismatch(table: Table, wanted: KeyShape) -> PortError {
PortError::InvalidState(format!(
"embedded engine: table `{table}` is keyed by {:?}, scanned as {wanted:?}",
table.key_shape()
))
}