Compare commits

..

5 Commits

Author SHA1 Message Date
Lennart
a53c333f1f version 0.9.14 2025-11-01 15:10:06 +01:00
Lennart
a05baea472 sqlite_store: Mark write transactions with BEGIN IMMEDIATE
Hopefully addresses SQLITE_BUSY error, see #131
2025-11-01 15:09:42 +01:00
Lennart
f34f7e420e Dockerfile: Update Rust to 1.91 2025-11-01 15:08:36 +01:00
Lennart
24ab323aa0 clippy appeasement 2025-11-01 14:21:44 +01:00
Lennart
f34f56ca89 update dependencies 2025-11-01 14:17:13 +01:00
9 changed files with 129 additions and 92 deletions

136
Cargo.lock generated
View File

@@ -19,9 +19,9 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
[[package]]
name = "aho-corasick"
version = "1.1.3"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
dependencies = [
"memchr",
]
@@ -397,13 +397,14 @@ dependencies = [
[[package]]
name = "axum-extra"
version = "0.10.3"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9963ff19f40c6102c76756ef0a46004c0d58957d87259fc9208ff8441c12ab96"
checksum = "460c45604cb25834835e3b4d3468510322852783dac36261d642424d75562ff3"
dependencies = [
"axum",
"axum-core",
"bytes",
"futures-core",
"futures-util",
"headers",
"http",
@@ -411,8 +412,6 @@ dependencies = [
"http-body-util",
"mime",
"pin-project-lite",
"rustversion",
"serde_core",
"tower-layer",
"tower-service",
"tracing",
@@ -532,9 +531,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
[[package]]
name = "cc"
version = "1.2.43"
version = "1.2.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "739eb0f94557554b3ca9a86d2d37bebd49c5e6d0c1d2bda35ba5bdac830befc2"
checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3"
dependencies = [
"find-msvc-tools",
"shlex",
@@ -587,9 +586,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.50"
version = "4.5.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c2cfd7bf8a6017ddaa4e32ffe7403d547790db06bd171c1c53926faab501623"
checksum = "4c26d721170e0295f191a69bd9a1f93efcdb0aff38684b61ab5750468972e5f5"
dependencies = [
"clap_builder",
"clap_derive",
@@ -597,9 +596,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.50"
version = "4.5.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a4c05b9e80c5ccd3a7ef080ad7b6ba7d6fc00a985b8b157197075677c82c7a0"
checksum = "75835f0c7bf681bfd05abe44e965760fea999a5286c6eb2d59883634fd02011a"
dependencies = [
"anstream",
"anstyle",
@@ -1582,9 +1581,9 @@ dependencies = [
[[package]]
name = "icu_collections"
version = "2.0.0"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47"
checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43"
dependencies = [
"displaydoc",
"potential_utf",
@@ -1595,9 +1594,9 @@ dependencies = [
[[package]]
name = "icu_locale_core"
version = "2.0.0"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a"
checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6"
dependencies = [
"displaydoc",
"litemap",
@@ -1608,11 +1607,10 @@ dependencies = [
[[package]]
name = "icu_normalizer"
version = "2.0.0"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979"
checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599"
dependencies = [
"displaydoc",
"icu_collections",
"icu_normalizer_data",
"icu_properties",
@@ -1623,42 +1621,38 @@ dependencies = [
[[package]]
name = "icu_normalizer_data"
version = "2.0.0"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3"
checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a"
[[package]]
name = "icu_properties"
version = "2.0.1"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b"
checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99"
dependencies = [
"displaydoc",
"icu_collections",
"icu_locale_core",
"icu_properties_data",
"icu_provider",
"potential_utf",
"zerotrie",
"zerovec",
]
[[package]]
name = "icu_properties_data"
version = "2.0.1"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632"
checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899"
[[package]]
name = "icu_provider"
version = "2.0.0"
version = "2.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af"
checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614"
dependencies = [
"displaydoc",
"icu_locale_core",
"stable_deref_trait",
"tinystr",
"writeable",
"yoke",
"zerofrom",
@@ -1838,9 +1832,9 @@ checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
[[package]]
name = "litemap"
version = "0.8.0"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
[[package]]
name = "lock_api"
@@ -1963,11 +1957,10 @@ dependencies = [
[[package]]
name = "num-bigint-dig"
version = "0.8.4"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151"
checksum = "82c79c15c05d4bf82b6f5ef163104cc81a760d8e874d38ac50ab67c8877b647b"
dependencies = [
"byteorder",
"lazy_static",
"libm",
"num-integer",
@@ -2476,9 +2469,9 @@ dependencies = [
[[package]]
name = "potential_utf"
version = "0.1.3"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a"
checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77"
dependencies = [
"zerovec",
]
@@ -2981,7 +2974,7 @@ dependencies = [
[[package]]
name = "rustical"
version = "0.9.13"
version = "0.9.14"
dependencies = [
"anyhow",
"argon2",
@@ -3024,7 +3017,7 @@ dependencies = [
[[package]]
name = "rustical_caldav"
version = "0.9.13"
version = "0.9.14"
dependencies = [
"async-std",
"async-trait",
@@ -3064,7 +3057,7 @@ dependencies = [
[[package]]
name = "rustical_carddav"
version = "0.9.13"
version = "0.9.14"
dependencies = [
"async-trait",
"axum",
@@ -3096,7 +3089,7 @@ dependencies = [
[[package]]
name = "rustical_dav"
version = "0.9.13"
version = "0.9.14"
dependencies = [
"async-trait",
"axum",
@@ -3121,7 +3114,7 @@ dependencies = [
[[package]]
name = "rustical_dav_push"
version = "0.9.13"
version = "0.9.14"
dependencies = [
"async-trait",
"axum",
@@ -3146,7 +3139,7 @@ dependencies = [
[[package]]
name = "rustical_frontend"
version = "0.9.13"
version = "0.9.14"
dependencies = [
"askama",
"askama_web",
@@ -3179,7 +3172,7 @@ dependencies = [
[[package]]
name = "rustical_ical"
version = "0.9.13"
version = "0.9.14"
dependencies = [
"axum",
"chrono",
@@ -3196,7 +3189,7 @@ dependencies = [
[[package]]
name = "rustical_oidc"
version = "0.9.13"
version = "0.9.14"
dependencies = [
"async-trait",
"axum",
@@ -3212,7 +3205,7 @@ dependencies = [
[[package]]
name = "rustical_store"
version = "0.9.13"
version = "0.9.14"
dependencies = [
"anyhow",
"async-trait",
@@ -3245,7 +3238,7 @@ dependencies = [
[[package]]
name = "rustical_store_sqlite"
version = "0.9.13"
version = "0.9.14"
dependencies = [
"async-trait",
"chrono",
@@ -3266,7 +3259,7 @@ dependencies = [
[[package]]
name = "rustical_xml"
version = "0.9.13"
version = "0.9.14"
dependencies = [
"quick-xml",
"thiserror 2.0.17",
@@ -3312,9 +3305,9 @@ dependencies = [
[[package]]
name = "rustls-webpki"
version = "0.103.7"
version = "0.103.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e10b3f4191e8a80e6b43eebabfac91e5dcecebb27a71f04e820c47ec41d314bf"
checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52"
dependencies = [
"ring",
"rustls-pki-types",
@@ -3999,9 +3992,9 @@ dependencies = [
[[package]]
name = "tinystr"
version = "0.8.1"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b"
checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869"
dependencies = [
"displaydoc",
"zerovec",
@@ -4456,24 +4449,24 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5"
[[package]]
name = "unicode-ident"
version = "1.0.20"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06"
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
[[package]]
name = "unicode-normalization"
version = "0.1.24"
version = "0.1.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956"
checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8"
dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-properties"
version = "0.1.3"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0"
checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d"
[[package]]
name = "unicode-xid"
@@ -5011,9 +5004,9 @@ checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
[[package]]
name = "writeable"
version = "0.6.1"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb"
checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9"
[[package]]
name = "xml_derive"
@@ -5035,11 +5028,10 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
[[package]]
name = "yoke"
version = "0.8.0"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc"
checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954"
dependencies = [
"serde",
"stable_deref_trait",
"yoke-derive",
"zerofrom",
@@ -5047,9 +5039,9 @@ dependencies = [
[[package]]
name = "yoke-derive"
version = "0.8.0"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6"
checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
dependencies = [
"proc-macro2",
"quote",
@@ -5106,9 +5098,9 @@ checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
[[package]]
name = "zerotrie"
version = "0.2.2"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595"
checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851"
dependencies = [
"displaydoc",
"yoke",
@@ -5117,9 +5109,9 @@ dependencies = [
[[package]]
name = "zerovec"
version = "0.11.4"
version = "0.11.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b"
checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002"
dependencies = [
"yoke",
"zerofrom",
@@ -5128,9 +5120,9 @@ dependencies = [
[[package]]
name = "zerovec-derive"
version = "0.11.1"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f"
checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
dependencies = [
"proc-macro2",
"quote",

View File

@@ -2,7 +2,7 @@
members = ["crates/*"]
[workspace.package]
version = "0.9.13"
version = "0.9.14"
edition = "2024"
description = "A CalDAV server"
documentation = "https://lennart-k.github.io/rustical/"
@@ -121,7 +121,7 @@ rustical_ical = { path = "./crates/ical/" }
chrono-tz = "0.10"
chrono-humanize = "0.2"
rand = "0.9"
axum-extra = { version = "0.10", features = ["typed-header"] }
axum-extra = { version = "0.12", features = ["typed-header"] }
rrule = "0.14"
argon2 = "0.5"
rpassword = "7.3"

View File

@@ -1,4 +1,4 @@
FROM --platform=$BUILDPLATFORM rust:1.90-alpine AS chef
FROM --platform=$BUILDPLATFORM rust:1.91-alpine AS chef
ARG TARGETPLATFORM
ARG BUILDPLATFORM

View File

@@ -11,7 +11,6 @@ publish = false
axum.workspace = true
tower.workspace = true
axum-extra.workspace = true
rustical_xml.workspace = true
async-trait.workspace = true
futures-util.workspace = true

View File

@@ -59,7 +59,7 @@ impl<S: SubscriptionStore> DavPushController<S> {
let mut latest_messages = HashMap::new();
for message in messages {
if matches!(message.data, CollectionOperationInfo::Content { .. }) {
latest_messages.insert(message.topic.to_string(), message);
latest_messages.insert(message.topic.clone(), message);
}
}
let messages = latest_messages.into_values();
@@ -156,12 +156,13 @@ impl<S: SubscriptionStore> DavPushController<S> {
) -> Result<(), NotifierError> {
if subsciption.public_key_type != "p256dh" {
return Err(NotifierError::InvalidPublicKeyType(
subsciption.public_key_type.to_string(),
subsciption.public_key_type.clone(),
));
}
let endpoint = subsciption.push_resource.parse().map_err(|_| {
NotifierError::InvalidEndpointUrl(subsciption.push_resource.to_string())
})?;
let endpoint = subsciption
.push_resource
.parse()
.map_err(|_| NotifierError::InvalidEndpointUrl(subsciption.push_resource.clone()))?;
let ua_public = base64::engine::general_purpose::URL_SAFE_NO_PAD
.decode(&subsciption.public_key)
.map_err(|_| NotifierError::InvalidKeyEncoding)?;

View File

@@ -14,7 +14,7 @@ reqwest.workspace = true
thiserror.workspace = true
async-trait.workspace = true
axum.workspace = true
tower-sessions = "0.14"
tower-sessions.workspace = true
axum-extra.workspace = true
headers.workspace = true
tracing.workspace = true

View File

@@ -1,4 +1,5 @@
use super::ChangeOperation;
use crate::BEGIN_IMMEDIATE;
use async_trait::async_trait;
use derive_more::derive::Constructor;
use rustical_ical::AddressObject;
@@ -414,7 +415,11 @@ impl AddressbookStore for SqliteAddressbookStore {
addressbook_id: &str,
use_trashbin: bool,
) -> 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 =
match Self::_get_addressbook(&mut *tx, principal, addressbook_id, use_trashbin).await {
@@ -508,7 +513,11 @@ impl AddressbookStore for SqliteAddressbookStore {
object: AddressObject,
overwrite: bool,
) -> 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();
@@ -554,7 +563,11 @@ impl AddressbookStore for SqliteAddressbookStore {
object_id: &str,
use_trashbin: bool,
) -> 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?;
@@ -589,7 +602,11 @@ impl AddressbookStore for SqliteAddressbookStore {
addressbook_id: &str,
object_id: &str,
) -> 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?;
@@ -624,7 +641,11 @@ impl AddressbookStore for SqliteAddressbookStore {
objects: Vec<AddressObject>,
merge_existing: bool,
) -> 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 =
match Self::_get_addressbook(&mut *tx, &addressbook.principal, &addressbook.id, true)

View File

@@ -1,4 +1,5 @@
use super::ChangeOperation;
use crate::BEGIN_IMMEDIATE;
use async_trait::async_trait;
use chrono::TimeDelta;
use derive_more::derive::Constructor;
@@ -539,7 +540,11 @@ impl CalendarStore for SqliteCalendarStore {
id: &str,
use_trashbin: bool,
) -> 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 {
Ok(cal) => Some(cal),
@@ -573,7 +578,11 @@ impl CalendarStore for SqliteCalendarStore {
objects: Vec<CalendarObject>,
merge_existing: bool,
) -> 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 =
match Self::_get_calendar(&mut *tx, &calendar.principal, &calendar.id, true).await {
@@ -663,7 +672,11 @@ impl CalendarStore for SqliteCalendarStore {
object: CalendarObject,
overwrite: bool,
) -> 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();
@@ -713,7 +726,11 @@ impl CalendarStore for SqliteCalendarStore {
id: &str,
use_trashbin: bool,
) -> 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?;
@@ -737,7 +754,11 @@ impl CalendarStore for SqliteCalendarStore {
cal_id: &str,
object_id: &str,
) -> 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?;

View File

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