From 95f9397e48ea0f562bd15845f84d08ccbeae29ce Mon Sep 17 00:00:00 2001 From: Hocuri Date: Fri, 7 Aug 2026 17:12:51 +0200 Subject: [PATCH] Do the background fetch in the background --- deltachat-ffi/src/lib.rs | 12 ++--- deltachat-jsonrpc/src/api.rs | 8 +-- deltachat-jsonrpc/src/api/types/events.rs | 61 +++++++++++++++++------ src/accounts.rs | 37 ++++++++------ src/events/payload.rs | 3 ++ 5 files changed, 80 insertions(+), 41 deletions(-) diff --git a/deltachat-ffi/src/lib.rs b/deltachat-ffi/src/lib.rs index 183989b5f..3e736e062 100644 --- a/deltachat-ffi/src/lib.rs +++ b/deltachat-ffi/src/lib.rs @@ -515,6 +515,7 @@ pub unsafe extern "C" fn dc_event_get_id(event: *mut dc_event_t) -> libc::c_int EventType::WebxdcRealtimeData { .. } => 2150, EventType::WebxdcRealtimeAdvertisementReceived { .. } => 2151, EventType::AccountsBackgroundFetchDone => 2200, + EventType::AccountsBackgroundFetchTimedOut => 2201, EventType::ChatlistChanged => 2300, EventType::ChatlistItemChanged { .. } => 2301, EventType::AccountsChanged => 2302, @@ -557,6 +558,7 @@ pub unsafe extern "C" fn dc_event_get_data1_int(event: *mut dc_event_t) -> libc: | EventType::IncomingMsgBunch | EventType::ErrorSelfNotInGroup(_) | EventType::AccountsBackgroundFetchDone + | EventType::AccountsBackgroundFetchTimedOut | EventType::ChatlistChanged | EventType::AccountsChanged | EventType::AccountsItemChanged @@ -638,6 +640,7 @@ pub unsafe extern "C" fn dc_event_get_data2_int(event: *mut dc_event_t) -> libc: | EventType::IncomingMsgBunch | EventType::SelfavatarChanged | EventType::AccountsBackgroundFetchDone + | EventType::AccountsBackgroundFetchTimedOut | EventType::ChatlistChanged | EventType::ChatlistItemChanged { .. } | EventType::AccountsChanged @@ -745,6 +748,7 @@ pub unsafe extern "C" fn dc_event_get_data2_str(event: *mut dc_event_t) -> *mut | EventType::WebxdcStatusUpdate { .. } | EventType::WebxdcInstanceDeleted { .. } | EventType::AccountsBackgroundFetchDone + | EventType::AccountsBackgroundFetchTimedOut | EventType::ChatEphemeralTimerModified { .. } | EventType::ChatDeleted { .. } | EventType::IncomingMsgBunch @@ -4774,12 +4778,8 @@ pub unsafe extern "C" fn dc_accounts_background_fetch( } let accounts = unsafe { &*accounts }; - let background_fetch_future = { - let lock = block_on(accounts.read()); - lock.background_fetch(Duration::from_secs(timeout_in_seconds)) - }; - // At this point account manager is not locked anymore. - block_on(background_fetch_future); + let lock = block_on(accounts.read()); + lock.background_fetch(Duration::from_secs(timeout_in_seconds)); 1 } diff --git a/deltachat-jsonrpc/src/api.rs b/deltachat-jsonrpc/src/api.rs index 84c2c994a..48f8c85a6 100644 --- a/deltachat-jsonrpc/src/api.rs +++ b/deltachat-jsonrpc/src/api.rs @@ -283,12 +283,8 @@ impl CommandApi { /// Process all events until you get this one and you can safely return to the background /// without forgetting to create notifications caused by timing race conditions. async fn background_fetch(&self, timeout_in_seconds: f64) -> Result<()> { - let future = { - let lock = self.accounts.read().await; - lock.background_fetch(std::time::Duration::from_secs_f64(timeout_in_seconds)) - }; - // At this point account manager is not locked anymore. - future.await; + let lock = self.accounts.read().await; + lock.background_fetch(std::time::Duration::from_secs_f64(timeout_in_seconds)); Ok(()) } diff --git a/deltachat-jsonrpc/src/api/types/events.rs b/deltachat-jsonrpc/src/api/types/events.rs index 64ab1a3a4..286c23b25 100644 --- a/deltachat-jsonrpc/src/api/types/events.rs +++ b/deltachat-jsonrpc/src/api/types/events.rs @@ -30,37 +30,55 @@ pub enum EventType { /// /// This event should *not* be reported to the end-user using a popup or something like /// that. - Info { msg: String }, + Info { + msg: String, + }, /// Emitted when SMTP connection is established and login was successful. - SmtpConnected { msg: String }, + SmtpConnected { + msg: String, + }, /// Emitted when IMAP connection is established and login was successful. - ImapConnected { msg: String }, + ImapConnected { + msg: String, + }, /// Emitted when a message was successfully sent to the SMTP server. - SmtpMessageSent { msg: String }, + SmtpMessageSent { + msg: String, + }, /// Emitted when an IMAP message has been marked as deleted - ImapMessageDeleted { msg: String }, + ImapMessageDeleted { + msg: String, + }, /// Emitted when an IMAP message has been moved - ImapMessageMoved { msg: String }, + ImapMessageMoved { + msg: String, + }, /// Emitted before going into IDLE on the Inbox folder. ImapInboxIdle, /// Emitted when an new file in the $BLOBDIR was created - NewBlobFile { file: String }, + NewBlobFile { + file: String, + }, /// Emitted when an file in the $BLOBDIR was deleted - DeletedBlobFile { file: String }, + DeletedBlobFile { + file: String, + }, /// The library-user should write a warning string to the log. /// /// This event should *not* be reported to the end-user using a popup or something like /// that. - Warning { msg: String }, + Warning { + msg: String, + }, /// The library-user should report an error to the end-user. /// @@ -72,14 +90,18 @@ pub enum EventType { /// it might be better to delay showing these events until the function has really /// failed (returned false). It should be sufficient to report only the *last* error /// in a message box then. - Error { msg: String }, + Error { + msg: String, + }, /// An action cannot be performed because the user is not in the group. /// Reported eg. after a call to /// setChatName(), setChatProfileImage(), /// addContactToChat(), removeContactFromChat(), /// and messages sending functions. - ErrorSelfNotInGroup { msg: String }, + ErrorSelfNotInGroup { + msg: String, + }, /// Messages or chats changed. One or more messages or chats changed for various /// reasons in the database: @@ -168,7 +190,9 @@ pub enum EventType { /// Messages were seen or noticed. /// chat id is always set. #[serde(rename_all = "camelCase")] - MsgsNoticed { chat_id: u32 }, + MsgsNoticed { + chat_id: u32, + }, /// A single message is sent successfully. State changed from DC_STATE_OUT_PENDING to /// DC_STATE_OUT_DELIVERED, see `Message.state`. @@ -243,7 +267,9 @@ pub enum EventType { /// This event does not include ephemeral timer modification, which /// is a separate event. #[serde(rename_all = "camelCase")] - ChatModified { chat_id: u32 }, + ChatModified { + chat_id: u32, + }, /// Chat ephemeral timer changed. #[serde(rename_all = "camelCase")] @@ -304,7 +330,9 @@ pub enum EventType { /// /// @param data2 0 #[serde(rename_all = "camelCase")] - ImexFileWritten { path: String }, + ImexFileWritten { + path: String, + }, /// Progress event sent when SecureJoin protocol has finished /// from the view of the inviter (Alice, the person who shows the QR code). @@ -482,6 +510,9 @@ pub enum EventType { /// synchronization messages arrives, /// but not when the UI modifies the transport list by itself. TransportsModified, + + // TODO documentation + AccountsBackgroundFetchTimedOut, } impl From for EventType { @@ -675,6 +706,8 @@ impl From for EventType { }, CoreEventType::TransportsModified => TransportsModified, + CoreEventType::AccountsBackgroundFetchTimedOut => AccountsBackgroundFetchTimedOut, + #[allow(unreachable_patterns)] #[cfg(test)] _ => unreachable!("This is just to silence a rust_analyzer false-positive"), diff --git a/src/accounts.rs b/src/accounts.rs index 1efaa63d1..598bc5a2f 100644 --- a/src/accounts.rs +++ b/src/accounts.rs @@ -452,6 +452,10 @@ impl Accounts { ) .await { + events.emit(Event { + id: 0, + typ: EventType::AccountsBackgroundFetchTimedOut, + }); events.emit(Event { id: 0, typ: EventType::Warning("Background fetch timed out.".to_string()), @@ -461,14 +465,16 @@ impl Accounts { account_id = 0, "Background fetch timed out." ); + } else { + events.emit(Event { + id: 0, + typ: EventType::AccountsBackgroundFetchDone, + }); } - events.emit(Event { - id: 0, - typ: EventType::AccountsBackgroundFetchDone, - }); (*interrupt_sender.lock()) = None; } + // TODO adapt all the documentation /// Performs a background fetch for all accounts in parallel with a timeout. /// /// Ongoing background fetch can also be cancelled manually @@ -482,10 +488,7 @@ impl Accounts { /// /// Returns a future that resolves when background fetch is done, /// but does not capture `&self`. - pub fn background_fetch( - &self, - timeout: std::time::Duration, - ) -> impl Future + use<> { + pub fn background_fetch(&self, timeout: std::time::Duration) { let accounts: Vec = self.accounts.values().cloned().collect(); let events = self.events.clone(); let (sender, receiver) = async_channel::bounded(1); @@ -500,13 +503,17 @@ impl Accounts { Some(receiver) } }; - Self::background_fetch_with_timeout( - accounts, - events, - timeout, - self.background_fetch_interrupt_sender.clone(), - receiver, - ) + let background_fetch_interrupt_sender = self.background_fetch_interrupt_sender.clone(); + tokio::task::spawn(async move { + Self::background_fetch_with_timeout( + accounts, + events, + timeout, + background_fetch_interrupt_sender, + receiver, + ) + .await + }); } /// Interrupts ongoing background_fetch() call, diff --git a/src/events/payload.rs b/src/events/payload.rs index 5be165743..fce527536 100644 --- a/src/events/payload.rs +++ b/src/events/payload.rs @@ -447,4 +447,7 @@ pub enum EventType { /// Number of events skipped. n: u64, }, + + // TODO documentation + AccountsBackgroundFetchTimedOut, }