feat: add background fetch method

This commit is contained in:
Simon Laux
2023-12-12 00:03:47 +01:00
committed by bjoern
parent 48f2ea717e
commit 7b68098785
2 changed files with 59 additions and 2 deletions

View File

@@ -5,6 +5,7 @@ use std::future::Future;
use std::path::{Path, PathBuf};
use anyhow::{ensure, Context as _, Result};
use futures::future::join_all;
use serde::{Deserialize, Serialize};
use tokio::fs;
use tokio::io::AsyncWriteExt;
@@ -291,6 +292,33 @@ impl Accounts {
}
}
/// Performs a background fetch for all accounts in parallel.
///
/// If you need a timeout, then use [Accounts::background_fetch_with_timeout] instead.
pub async fn background_fetch(&self) {
async fn background_fetch_and_log_error(account: Context) {
if let Err(error) = account.background_fetch().await {
warn!(account, "{error:#}");
}
}
join_all(
self.accounts
.values()
.cloned()
.map(background_fetch_and_log_error),
)
.await;
}
/// Performs a background fetch for all accounts in parallel with a timeout.
///
/// If you want no timeout, then use [Accounts::background_fetch] instead.
pub async fn background_fetch_with_timeout(&self, timeout: Duration) -> Result<()> {
tokio::time::timeout(timeout, self.background_fetch()).await?;
Ok(())
}
/// Emits a single event.
pub fn emit_event(&self, event: EventType) {
self.events.emit(Event { id: 0, typ: event })

View File

@@ -19,12 +19,12 @@ use crate::constants::DC_VERSION_STR;
use crate::contact::Contact;
use crate::debug_logging::DebugLogging;
use crate::events::{Event, EventEmitter, EventType, Events};
use crate::imap::ServerMetadata;
use crate::imap::{FolderMeaning, Imap, ServerMetadata};
use crate::key::{load_self_public_key, DcKey as _};
use crate::login_param::LoginParam;
use crate::message::{self, MessageState, MsgId};
use crate::quota::QuotaInfo;
use crate::scheduler::SchedulerState;
use crate::scheduler::{convert_folder_meaning, SchedulerState};
use crate::sql::Sql;
use crate::stock_str::StockStrings;
use crate::timesmearing::SmearedTimestamp;
@@ -441,6 +441,35 @@ impl Context {
self.scheduler.maybe_network().await;
}
/// Do a background fetch
/// pauses the scheduler and does one imap fetch, then unpauses and returns
pub async fn background_fetch(&self) -> Result<()> {
if !(self.is_configured().await?) {
return Ok(());
}
let _pause_guard = self.scheduler.pause(self.clone()).await?;
// connection
let mut connection = Imap::new_configured(self, channel::bounded(1).1).await?;
connection.prepare(self).await?;
// fetch imap folders
for folder_meaning in [FolderMeaning::Inbox, FolderMeaning::Mvbox] {
let (_, watch_folder) = convert_folder_meaning(self, folder_meaning).await?;
connection
.fetch_move_delete(self, &watch_folder, folder_meaning)
.await?;
}
// update quota (to send warning if full)
if let Err(err) = self.update_recent_quota(&mut connection).await {
warn!(self, "Failed to update quota: {:#}.", err);
}
Ok(())
}
pub(crate) async fn schedule_resync(&self) -> Result<()> {
self.resync_request.store(true, Ordering::Relaxed);
self.scheduler.interrupt_inbox().await;