Files
oak-gpui/crates/component_preview/src/persistence.rs
T
Kirill Bulatov f106dfca42 Avoid unnecessary DB writes (#29417)
Part of https://github.com/zed-industries/zed/issues/16472

* Adds debug logging to everywhere near INSERT/UPDATEs in the DB

So something like 
`env RUST_LOG=debug,wasmtime_cranelift=off,cranelift_codegen=off,vte=off
cargo run` could be used to view these (current zlog seems to process
the exclusions odd, so not sure this is the optimal RUST_LOG line) can
be used to debug any further writes.

* Removes excessive window stack serialization

Previously, it serialized unconditionally every 100ms.
Now, only if the stack had changed, which is now check every 500ms.

* Removes excessive terminal serialization

Previously, it serialized its `cwd` on every `ItemEvent::UpdateTab`
which was caused by e.g. any character output.
Now, only if the `cwd` has changed at the next event processing time.

Release Notes:

- Fixed more excessive DB writes
2025-04-25 17:41:49 +03:00

77 lines
2.5 KiB
Rust

use anyhow::Result;
use db::{define_connection, query, sqlez::statement::Statement, sqlez_macros::sql};
use workspace::{ItemId, WorkspaceDb, WorkspaceId};
define_connection! {
pub static ref COMPONENT_PREVIEW_DB: ComponentPreviewDb<WorkspaceDb> =
&[sql!(
CREATE TABLE component_previews (
workspace_id INTEGER,
item_id INTEGER UNIQUE,
active_page_id TEXT,
PRIMARY KEY(workspace_id, item_id),
FOREIGN KEY(workspace_id) REFERENCES workspaces(workspace_id)
ON DELETE CASCADE
) STRICT;
)];
}
impl ComponentPreviewDb {
pub async fn save_active_page(
&self,
item_id: ItemId,
workspace_id: WorkspaceId,
active_page_id: String,
) -> Result<()> {
log::debug!(
"Saving active page: item_id={item_id:?}, workspace_id={workspace_id:?}, active_page_id={active_page_id}"
);
let query = "INSERT INTO component_previews(item_id, workspace_id, active_page_id)
VALUES (?1, ?2, ?3)
ON CONFLICT DO UPDATE SET
active_page_id = ?3";
self.write(move |conn| {
let mut statement = Statement::prepare(conn, query)?;
let mut next_index = statement.bind(&item_id, 1)?;
next_index = statement.bind(&workspace_id, next_index)?;
statement.bind(&active_page_id, next_index)?;
statement.exec()
})
.await
}
query! {
pub fn get_active_page(item_id: ItemId, workspace_id: WorkspaceId) -> Result<Option<String>> {
SELECT active_page_id
FROM component_previews
WHERE item_id = ? AND workspace_id = ?
}
}
pub async fn delete_unloaded_items(
&self,
workspace: WorkspaceId,
alive_items: Vec<ItemId>,
) -> Result<()> {
let placeholders = alive_items
.iter()
.map(|_| "?")
.collect::<Vec<&str>>()
.join(", ");
let query = format!(
"DELETE FROM component_previews WHERE workspace_id = ? AND item_id NOT IN ({placeholders})"
);
self.write(move |conn| {
let mut statement = Statement::prepare(conn, query)?;
let mut next_index = statement.bind(&workspace, 1)?;
for id in alive_items {
next_index = statement.bind(&id, next_index)?;
}
statement.exec()
})
.await
}
}