From 4b09f779506c3d42cc760ece0d67be46faf059ea Mon Sep 17 00:00:00 2001 From: Mikayla Maki Date: Fri, 14 Oct 2022 16:06:18 -0700 Subject: [PATCH] WIP --- Cargo.lock | 1 + crates/client/src/telemetry.rs | 6 ++-- crates/db/src/db.rs | 52 ++++++++++++++----------------- crates/db/src/kvp.rs | 23 +++++++------- crates/db/src/serialized_item.rs | 22 +++++++++++++ crates/workspace/Cargo.toml | 1 + crates/workspace/src/workspace.rs | 27 ++++++++++++++++ 7 files changed, 88 insertions(+), 44 deletions(-) create mode 100644 crates/db/src/serialized_item.rs diff --git a/Cargo.lock b/Cargo.lock index 9b90801444..eaeb99cd2d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7524,6 +7524,7 @@ dependencies = [ "client", "collections", "context_menu", + "db", "drag_and_drop", "fs", "futures 0.3.24", diff --git a/crates/client/src/telemetry.rs b/crates/client/src/telemetry.rs index 178cee0234..1346b97f61 100644 --- a/crates/client/src/telemetry.rs +++ b/crates/client/src/telemetry.rs @@ -135,13 +135,12 @@ impl Telemetry { Some(self.state.lock().log_file.as_ref()?.path().to_path_buf()) } - pub fn start(self: &Arc, db: Arc>) { + pub fn start(self: &Arc, db: Arc) { let this = self.clone(); self.executor .spawn( async move { - let db = db.lock(); - let device_id = if let Ok(device_id) = db.read_kvp("device_id") { + let device_id = if let Ok(Some(device_id)) = db.read_kvp("device_id") { device_id } else { let device_id = Uuid::new_v4().to_string(); @@ -149,7 +148,6 @@ impl Telemetry { device_id }; - drop(db); let device_id = Some(Arc::from(device_id)); let mut state = this.state.lock(); state.device_id = device_id.clone(); diff --git a/crates/db/src/db.rs b/crates/db/src/db.rs index ed7187b567..fb71975489 100644 --- a/crates/db/src/db.rs +++ b/crates/db/src/db.rs @@ -1,5 +1,6 @@ mod kvp; mod migrations; +mod serialized_item; use anyhow::Result; use migrations::MIGRATIONS; @@ -9,9 +10,10 @@ use std::path::Path; use std::sync::Arc; pub use kvp::*; +pub use serialized_item::*; pub struct Db { - connecion: Connection, + connection: Mutex, in_memory: bool, } @@ -22,26 +24,26 @@ pub struct Db { impl Db { /// Open or create a database at the given file path. Falls back to in memory database if the /// database at the given path is corrupted - pub fn open(path: &Path) -> Result>> { + pub fn open(path: &Path) -> Result> { let conn = Connection::open(path)?; Self::initialize(conn, false).or_else(|_| Self::open_in_memory()) } /// Open a in memory database for testing and as a fallback. - pub fn open_in_memory() -> Result>> { + pub fn open_in_memory() -> Result> { let conn = Connection::open_in_memory()?; Self::initialize(conn, true) } - fn initialize(mut conn: Connection, in_memory: bool) -> Result>> { + fn initialize(mut conn: Connection, in_memory: bool) -> Result> { MIGRATIONS.to_latest(&mut conn)?; - Ok(Arc::new(Mutex::new(Self { - connecion: conn, + Ok(Arc::new(Self { + connection: Mutex::new(conn), in_memory, - }))) + })) } } @@ -57,34 +59,26 @@ mod tests { let real_db = Db::open(&dir.path().join("test.db")).unwrap(); for db in [&real_db, &fake_db] { - assert_eq!( - db.read(["key-1", "key-2", "key-3"]).unwrap(), - &[None, None, None] - ); + assert_eq!(db.read_kvp("key-1").unwrap(), None); - db.write([("key-1", "one"), ("key-3", "three")]).unwrap(); - assert_eq!( - db.read(["key-1", "key-2", "key-3"]).unwrap(), - &[ - Some("one".as_bytes().to_vec()), - None, - Some("three".as_bytes().to_vec()) - ] - ); + db.write_kvp("key-1", "one").unwrap(); + assert_eq!(db.read_kvp("key-1").unwrap(), Some("one".to_string())); - db.delete(["key-3", "key-4"]).unwrap(); - assert_eq!( - db.read(["key-1", "key-2", "key-3"]).unwrap(), - &[Some("one".as_bytes().to_vec()), None, None,] - ); + db.write_kvp("key-2", "two").unwrap(); + assert_eq!(db.read_kvp("key-2").unwrap(), Some("two".to_string())); + + db.delete_kvp("key-1").unwrap(); + assert_eq!(db.read_kvp("key-1").unwrap(), None); } drop(real_db); let real_db = Db::open(&dir.path().join("test.db")).unwrap(); - assert_eq!( - real_db.read(["key-1", "key-2", "key-3"]).unwrap(), - &[Some("one".as_bytes().to_vec()), None, None,] - ); + + real_db.write_kvp("key-1", "one").unwrap(); + assert_eq!(real_db.read_kvp("key-1").unwrap(), None); + + real_db.write_kvp("key-2", "two").unwrap(); + assert_eq!(real_db.read_kvp("key-2").unwrap(), Some("two".to_string())); } } diff --git a/crates/db/src/kvp.rs b/crates/db/src/kvp.rs index d7a2828da9..d23e6ae5b0 100644 --- a/crates/db/src/kvp.rs +++ b/crates/db/src/kvp.rs @@ -1,20 +1,20 @@ use anyhow::Result; +use rusqlite::OptionalExtension; use super::Db; impl Db { - pub fn read_kvp(&self, key: &str) -> Result { - let mut stmt = self - .connecion - .prepare_cached("SELECT value FROM kv_store WHERE key = (?)")?; + pub fn read_kvp(&self, key: &str) -> Result> { + let lock = self.connection.lock(); + let mut stmt = lock.prepare_cached("SELECT value FROM kv_store WHERE key = (?)")?; - Ok(stmt.query_row([key], |row| row.get(0))?) + Ok(stmt.query_row([key], |row| row.get(0)).optional()?) } pub fn delete_kvp(&self, key: &str) -> Result<()> { - let mut stmt = self - .connecion - .prepare_cached("SELECT value FROM kv_store WHERE key = (?)")?; + let lock = self.connection.lock(); + + let mut stmt = lock.prepare_cached("SELECT value FROM kv_store WHERE key = (?)")?; stmt.execute([key])?; @@ -22,9 +22,10 @@ impl Db { } pub fn write_kvp(&self, key: &str, value: &str) -> Result<()> { - let mut stmt = self - .connecion - .prepare_cached("INSERT OR REPLACE INTO kv_store(key, value) VALUES ((?), (?))")?; + let lock = self.connection.lock(); + + let mut stmt = + lock.prepare_cached("INSERT OR REPLACE INTO kv_store(key, value) VALUES ((?), (?))")?; stmt.execute([key, value])?; diff --git a/crates/db/src/serialized_item.rs b/crates/db/src/serialized_item.rs new file mode 100644 index 0000000000..9f6284fa07 --- /dev/null +++ b/crates/db/src/serialized_item.rs @@ -0,0 +1,22 @@ +use std::path::PathBuf; + +use anyhow::Result; + +use super::Db; + +impl Db {} + +#[derive(PartialEq, Eq, Hash)] +pub enum SerializedItemKind { + Editor, + Terminal, + ProjectSearch, + Diagnostics, +} + +pub enum SerializedItem { + Editor(PathBuf, String), + Terminal, + ProjectSearch(String), + Diagnostics, +} diff --git a/crates/workspace/Cargo.toml b/crates/workspace/Cargo.toml index 54e7eaf463..b68636b50f 100644 --- a/crates/workspace/Cargo.toml +++ b/crates/workspace/Cargo.toml @@ -23,6 +23,7 @@ client = { path = "../client" } collections = { path = "../collections" } context_menu = { path = "../context_menu" } drag_and_drop = { path = "../drag_and_drop" } +db = { path = "../db" } fs = { path = "../fs" } gpui = { path = "../gpui" } language = { path = "../language" } diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index ece8cedfb1..95ab8c4964 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -14,6 +14,7 @@ use anyhow::{anyhow, Context, Result}; use call::ActiveCall; use client::{proto, Client, PeerId, TypedEnvelope, UserStore}; use collections::{hash_map, HashMap, HashSet}; +use db::{SerializedItem, SerializedItemKind}; use dock::{DefaultItemFactory, Dock, ToggleDockButton}; use drag_and_drop::DragAndDrop; use fs::{self, Fs}; @@ -77,6 +78,9 @@ type FollowableItemBuilders = HashMap< ), >; +type ItemDeserializers = + HashMap) -> Box>; + #[derive(Clone, PartialEq)] pub struct RemoveWorktreeFromProject(pub WorktreeId); @@ -230,6 +234,14 @@ pub fn register_followable_item(cx: &mut MutableAppContext) { }); } +pub fn register_deserializable_item(cx: &mut MutableAppContext) { + cx.update_default_global(|deserializers: &mut ItemDeserializers, _| { + deserializers.insert(I::serialized_item_kind(), |serialized_item, cx| { + Box::new(cx.add_view(|cx| I::deserialize(serialized_item, cx))) + }) + }); +} + pub struct AppState { pub languages: Arc, pub themes: Arc, @@ -333,6 +345,9 @@ pub trait Item: View { fn breadcrumbs(&self, _theme: &Theme, _cx: &AppContext) -> Option> { None } + fn serialized_item_kind() -> SerializedItemKind; + fn deserialize(serialized_item: SerializedItem, cx: &mut ViewContext) -> Self; + fn serialize(&self) -> SerializedItem; } pub trait ProjectItem: Item { @@ -3611,6 +3626,18 @@ mod tests { fn to_item_events(_: &Self::Event) -> Vec { vec![ItemEvent::UpdateTab, ItemEvent::Edit] } + + fn serialized_item_kind() -> SerializedItemKind { + unimplemented!() + } + + fn deserialize(_serialized_item: SerializedItem, _cx: &mut ViewContext) -> Self { + unimplemented!() + } + + fn serialize(&self) -> SerializedItem { + unimplemented!() + } } impl SidebarItem for TestItem {}