From abfb5563777b42c8a3efeb929045bdd301efc55b Mon Sep 17 00:00:00 2001 From: link2xt Date: Tue, 18 Nov 2025 14:54:54 +0000 Subject: [PATCH] fix: set SQLite busy timeout to 1 minute on iOS Closes --- src/sql.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/sql.rs b/src/sql.rs index 650d7ade3..893c052af 100644 --- a/src/sql.rs +++ b/src/sql.rs @@ -2,6 +2,7 @@ use std::collections::{HashMap, HashSet}; use std::path::{Path, PathBuf}; +use std::time::Duration; use anyhow::{Context as _, Result, bail, ensure}; use rusqlite::{Connection, OpenFlags, Row, config::DbConfig, types::ValueRef}; @@ -760,7 +761,6 @@ fn new_connection(path: &Path, passphrase: &str) -> Result { conn.execute_batch( "PRAGMA cipher_memory_security = OFF; -- Too slow on Android PRAGMA secure_delete=on; - PRAGMA busy_timeout = 0; -- fail immediately PRAGMA soft_heap_limit = 8388608; -- 8 MiB limit, same as set in Android SQLiteDatabase. PRAGMA foreign_keys=on; ", @@ -773,6 +773,22 @@ fn new_connection(path: &Path, passphrase: &str) -> Result { conn.pragma_update(None, "temp_store", "memory")?; } + // Fail immediately when the database is busy, + // except for iOS. On iOS we don't have + // `accounts.lock` lockfile and the database + // is used by two processes: + // main process and the notification extension. + // Due to a bug they both may run at the same time + // and try to write to the database. + // As a workaround, we wait up to 1 minute and retry + // instead of failing immediately and + // possibly missing a message. + if cfg!(target_os = "ios") { + conn.busy_timeout(Duration::new(60, 0))?; + } else { + conn.busy_timeout(Duration::ZERO)?; + } + if !passphrase.is_empty() { conn.pragma_update(None, "key", passphrase)?; }