feat: gate the store behind a feature and document the schema as a contract
This commit is contained in:
parent
8fb5661b53
commit
aa3950bc80
6 changed files with 122 additions and 16 deletions
|
|
@ -84,12 +84,29 @@ pub type ContactRow = (String, [u8; KEY_LEN], bool, Option<i64>);
|
|||
pub const SCHEMA_VERSION: i32 = 1;
|
||||
|
||||
impl Store {
|
||||
/// Opens the store at `path`. SQLite's own `:memory:` path works too;
|
||||
/// `open_in_memory` spells that case without the magic string.
|
||||
pub fn open(path: &Path) -> Result<Store, Error> {
|
||||
let db = Connection::open(path)?;
|
||||
Store::init(Connection::open(path)?)
|
||||
}
|
||||
|
||||
/// An in-memory store: the same schema, version and contract, gone with
|
||||
/// the handle. For tests, foreign importers assembling rows in code,
|
||||
/// and FFI round-trips that never touch disk.
|
||||
pub fn open_in_memory() -> Result<Store, Error> {
|
||||
Store::init(Connection::open_in_memory()?)
|
||||
}
|
||||
|
||||
fn init(db: Connection) -> Result<Store, Error> {
|
||||
// WAL keeps concurrent readers cheap while a writer commits, and a
|
||||
// short busy timeout absorbs the contention the mutex cannot (a
|
||||
// second connection in the same process, or a CLI run alongside).
|
||||
db.pragma_update(None, "journal_mode", "WAL")?;
|
||||
// An in-memory database journals in memory, so WAL applies to
|
||||
// files only.
|
||||
let journal: String = db.query_row("PRAGMA journal_mode", [], |row| row.get(0))?;
|
||||
if journal != "memory" {
|
||||
db.pragma_update(None, "journal_mode", "WAL")?;
|
||||
}
|
||||
db.busy_timeout(std::time::Duration::from_secs(5))?;
|
||||
let version: i32 = db.query_row("PRAGMA user_version", [], |row| row.get(0))?;
|
||||
if version == 0 {
|
||||
|
|
@ -706,6 +723,22 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn in_memory_store_round_trips() {
|
||||
let store = Store::open_in_memory().expect("memory store opens");
|
||||
let addr = Address::parse("alice@example.org").unwrap();
|
||||
store.set_account(&addr).unwrap();
|
||||
assert_eq!(
|
||||
store.account().unwrap().unwrap().short(),
|
||||
"alice@example.org"
|
||||
);
|
||||
store.store_inbox(&[1u8; 32], b"envelope", 5, false).unwrap();
|
||||
assert_eq!(store.mail("inbox").unwrap().len(), 1);
|
||||
// The same handle through the path spelling.
|
||||
let path = std::path::Path::new(":memory:");
|
||||
assert!(Store::open(path).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn store_is_shareable_across_threads() {
|
||||
fn assert_send_sync<T: Send + Sync>() {}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue