core: give consumers an in-memory store instead of a rusqlite dependency
Desktop (Tauri) / Windows installer (cross-compiled) (push) Successful in 1m56s
Desktop (Tauri) / Tauri desktop (Linux) (push) Successful in 3m51s
Desktop (Tauri) / Update manifest (push) Successful in 5s

The extraction left update.rs's tests reaching for rusqlite and uuid directly to
build a Db — crates that now belong to the core alone, so clippy failed on
unresolved imports. The Windows job had already compiled the whole installer, so
this was only ever the test module.

Adding rusqlite as a dev-dependency of the desktop crate would have fixed it and
quietly undone part of the point: the desktop is not supposed to know what the
store is made of. So the core exposes open_in_memory() instead, which is what the
caller actually wanted, and the Android bindings will want the same thing when
they get tests.

uuid went the same way. It was generating unique scratch-directory names, which a
process id plus a counter does without a dependency — process id separates
concurrent cargo test runs, the counter separates tests within a run. The comment
right above it already said nothing there was worth a new dependency.

Verified the boundary holds in both directions afterwards: the desktop crate
references none of rusqlite/uuid/chrono/reqwest/sha2, and the core references no
tauri.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-17 23:22:24 -04:00
co-authored by Claude Opus 5
parent 0a7480cf9b
commit e696b23417
2 changed files with 26 additions and 8 deletions
+14 -8
View File
@@ -308,14 +308,20 @@ fn describe_check_error(detail: &str) -> String {
#[cfg(test)]
mod tests {
use super::*;
use rusqlite::Connection;
use std::sync::Mutex;
use thoughtsync_core::local::schema;
use std::sync::atomic::{AtomicU32, Ordering};
fn db() -> Db {
let conn = Connection::open_in_memory().expect("in-memory db");
schema::migrate(&conn).expect("migrate");
Db(Mutex::new(conn))
thoughtsync_core::local::open_in_memory().expect("in-memory db")
}
/// A scratch path nothing else will collide with. Process id keeps concurrent
/// `cargo test` runs apart, the counter keeps tests within one run apart — which
/// is all uuid was doing here, without the dependency (the core owns uuid now,
/// and pulling it into the desktop crate for two test filenames would be silly).
fn scratch_path(tag: &str) -> std::path::PathBuf {
static SEQ: AtomicU32 = AtomicU32::new(0);
let n = SEQ.fetch_add(1, Ordering::Relaxed);
std::env::temp_dir().join(format!("ts-{tag}-{}-{n}", std::process::id()))
}
/// The channel `update_check` would actually use.
@@ -336,7 +342,7 @@ mod tests {
/// A scratch directory holding a marker file, named uniquely so tests can run in
/// parallel. Dropped by the OS' temp cleanup; nothing here is worth a new dependency.
fn data_dir_with_marker(contents: &str) -> std::path::PathBuf {
let dir = std::env::temp_dir().join(format!("ts-marker-{}", uuid::Uuid::new_v4()));
let dir = scratch_path("marker");
std::fs::create_dir_all(&dir).expect("scratch dir");
std::fs::write(dir.join(INSTALL_MARKER), contents).expect("write marker");
dir
@@ -397,7 +403,7 @@ mod tests {
// Built from source, or installed by anything that isn't install.sh.
let db = db();
set_channel(&db, Channel::Dev);
let empty = std::env::temp_dir().join(format!("ts-nomarker-{}", uuid::Uuid::new_v4()));
let empty = scratch_path("nomarker");
std::fs::create_dir_all(&empty).expect("scratch dir");
adopt_installer_channel(&db, &empty);
assert_eq!(effective(&db), Channel::Dev);