mirror of
https://github.com/chatmail/core.git
synced 2026-04-29 11:26:29 +03:00
Fix imex race condition, (#2255)
fix #2254: if the DB was closed without calling stop_io() and then an interrupt arrives (e.g. incoming message), the db was corrupted. * Add result.log() for logging with less boilerplate code * Bugfix: Resultify housekeeping() to make it abort if the db is closed instead of just deleting everything * Require the UI to call dc_stop_io() before backup export * Prepare a bit better for closed-db: Resultify get_uidvalidity and get_uid_next and let job::load_next() wait until the db is open About the bug (before this PR): if the DB was closed without calling stop_io() and then an interrupt arrives (e.g. incoming message): - I don't know if it downloads the message, but of course at some point the process of receiving the message will fail - In my test, DC is just in the process of moving a message when the imex starts, but then can't delete the job or update the msg server_uid - Then, when job::load_next() is called, no job can be loaded. That's why it calls `load_housekeeping_job()`. As `load_housekeeping_job()` can't load the time of the last housekeeping, it assumes we never ran housekeeping and returns a new Housekeeping job, which is immediately executed. - housekeeping can't find any blobs referenced in the db and therefore deletes almost all blobs.
This commit is contained in:
40
src/log.rs
40
src/log.rs
@@ -1,4 +1,6 @@
|
||||
//! # Logging macros
|
||||
//! # Logging
|
||||
|
||||
use crate::context::Context;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! info {
|
||||
@@ -58,3 +60,39 @@ macro_rules! emit_event {
|
||||
$ctx.emit_event($event);
|
||||
};
|
||||
}
|
||||
|
||||
pub trait LogExt<T> {
|
||||
/// Emits a warning if the receiver contains an Err value.
|
||||
///
|
||||
/// Returns an [`Option<T>`] with the `Ok(_)` value, if any:
|
||||
/// - You won't get any warnings about unused results but can still use the value if you need it
|
||||
/// - This prevents the same warning from being printed to the log multiple times
|
||||
///
|
||||
/// Thanks to the [track_caller](https://blog.rust-lang.org/2020/08/27/Rust-1.46.0.html#track_caller)
|
||||
/// feature, the location of the caller is printed to the log, just like with the warn!() macro.
|
||||
#[track_caller]
|
||||
fn log(self, context: &Context) -> Option<T>;
|
||||
}
|
||||
|
||||
impl<T> LogExt<T> for anyhow::Result<T> {
|
||||
#[track_caller]
|
||||
fn log(self, context: &Context) -> Option<T> {
|
||||
match self {
|
||||
Err(e) => {
|
||||
let location = std::panic::Location::caller();
|
||||
// We are using Anyhow's .context() and to show the inner error, too, we need the {:#}:
|
||||
let full = format!(
|
||||
"{file}:{line}: {e:#}",
|
||||
file = location.file(),
|
||||
line = location.line(),
|
||||
e = e
|
||||
);
|
||||
// We can't use the warn!() macro here as the file!() and line!() macros
|
||||
// don't work well with #[track_caller]
|
||||
emit_event!(context, crate::EventType::Warning(full));
|
||||
None
|
||||
}
|
||||
Ok(v) => Some(v),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user