mirror of
https://github.com/chatmail/core.git
synced 2026-10-01 18:50:39 +03:00
fix: always emit AccountsBackgroundFetchDone
A second background_fetch() while one is already running returned without emitting the event, and the FFI returned 1 for it, so a UI waiting for an event hangs dc_get_next_event(). Emit the event in any case, so waiting for it is safe.
This commit is contained in:
+31
-1
@@ -443,7 +443,12 @@ impl Accounts {
|
||||
interrupt_receiver: Option<Receiver<()>>,
|
||||
) {
|
||||
let Some(interrupt_receiver) = interrupt_receiver else {
|
||||
// Nothing to do if we got no interrupt receiver.
|
||||
// Another background fetch is already running.
|
||||
// Emit the event anyway so that a caller waiting for it does not hang.
|
||||
events.emit(Event {
|
||||
id: 0,
|
||||
typ: EventType::AccountsBackgroundFetchDone,
|
||||
});
|
||||
return;
|
||||
};
|
||||
if let Err(_err) = tokio::time::timeout(
|
||||
@@ -480,6 +485,8 @@ impl Accounts {
|
||||
/// The `AccountsBackgroundFetchDone` event is emitted at the end,
|
||||
/// 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.
|
||||
/// If another background fetch is already running,
|
||||
/// nothing is fetched and the event is emitted immediately.
|
||||
///
|
||||
/// Returns a future that resolves when background fetch is done,
|
||||
/// but does not capture `&self`.
|
||||
@@ -1239,6 +1246,29 @@ mod tests {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_background_fetch_emits_done_when_already_running() -> Result<()> {
|
||||
let dir = tempfile::tempdir()?;
|
||||
let writable = true;
|
||||
let accounts = Accounts::new(dir.path().join("accounts"), writable).await?;
|
||||
let event_emitter = accounts.get_event_emitter();
|
||||
|
||||
let timeout = std::time::Duration::from_secs(3);
|
||||
let first = accounts.background_fetch(timeout);
|
||||
let second = accounts.background_fetch(timeout);
|
||||
tokio::join!(first, second);
|
||||
|
||||
let mut done = 0;
|
||||
while let Ok(event) = event_emitter.try_recv() {
|
||||
if matches!(event.typ, EventType::AccountsBackgroundFetchDone) {
|
||||
done += 1;
|
||||
}
|
||||
}
|
||||
assert_eq!(done, 2);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn test_encrypted_account() -> Result<()> {
|
||||
let dir = tempfile::tempdir().context("failed to create tempdir")?;
|
||||
|
||||
@@ -357,11 +357,15 @@ pub enum EventType {
|
||||
msg_id: MsgId,
|
||||
},
|
||||
|
||||
/// Tells that the Background fetch was completed (or timed out).
|
||||
/// This event acts as a marker, when you reach this event you can be sure
|
||||
/// that all events emitted during the background fetch were processed.
|
||||
/// Tells that a background fetch call is done:
|
||||
/// the fetch completed, timed out, was stopped or was not started.
|
||||
///
|
||||
/// This event is only emitted by the account manager
|
||||
/// For the call that started the fetch, this event acts as a marker:
|
||||
/// all events emitted during the fetch were processed once it is reached.
|
||||
/// A call made while another background fetch is running gets the event immediately,
|
||||
/// and the running fetch keeps emitting events until its own marker.
|
||||
///
|
||||
/// This event is only emitted by the account manager.
|
||||
AccountsBackgroundFetchDone,
|
||||
/// Inform that set of chats or the order of the chats in the chatlist has changed.
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user