1use sqlx::sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePoolOptions, SqliteSynchronous};
2use sqlx::SqlitePool;
3use std::path::Path;
4use std::str::FromStr;
5
6pub struct Store {
7 writer: SqlitePool,
8 reader: SqlitePool,
9}
10
11impl Store {
12 pub async fn new(db_path: &Path) -> Result<Self, sqlx::Error> {
13 let db_url = format!("sqlite:{}", db_path.display());
14
15 let write_opts = SqliteConnectOptions::from_str(&db_url)?
16 .create_if_missing(true)
17 .journal_mode(SqliteJournalMode::Wal)
18 .synchronous(SqliteSynchronous::Normal)
19 .pragma("foreign_keys", "ON");
20
21 let writer = SqlitePoolOptions::new()
22 .max_connections(1)
23 .connect_with(write_opts)
24 .await?;
25
26 let read_opts = SqliteConnectOptions::from_str(&db_url)?
27 .journal_mode(SqliteJournalMode::Wal)
28 .synchronous(SqliteSynchronous::Normal)
29 .pragma("foreign_keys", "ON")
30 .read_only(true);
31
32 let reader = SqlitePoolOptions::new()
33 .max_connections(4)
34 .connect_with(read_opts)
35 .await?;
36
37 let store = Self { writer, reader };
38 store.run_migrations().await?;
39 Ok(store)
40 }
41
42 pub async fn in_memory() -> Result<Self, sqlx::Error> {
43 let opts = SqliteConnectOptions::from_str("sqlite::memory:")?
44 .journal_mode(SqliteJournalMode::Wal)
45 .pragma("foreign_keys", "ON");
46
47 let pool = SqlitePoolOptions::new()
48 .max_connections(1)
49 .connect_with(opts)
50 .await?;
51
52 let store = Self {
53 writer: pool.clone(),
54 reader: pool,
55 };
56 store.run_migrations().await?;
57 Ok(store)
58 }
59
60 async fn run_migrations(&self) -> Result<(), sqlx::Error> {
61 let _ = sqlx::raw_sql(include_str!("../migrations/001_initial.sql"))
62 .execute(&self.writer)
63 .await;
64 let _ = sqlx::raw_sql(include_str!("../migrations/002_body_metadata.sql"))
65 .execute(&self.writer)
66 .await;
67 let _ = sqlx::raw_sql(include_str!("../migrations/003_sync_runtime_status.sql"))
68 .execute(&self.writer)
69 .await;
70 let _ = sqlx::raw_sql(include_str!("../migrations/004_semantic_search.sql"))
71 .execute(&self.writer)
72 .await;
73 Ok(())
74 }
75
76 pub fn writer(&self) -> &SqlitePool {
77 &self.writer
78 }
79
80 pub fn reader(&self) -> &SqlitePool {
81 &self.reader
82 }
83}