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
@@ -67,7 +67,7 @@ pub async fn run_cycle(
} else {
state::SHARES
};
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
if state::begin_shares(&conn, level).map_err(|e| e.to_string())? {
log::info!("the server shares more of notes now; pulling everything once");
}
@@ -91,7 +91,7 @@ pub async fn run_cycle(
let retention = server.and_then(|s| s.trash_retention_days);
let status = {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
if let Some(days) = retention {
state::set_server_retention(&conn, days as i64).map_err(|e| e.to_string())?;
}
+3 -3
View File
@@ -79,7 +79,7 @@ async fn download_missing_blobs(
token: &str,
) -> Result<(usize, usize), String> {
let wanted = {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
hashed_attachments(&conn).map_err(|e| e.to_string())?
};
@@ -446,7 +446,7 @@ pub async fn run(
loop {
let since = {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
state::read(&conn).map_err(|e| e.to_string())?.last_cursor
};
@@ -463,7 +463,7 @@ pub async fn run(
let has_more = page.has_more;
let applied = {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
apply_page(&conn, &page).map_err(|e| e.to_string())?
};
total.absorb(applied);
+9 -38
View File
@@ -64,7 +64,7 @@ impl PushSummary {
/// One entry in the `changes` array. Notes and labels share the envelope; serde skips
/// the fields that don't apply, so the server sees exactly the shape docs/sync.md
/// describes for each entity.
#[derive(Debug, Serialize)]
#[derive(Debug, Default, Serialize)]
pub struct Change {
pub entity: &'static str,
pub id: String,
@@ -110,18 +110,7 @@ impl Change {
id,
op: "delete",
edited_at,
body: None,
color: None,
pinned: None,
archived: None,
trashed: None,
remind_at: None,
recurrence: None,
position: None,
label_ids: None,
created_at: None,
name: None,
state_at: None,
..Default::default()
}
}
}
@@ -237,16 +226,7 @@ fn collect_labels(conn: &Connection, out: &mut Vec<Change>, limit: usize) -> rus
name: Some(r.get(1)?),
color: Some(r.get(2)?),
edited_at: r.get(3)?,
body: None,
pinned: None,
archived: None,
trashed: None,
remind_at: None,
recurrence: None,
position: None,
label_ids: None,
created_at: None,
state_at: None,
..Default::default()
})
})?;
for row in rows {
@@ -342,17 +322,11 @@ fn note_change(conn: &Connection, id: &str, shared_state: bool) -> rusqlite::Res
op: "upsert",
edited_at: row.updated_at,
body: (row.permission == "edit").then_some(row.body),
color: None,
pinned: own.then_some(row.pinned),
archived: own.then_some(row.archived),
trashed: None,
remind_at: None,
recurrence: None,
position: own.then_some(row.position),
label_ids: None,
created_at: None,
name: None,
state_at,
..Default::default()
});
}
@@ -374,8 +348,6 @@ fn note_change(conn: &Connection, id: &str, shared_state: bool) -> rusqlite::Res
// server's last-write-wins comparison runs against.
edited_at: row.updated_at,
body: Some(row.body),
// A note has no colour to send. See the field on `Change`.
color: None,
pinned: Some(row.pinned),
archived: Some(row.archived),
trashed: Some(row.trashed),
@@ -384,8 +356,7 @@ fn note_change(conn: &Connection, id: &str, shared_state: bool) -> rusqlite::Res
position: Some(row.position),
label_ids: Some(label_ids),
created_at: Some(row.created_at),
name: None,
state_at: None,
..Default::default()
})
}
@@ -610,7 +581,7 @@ async fn upload_pending(
token: &str,
) -> Result<PushSummary, String> {
let wanted = {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
pending_uploads(&conn).map_err(|e| e.to_string())?
};
let mut summary = PushSummary::default();
@@ -636,7 +607,7 @@ async fn upload_pending(
)),
};
{
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
settle_upload(&conn, &upload.id, &result).map_err(|e| e.to_string())?;
}
match result {
@@ -669,7 +640,7 @@ pub async fn run(
loop {
let batch = {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
collect(&conn, BATCH, accepts).map_err(|e| e.to_string())?
};
if batch.is_empty() {
@@ -680,7 +651,7 @@ pub async fn run(
let results = parse_results(&raw)?;
let applied = {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
apply_results(&conn, &batch, &results).map_err(|e| e.to_string())?
};
// Everything rejected clears nothing, so the same batch would be collected
+2 -2
View File
@@ -18,7 +18,7 @@ pub const NEEDS_SERVER: &str =
"Sharing is between people on a server. Link this device to one in Sync to share notes.";
fn link(db: &Db) -> Result<(String, String), String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
let link = state::read(&conn).map_err(|e| e.to_string())?;
match (link.server_url, link.device_token) {
(Some(url), Some(token)) => Ok((url, token)),
@@ -29,7 +29,7 @@ fn link(db: &Db) -> Result<(String, String), String> {
/// Set the local note's `shared` flag from the server's list of its shares. Not a
/// local edit, so it leaves `dirty` and `updated_at` alone.
fn mark_shared(db: &Db, note_id: &str, shares: &[NoteShare]) -> Result<(), String> {
let conn = db.0.lock().map_err(|e| e.to_string())?;
let conn = db.conn()?;
conn.execute(
"UPDATE notes SET shared = ?2 WHERE id = ?1 AND permission = 'owner'",
params![note_id, !shares.is_empty()],