sqlite_store: Mark write transactions with BEGIN IMMEDIATE

Hopefully addresses SQLITE_BUSY error, see #131
This commit is contained in:
Lennart
2025-11-01 15:09:42 +01:00
parent f34f7e420e
commit a05baea472
3 changed files with 55 additions and 10 deletions

View File

@@ -1,4 +1,5 @@
use super::ChangeOperation; use super::ChangeOperation;
use crate::BEGIN_IMMEDIATE;
use async_trait::async_trait; use async_trait::async_trait;
use derive_more::derive::Constructor; use derive_more::derive::Constructor;
use rustical_ical::AddressObject; use rustical_ical::AddressObject;
@@ -414,7 +415,11 @@ impl AddressbookStore for SqliteAddressbookStore {
addressbook_id: &str, addressbook_id: &str,
use_trashbin: bool, use_trashbin: bool,
) -> Result<(), rustical_store::Error> { ) -> Result<(), rustical_store::Error> {
let mut tx = self.db.begin().await.map_err(crate::Error::from)?; let mut tx = self
.db
.begin_with(BEGIN_IMMEDIATE)
.await
.map_err(crate::Error::from)?;
let addressbook = let addressbook =
match Self::_get_addressbook(&mut *tx, principal, addressbook_id, use_trashbin).await { match Self::_get_addressbook(&mut *tx, principal, addressbook_id, use_trashbin).await {
@@ -508,7 +513,11 @@ impl AddressbookStore for SqliteAddressbookStore {
object: AddressObject, object: AddressObject,
overwrite: bool, overwrite: bool,
) -> Result<(), rustical_store::Error> { ) -> Result<(), rustical_store::Error> {
let mut tx = self.db.begin().await.map_err(crate::Error::from)?; let mut tx = self
.db
.begin_with(BEGIN_IMMEDIATE)
.await
.map_err(crate::Error::from)?;
let object_id = object.get_id().to_owned(); let object_id = object.get_id().to_owned();
@@ -554,7 +563,11 @@ impl AddressbookStore for SqliteAddressbookStore {
object_id: &str, object_id: &str,
use_trashbin: bool, use_trashbin: bool,
) -> Result<(), rustical_store::Error> { ) -> Result<(), rustical_store::Error> {
let mut tx = self.db.begin().await.map_err(crate::Error::from)?; let mut tx = self
.db
.begin_with(BEGIN_IMMEDIATE)
.await
.map_err(crate::Error::from)?;
Self::_delete_object(&mut *tx, principal, addressbook_id, object_id, use_trashbin).await?; Self::_delete_object(&mut *tx, principal, addressbook_id, object_id, use_trashbin).await?;
@@ -589,7 +602,11 @@ impl AddressbookStore for SqliteAddressbookStore {
addressbook_id: &str, addressbook_id: &str,
object_id: &str, object_id: &str,
) -> Result<(), rustical_store::Error> { ) -> Result<(), rustical_store::Error> {
let mut tx = self.db.begin().await.map_err(crate::Error::from)?; let mut tx = self
.db
.begin_with(BEGIN_IMMEDIATE)
.await
.map_err(crate::Error::from)?;
Self::_restore_object(&mut *tx, principal, addressbook_id, object_id).await?; Self::_restore_object(&mut *tx, principal, addressbook_id, object_id).await?;
@@ -624,7 +641,11 @@ impl AddressbookStore for SqliteAddressbookStore {
objects: Vec<AddressObject>, objects: Vec<AddressObject>,
merge_existing: bool, merge_existing: bool,
) -> Result<(), Error> { ) -> Result<(), Error> {
let mut tx = self.db.begin().await.map_err(crate::Error::from)?; let mut tx = self
.db
.begin_with(BEGIN_IMMEDIATE)
.await
.map_err(crate::Error::from)?;
let existing = let existing =
match Self::_get_addressbook(&mut *tx, &addressbook.principal, &addressbook.id, true) match Self::_get_addressbook(&mut *tx, &addressbook.principal, &addressbook.id, true)

View File

@@ -1,4 +1,5 @@
use super::ChangeOperation; use super::ChangeOperation;
use crate::BEGIN_IMMEDIATE;
use async_trait::async_trait; use async_trait::async_trait;
use chrono::TimeDelta; use chrono::TimeDelta;
use derive_more::derive::Constructor; use derive_more::derive::Constructor;
@@ -539,7 +540,11 @@ impl CalendarStore for SqliteCalendarStore {
id: &str, id: &str,
use_trashbin: bool, use_trashbin: bool,
) -> Result<(), Error> { ) -> Result<(), Error> {
let mut tx = self.db.begin().await.map_err(crate::Error::from)?; let mut tx = self
.db
.begin_with(BEGIN_IMMEDIATE)
.await
.map_err(crate::Error::from)?;
let cal = match Self::_get_calendar(&mut *tx, principal, id, true).await { let cal = match Self::_get_calendar(&mut *tx, principal, id, true).await {
Ok(cal) => Some(cal), Ok(cal) => Some(cal),
@@ -573,7 +578,11 @@ impl CalendarStore for SqliteCalendarStore {
objects: Vec<CalendarObject>, objects: Vec<CalendarObject>,
merge_existing: bool, merge_existing: bool,
) -> Result<(), Error> { ) -> Result<(), Error> {
let mut tx = self.db.begin().await.map_err(crate::Error::from)?; let mut tx = self
.db
.begin_with(BEGIN_IMMEDIATE)
.await
.map_err(crate::Error::from)?;
let existing_cal = let existing_cal =
match Self::_get_calendar(&mut *tx, &calendar.principal, &calendar.id, true).await { match Self::_get_calendar(&mut *tx, &calendar.principal, &calendar.id, true).await {
@@ -663,7 +672,11 @@ impl CalendarStore for SqliteCalendarStore {
object: CalendarObject, object: CalendarObject,
overwrite: bool, overwrite: bool,
) -> Result<(), Error> { ) -> Result<(), Error> {
let mut tx = self.db.begin().await.map_err(crate::Error::from)?; let mut tx = self
.db
.begin_with(BEGIN_IMMEDIATE)
.await
.map_err(crate::Error::from)?;
let object_id = object.get_id().to_owned(); let object_id = object.get_id().to_owned();
@@ -713,7 +726,11 @@ impl CalendarStore for SqliteCalendarStore {
id: &str, id: &str,
use_trashbin: bool, use_trashbin: bool,
) -> Result<(), Error> { ) -> Result<(), Error> {
let mut tx = self.db.begin().await.map_err(crate::Error::from)?; let mut tx = self
.db
.begin_with(BEGIN_IMMEDIATE)
.await
.map_err(crate::Error::from)?;
Self::_delete_object(&mut *tx, principal, cal_id, id, use_trashbin).await?; Self::_delete_object(&mut *tx, principal, cal_id, id, use_trashbin).await?;
@@ -737,7 +754,11 @@ impl CalendarStore for SqliteCalendarStore {
cal_id: &str, cal_id: &str,
object_id: &str, object_id: &str,
) -> Result<(), Error> { ) -> Result<(), Error> {
let mut tx = self.db.begin().await.map_err(crate::Error::from)?; let mut tx = self
.db
.begin_with(BEGIN_IMMEDIATE)
.await
.map_err(crate::Error::from)?;
Self::_restore_object(&mut *tx, principal, cal_id, object_id).await?; Self::_restore_object(&mut *tx, principal, cal_id, object_id).await?;

View File

@@ -10,6 +10,9 @@ pub mod error;
pub mod principal_store; pub mod principal_store;
pub mod subscription_store; pub mod subscription_store;
// Begin statement for write transactions
pub const BEGIN_IMMEDIATE: &str = "BEGIN IMMEDIATE";
#[cfg(any(test, feature = "test"))] #[cfg(any(test, feature = "test"))]
pub mod tests; pub mod tests;