mirror of
https://github.com/chatmail/core.git
synced 2026-04-17 21:46:35 +03:00
sql: start transactions as IMMEDIATE
With the introduction of transactions in Contact::add_or_lookup(), python tests sometimes fail to create contacts with the folowing error: Cannot create contact: add_or_lookup: database is locked: Error code 5: The database file is locked `PRAGMA busy_timeout=60000` does not affect this case as the error is returned before 60 seconds pass. DEFERRED transactions with write operations need to be retried from scratch if they are rolled back due to a write operation on another connection. Using IMMEDIATE transactions for writing is an attempt to fix this problem without a retry loop. If we later need DEFERRED transactions, e.g. for reading a snapshot without locking the database, we may introduce another function for this.
This commit is contained in:
10
src/sql.rs
10
src/sql.rs
@@ -6,7 +6,7 @@ use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::{bail, Context as _, Result};
|
||||
use rusqlite::{self, config::DbConfig, Connection, OpenFlags};
|
||||
use rusqlite::{self, config::DbConfig, Connection, OpenFlags, TransactionBehavior};
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
use crate::blob::BlobObject;
|
||||
@@ -377,6 +377,12 @@ impl Sql {
|
||||
///
|
||||
/// If the function returns an error, the transaction will be rolled back. If it does not return an
|
||||
/// error, the transaction will be committed.
|
||||
///
|
||||
/// Transactions started use IMMEDIATE behavior
|
||||
/// rather than default DEFERRED behavior
|
||||
/// to avoid "database is busy" errors
|
||||
/// which may happen when DEFERRED transaction
|
||||
/// is attempted to be promoted to a write transaction.
|
||||
pub async fn transaction<G, H>(&self, callback: G) -> Result<H>
|
||||
where
|
||||
H: Send + 'static,
|
||||
@@ -384,7 +390,7 @@ impl Sql {
|
||||
{
|
||||
let mut conn = self.get_conn().await?;
|
||||
tokio::task::block_in_place(move || {
|
||||
let mut transaction = conn.transaction()?;
|
||||
let mut transaction = conn.transaction_with_behavior(TransactionBehavior::Immediate)?;
|
||||
let ret = callback(&mut transaction);
|
||||
|
||||
match ret {
|
||||
|
||||
Reference in New Issue
Block a user