Distributed database pattern built.

Co-Authored-By: kay@zed.dev
This commit is contained in:
Mikayla Maki 2022-11-14 13:18:44 -08:00
parent 2a5565ca93
commit 4798161118
28 changed files with 893 additions and 937 deletions

View file

@ -1,11 +1,12 @@
pub mod kvp;
use std::fs;
use std::ops::Deref;
use std::path::Path;
#[cfg(any(test, feature = "test-support"))]
use anyhow::Result;
use indoc::indoc;
#[cfg(any(test, feature = "test-support"))]
use sqlez::connection::Connection;
use sqlez::domain::Domain;
use sqlez::thread_safe_connection::ThreadSafeConnection;
@ -17,47 +18,29 @@ const INITIALIZE_QUERY: &'static str = indoc! {"
PRAGMA case_sensitive_like=TRUE;
"};
#[derive(Clone)]
pub struct Db<D: Domain>(ThreadSafeConnection<D>);
/// Open or create a database at the given directory path.
pub fn open_file_db<D: Domain>() -> ThreadSafeConnection<D> {
// Use 0 for now. Will implement incrementing and clearing of old db files soon TM
let current_db_dir = (*util::paths::DB_DIR).join(Path::new(&format!(
"0-{}",
*util::channel::RELEASE_CHANNEL_NAME
)));
fs::create_dir_all(&current_db_dir).expect("Should be able to create the database directory");
let db_path = current_db_dir.join(Path::new("db.sqlite"));
impl<D: Domain> Deref for Db<D> {
type Target = sqlez::connection::Connection;
fn deref(&self) -> &Self::Target {
&self.0.deref()
}
ThreadSafeConnection::new(db_path.to_string_lossy().as_ref(), true)
.with_initialize_query(INITIALIZE_QUERY)
}
impl<D: Domain> Db<D> {
/// Open or create a database at the given directory path.
pub fn open(db_dir: &Path, channel: &'static str) -> Self {
// Use 0 for now. Will implement incrementing and clearing of old db files soon TM
let current_db_dir = db_dir.join(Path::new(&format!("0-{}", channel)));
fs::create_dir_all(&current_db_dir)
.expect("Should be able to create the database directory");
let db_path = current_db_dir.join(Path::new("db.sqlite"));
Db(
ThreadSafeConnection::new(db_path.to_string_lossy().as_ref(), true)
.with_initialize_query(INITIALIZE_QUERY),
)
}
/// Open a in memory database for testing and as a fallback.
pub fn open_in_memory(db_name: &str) -> Self {
Db(ThreadSafeConnection::new(db_name, false).with_initialize_query(INITIALIZE_QUERY))
}
pub fn persisting(&self) -> bool {
self.persistent()
}
pub fn write_to<P: AsRef<Path>>(&self, dest: P) -> Result<()> {
let destination = Connection::open_file(dest.as_ref().to_string_lossy().as_ref());
self.backup_main(&destination)
}
pub fn open_as<D2: Domain>(&self) -> Db<D2> {
Db(self.0.for_domain())
}
pub fn open_memory_db<D: Domain>(db_name: &str) -> ThreadSafeConnection<D> {
ThreadSafeConnection::new(db_name, false).with_initialize_query(INITIALIZE_QUERY)
}
#[cfg(any(test, feature = "test-support"))]
pub fn write_db_to<D: Domain, P: AsRef<Path>>(
conn: &ThreadSafeConnection<D>,
dest: P,
) -> Result<()> {
let destination = Connection::open_file(dest.as_ref().to_string_lossy().as_ref());
conn.backup_main(&destination)
}

View file

@ -1,7 +1,11 @@
use super::Db;
use anyhow::Result;
use indoc::indoc;
use sqlez::{connection::Connection, domain::Domain, migrations::Migration};
use sqlez::{
connection::Connection, domain::Domain, migrations::Migration,
thread_safe_connection::ThreadSafeConnection,
};
use std::ops::Deref;
pub(crate) const KVP_MIGRATION: Migration = Migration::new(
"kvp",
@ -13,16 +17,29 @@ pub(crate) const KVP_MIGRATION: Migration = Migration::new(
"}],
);
#[derive(Clone)]
pub enum KeyValue {}
lazy_static::lazy_static! {
pub static ref KEY_VALUE_STORE: KeyValueStore =
KeyValueStore(crate::open_file_db());
}
impl Domain for KeyValue {
#[derive(Clone)]
pub struct KeyValueStore(ThreadSafeConnection<KeyValueStore>);
impl Domain for KeyValueStore {
fn migrate(conn: &Connection) -> anyhow::Result<()> {
KVP_MIGRATION.run(conn)
}
}
impl Db<KeyValue> {
impl Deref for KeyValueStore {
type Target = ThreadSafeConnection<KeyValueStore>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl KeyValueStore {
pub fn read_kvp(&self, key: &str) -> Result<Option<String>> {
self.select_row_bound("SELECT value FROM kv_store WHERE key = (?)")?(key)
}
@ -44,11 +61,11 @@ impl Db<KeyValue> {
mod tests {
use anyhow::Result;
use super::*;
use crate::kvp::KeyValueStore;
#[test]
fn test_kvp() -> Result<()> {
let db = Db::open_in_memory("test_kvp");
let db = KeyValueStore(crate::open_memory_db("test_kvp"));
assert_eq!(db.read_kvp("key-1").unwrap(), None);