core, desktop: Db::conn everywhere, Change::default, notes_where, and shared row mappings
Android / Build, or is the channel already serving this? (push) Successful in 4s
CI & Build / Build now, or wait for Android? (push) Successful in 4s
CI & Build / Web typecheck and unit tests (push) Successful in 16s
CI & Build / Python lint (push) Successful in 2s
CI & Build / Python tests (push) Successful in 15s
Desktop (Tauri) / Build, or is the channel already serving this? (push) Successful in 3s
CI & Build / integration (push) Successful in 1m22s
CI & Build / Build & push image (push) Skipped
Desktop (Tauri) / Web tests, clippy, Rust tests and rustfmt (push) Successful in 4m6s
Desktop (Tauri) / Windows installer (cross-compiled) (push) Successful in 4m20s
Desktop (Tauri) / Tauri desktop (Linux) (push) Successful in 5m21s
Desktop (Tauri) / Update manifest (push) Successful in 5s
Android / Kotlin + Rust (APK) (push) Canceled after 12m20s

From the audit (#5179, core and desktop half).

- Every `db.0.lock().map_err(|e| e.to_string())?` (about 50 sites in core and
  the desktop) is now `db.conn()?`. The few sites that deliberately handle
  a poisoned lock differently, and the tests, keep their own spelling.
- push::Change derives Default, so its four constructors name only the
  fields they set.
- store: list_notes, reminders, titles and search share notes_where (ids
  from a query, each loaded through load_note). Labels share
  LABEL_SELECT/label_row, and saved filters share
  SAVED_FILTER_SELECT/saved_filter_row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-07 19:57:24 -04:00
co-authored by Claude Opus 5.5
parent 646a115701
commit 05c82c2362
12 changed files with 132 additions and 184 deletions
+2 -2
View File
@@ -175,7 +175,7 @@ fn backoff(failures: u32) -> Duration {
/// The server URL and token, or None when this device isn't linked.
fn credentials(db: &Db) -> Result<Option<(String, String)>, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
let current = state::read(&conn).map_err(|e| e.to_string())?;
Ok(current.server_url.zip(current.device_token))
}
@@ -183,7 +183,7 @@ fn credentials(db: &Db) -> Result<Option<(String, String)>, String> {
/// What is waiting to be sent, as [`push::pending_fingerprint`] sees it. A store
/// that can't be read reads as nothing pending; the periodic cycle still runs.
fn pending(db: &Db) -> Option<String> {
let conn = db.0.lock().ok()?;
let conn = db.conn().ok()?;
push::pending_fingerprint(&conn).ok().flatten()
}
+2 -2
View File
@@ -60,7 +60,7 @@ pub struct CaptureShortcut {
}
fn stored(db: &Db) -> Result<String, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
Ok(store::pref(&conn, SHORTCUT_PREF)
.map_err(|e| e.to_string())?
.unwrap_or_default())
@@ -187,7 +187,7 @@ pub fn capture_shortcut_set(
) -> Result<CaptureShortcut, String> {
let wanted = shortcut.trim().to_string();
register(&app, &wanted)?;
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::set_pref(&conn, SHORTCUT_PREF, &wanted).map_err(|e| e.to_string())?;
log::info!(
"quick capture shortcut {}",
+31 -31
View File
@@ -54,37 +54,37 @@ pub fn auth_me() -> User {
#[tauri::command]
pub fn notes_list(query: ListQuery, db: State<'_, Db>) -> Result<Vec<Note>, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::list_notes(&conn, &query).map_err(|e| e.to_string())
}
#[tauri::command]
pub fn notes_get(id: String, db: State<'_, Db>) -> Result<Note, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::get_note(&conn, &id).map_err(|e| e.to_string())
}
#[tauri::command]
pub fn notes_create(input: NoteCreateInput, db: State<'_, Db>) -> Result<Note, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::create_note(&conn, &input).map_err(|e| e.to_string())
}
#[tauri::command]
pub fn notes_update(id: String, changes: Value, db: State<'_, Db>) -> Result<Note, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::update_note(&conn, &id, &changes).map_err(|e| e.to_string())
}
#[tauri::command]
pub fn notes_complete_reminder(id: String, db: State<'_, Db>) -> Result<Note, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::complete_reminder(&conn, &id).map_err(|e| e.to_string())
}
#[tauri::command]
pub fn notes_snooze_reminder(id: String, minutes: i64, db: State<'_, Db>) -> Result<Note, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::snooze_reminder(&conn, &id, minutes).map_err(|e| e.to_string())
}
@@ -94,7 +94,7 @@ pub fn notes_set_labels(
label_ids: Vec<String>,
db: State<'_, Db>,
) -> Result<Note, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::set_labels(&conn, &id, &label_ids).map_err(|e| e.to_string())
}
@@ -105,7 +105,7 @@ pub fn notes_update_item(
changes: Value,
db: State<'_, Db>,
) -> Result<Note, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::update_item(&conn, &id, &item_id, &changes).map_err(|e| e.to_string())
}
@@ -134,7 +134,7 @@ pub async fn notes_add_attachment(
let note_id = header("x-note-id");
let filename = blobs::urldecode(header("x-filename"));
let mime = header("x-mime");
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::add_attachment(&conn, &blobs, note_id, &filename, mime, bytes)
}
@@ -152,7 +152,7 @@ pub async fn notes_export(
) -> Result<String, String> {
use tauri::Manager;
let bytes = {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
portable::export_zip(&conn, &blobs)?
};
let dir = app
@@ -188,7 +188,7 @@ pub async fn notes_import(
let tauri::ipc::InvokeBody::Raw(bytes) = request.body() else {
return Err("The file's contents didn't arrive.".to_string());
};
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
portable::import_zip(&conn, &blobs, bytes)
}
@@ -198,7 +198,7 @@ pub fn notes_delete_attachment(
att_id: String,
db: State<'_, Db>,
) -> Result<Note, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::delete_attachment(&conn, &id, &att_id).map_err(|e| e.to_string())
}
@@ -208,37 +208,37 @@ pub fn notes_delete_preview(
preview_id: String,
db: State<'_, Db>,
) -> Result<Note, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::delete_preview(&conn, &id, &preview_id).map_err(|e| e.to_string())
}
#[tauri::command]
pub fn notes_reorder(ordered_ids: Vec<String>, db: State<'_, Db>) -> Result<(), String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::reorder(&conn, &ordered_ids).map_err(|e| e.to_string())
}
#[tauri::command]
pub fn notes_trash(id: String, db: State<'_, Db>) -> Result<Note, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::trash(&conn, &id).map_err(|e| e.to_string())
}
#[tauri::command]
pub fn notes_restore(id: String, db: State<'_, Db>) -> Result<Note, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::restore(&conn, &id).map_err(|e| e.to_string())
}
#[tauri::command]
pub fn notes_delete_forever(id: String, db: State<'_, Db>) -> Result<(), String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::delete_forever(&conn, &id).map_err(|e| e.to_string())
}
#[tauri::command]
pub fn notes_revisions(id: String, db: State<'_, Db>) -> Result<Vec<NoteRevision>, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::revisions(&conn, &id).map_err(|e| e.to_string())
}
@@ -248,61 +248,61 @@ pub fn notes_restore_revision(
rev_id: String,
db: State<'_, Db>,
) -> Result<Note, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::restore_revision(&conn, &id, &rev_id).map_err(|e| e.to_string())
}
#[tauri::command]
pub fn notes_reminders(db: State<'_, Db>) -> Result<Vec<Note>, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::reminders(&conn).map_err(|e| e.to_string())
}
#[tauri::command]
pub fn notes_titles(db: State<'_, Db>) -> Result<Vec<TitleEntry>, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::titles(&conn).map_err(|e| e.to_string())
}
#[tauri::command]
pub fn labels_list(db: State<'_, Db>) -> Result<Vec<Label>, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::list_labels(&conn).map_err(|e| e.to_string())
}
#[tauri::command]
pub fn labels_create(name: String, db: State<'_, Db>) -> Result<Label, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::create_label(&conn, &name).map_err(|e| e.to_string())
}
#[tauri::command]
pub fn labels_rename(id: String, name: String, db: State<'_, Db>) -> Result<Label, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::rename_label(&conn, &id, &name).map_err(|e| e.to_string())
}
#[tauri::command]
pub fn labels_set_color(id: String, color: String, db: State<'_, Db>) -> Result<Label, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::set_label_color(&conn, &id, &color).map_err(|e| e.to_string())
}
#[tauri::command]
pub fn labels_remove(id: String, db: State<'_, Db>) -> Result<(), String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::remove_label(&conn, &id).map_err(|e| e.to_string())
}
#[tauri::command]
pub fn labels_merge(source_id: String, into: String, db: State<'_, Db>) -> Result<Label, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::merge_labels(&conn, &source_id, &into).map_err(|e| e.to_string())
}
#[tauri::command]
pub fn saved_filters_list(db: State<'_, Db>) -> Result<Vec<SavedFilter>, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::list_saved_filters(&conn).map_err(|e| e.to_string())
}
@@ -312,13 +312,13 @@ pub fn saved_filters_create(
params: Value,
db: State<'_, Db>,
) -> Result<SavedFilter, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::create_saved_filter(&conn, &name, &params).map_err(|e| e.to_string())
}
#[tauri::command]
pub fn saved_filters_remove(id: String, db: State<'_, Db>) -> Result<(), String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::remove_saved_filter(&conn, &id).map_err(|e| e.to_string())
}
@@ -328,6 +328,6 @@ pub fn saved_filters_rename(
name: String,
db: State<'_, Db>,
) -> Result<SavedFilter, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::rename_saved_filter(&conn, &id, &name).map_err(|e| e.to_string())
}
+5 -5
View File
@@ -96,7 +96,7 @@ pub async fn sync_link(input: LinkInput, db: State<'_, Db>) -> Result<LinkResult
// isn't Send so it cannot be held across an await, and holding the store
// locked for a network round-trip would freeze every note operation in the UI.
let status = {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
state::set_link(&conn, &base_url, &token).map_err(|e| e.to_string())?;
// Adopt the server's trash-retention window immediately, so the Trash view
// stops counting down against this device's offline default the moment it's
@@ -135,7 +135,7 @@ pub async fn sync_unlink(db: State<'_, Db>) -> Result<UnlinkResult, String> {
// holding the store across a round-trip would freeze every note operation in
// the UI.
let link = {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
let current = state::read(&conn).map_err(|e| e.to_string())?;
current.server_url.zip(current.device_token)
};
@@ -144,7 +144,7 @@ pub async fn sync_unlink(db: State<'_, Db>) -> Result<UnlinkResult, String> {
None => client::RevokeOutcome::Skipped,
};
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
state::clear_link(&conn).map_err(|e| e.to_string())?;
log::info!("unlinked from server (server-side token: {revoked:?})");
Ok(UnlinkResult {
@@ -155,7 +155,7 @@ pub async fn sync_unlink(db: State<'_, Db>) -> Result<UnlinkResult, String> {
#[tauri::command]
pub fn sync_status(db: State<'_, Db>) -> Result<state::Status, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
state::status(&conn).map_err(|e| e.to_string())
}
@@ -183,7 +183,7 @@ pub fn sync_last(autosync: State<'_, AutoSync>) -> Option<LastCycle> {
/// changes" state without running a sync to find out.
#[tauri::command]
pub fn sync_has_pending(db: State<'_, Db>) -> Result<bool, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
push::has_pending(&conn).map_err(|e| e.to_string())
}
+1 -1
View File
@@ -69,7 +69,7 @@ fn worker(app: AppHandle) {
fn due(app: &AppHandle, now: i64) -> Result<Vec<DueReminder>, String> {
let db = app.state::<Db>();
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::due_reminders(&conn, now).map_err(|e| e.to_string())
}
+3 -3
View File
@@ -180,7 +180,7 @@ pub fn adopt_installer_channel(db: &Db, data_dir: &Path) {
/// Apply `channel` unless we already applied this same marker value. Returns whether
/// anything changed.
fn adopt(db: &Db, channel: Channel) -> Result<bool, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
let adopted = store::pref(&conn, CHANNEL_SEED_PREF).map_err(|e| e.to_string())?;
// Already acted on this marker — whatever the pref says now is the user's own
// choice, and re-applying would quietly undo it.
@@ -193,7 +193,7 @@ fn adopt(db: &Db, channel: Channel) -> Result<bool, String> {
}
fn read_channel(db: &State<'_, Db>) -> Result<Channel, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
let raw = store::pref(&conn, CHANNEL_PREF).map_err(|e| e.to_string())?;
Ok(raw
.as_deref()
@@ -208,7 +208,7 @@ pub fn update_channel_get(db: State<'_, Db>) -> Result<Channel, String> {
#[tauri::command]
pub fn update_channel_set(channel: Channel, db: State<'_, Db>) -> Result<Channel, String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
store::set_pref(&conn, CHANNEL_PREF, channel.as_str()).map_err(|e| e.to_string())?;
log::info!("update channel set to {}", channel.as_str());
Ok(channel)