persistence.rs

 1use anyhow::Result;
 2use db::{define_connection, query, sqlez::statement::Statement, sqlez_macros::sql};
 3use workspace::{ItemId, WorkspaceDb, WorkspaceId};
 4
 5define_connection! {
 6    pub static ref COMPONENT_PREVIEW_DB: ComponentPreviewDb<WorkspaceDb> =
 7        &[sql!(
 8            CREATE TABLE component_previews (
 9                workspace_id INTEGER,
10                item_id INTEGER UNIQUE,
11                active_page_id TEXT,
12                PRIMARY KEY(workspace_id, item_id),
13                FOREIGN KEY(workspace_id) REFERENCES workspaces(workspace_id)
14                ON DELETE CASCADE
15            ) STRICT;
16        )];
17}
18
19impl ComponentPreviewDb {
20    pub async fn save_active_page(
21        &self,
22        item_id: ItemId,
23        workspace_id: WorkspaceId,
24        active_page_id: String,
25    ) -> Result<()> {
26        log::debug!(
27            "Saving active page: item_id={item_id:?}, workspace_id={workspace_id:?}, active_page_id={active_page_id}"
28        );
29        let query = "INSERT INTO component_previews(item_id, workspace_id, active_page_id)
30            VALUES (?1, ?2, ?3)
31            ON CONFLICT DO UPDATE SET
32                active_page_id = ?3";
33        self.write(move |conn| {
34            let mut statement = Statement::prepare(conn, query)?;
35            let mut next_index = statement.bind(&item_id, 1)?;
36            next_index = statement.bind(&workspace_id, next_index)?;
37            statement.bind(&active_page_id, next_index)?;
38            statement.exec()
39        })
40        .await
41    }
42
43    query! {
44        pub fn get_active_page(item_id: ItemId, workspace_id: WorkspaceId) -> Result<Option<String>> {
45            SELECT active_page_id
46            FROM component_previews
47            WHERE item_id = ? AND workspace_id = ?
48        }
49    }
50
51    pub async fn delete_unloaded_items(
52        &self,
53        workspace: WorkspaceId,
54        alive_items: Vec<ItemId>,
55    ) -> Result<()> {
56        let placeholders = alive_items
57            .iter()
58            .map(|_| "?")
59            .collect::<Vec<&str>>()
60            .join(", ");
61
62        let query = format!(
63            "DELETE FROM component_previews WHERE workspace_id = ? AND item_id NOT IN ({placeholders})"
64        );
65
66        self.write(move |conn| {
67            let mut statement = Statement::prepare(conn, query)?;
68            let mut next_index = statement.bind(&workspace, 1)?;
69            for id in alive_items {
70                next_index = statement.bind(&id, next_index)?;
71            }
72            statement.exec()
73        })
74        .await
75    }
76}