mirror of
https://github.com/chatmail/core.git
synced 2026-05-20 23:36:30 +03:00
add dc_get_last_error() (#2788)
* add dc_get_last_error() * make clippy happy * simplify block_on() call
This commit is contained in:
@@ -2414,6 +2414,22 @@ dc_array_t* dc_get_locations (dc_context_t* context, uint32_t cha
|
|||||||
void dc_delete_all_locations (dc_context_t* context);
|
void dc_delete_all_locations (dc_context_t* context);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get last error string.
|
||||||
|
*
|
||||||
|
* This is the same error string as logged via #DC_EVENT_ERROR,
|
||||||
|
* however, using this function avoids race conditions
|
||||||
|
* if the failing function is called in another thread than dc_get_next_event().
|
||||||
|
*
|
||||||
|
* @memberof dc_context_t
|
||||||
|
* @param context The context object.
|
||||||
|
* @return Last error or an empty string if there is no last error.
|
||||||
|
* NULL is never returned.
|
||||||
|
* The returned value must be released using dc_str_unref() after usage.
|
||||||
|
*/
|
||||||
|
char* dc_get_last_error (dc_context_t* context);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Release a string returned by another deltachat-core function.
|
* Release a string returned by another deltachat-core function.
|
||||||
* - Strings returned by any deltachat-core-function
|
* - Strings returned by any deltachat-core-function
|
||||||
|
|||||||
@@ -2206,6 +2206,16 @@ pub unsafe extern "C" fn dc_delete_all_locations(context: *mut dc_context_t) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub unsafe extern "C" fn dc_get_last_error(context: *mut dc_context_t) -> *mut libc::c_char {
|
||||||
|
if context.is_null() {
|
||||||
|
eprintln!("ignoring careless call to dc_get_last_error()");
|
||||||
|
return "".strdup();
|
||||||
|
}
|
||||||
|
let ctx = &*context;
|
||||||
|
block_on(ctx.get_last_error()).strdup()
|
||||||
|
}
|
||||||
|
|
||||||
// dc_array_t
|
// dc_array_t
|
||||||
|
|
||||||
pub type dc_array_t = dc_array::dc_array_t;
|
pub type dc_array_t = dc_array::dc_array_t;
|
||||||
|
|||||||
@@ -76,6 +76,11 @@ pub struct InnerContext {
|
|||||||
pub(crate) id: u32,
|
pub(crate) id: u32,
|
||||||
|
|
||||||
creation_time: SystemTime,
|
creation_time: SystemTime,
|
||||||
|
|
||||||
|
/// The text of the last error logged and emitted as an event.
|
||||||
|
/// If the ui wants to display an error after a failure,
|
||||||
|
/// `last_error` should be used to avoid races with the event thread.
|
||||||
|
pub(crate) last_error: RwLock<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -147,6 +152,7 @@ impl Context {
|
|||||||
quota: RwLock::new(None),
|
quota: RwLock::new(None),
|
||||||
creation_time: std::time::SystemTime::now(),
|
creation_time: std::time::SystemTime::now(),
|
||||||
last_full_folder_scan: Mutex::new(None),
|
last_full_folder_scan: Mutex::new(None),
|
||||||
|
last_error: RwLock::new("".to_string()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let ctx = Context {
|
let ctx = Context {
|
||||||
|
|||||||
47
src/log.rs
47
src/log.rs
@@ -1,6 +1,7 @@
|
|||||||
//! # Logging.
|
//! # Logging.
|
||||||
|
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
|
use async_std::task::block_on;
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! info {
|
macro_rules! info {
|
||||||
@@ -39,10 +40,28 @@ macro_rules! error {
|
|||||||
};
|
};
|
||||||
($ctx:expr, $msg:expr, $($args:expr),* $(,)?) => {{
|
($ctx:expr, $msg:expr, $($args:expr),* $(,)?) => {{
|
||||||
let formatted = format!($msg, $($args),*);
|
let formatted = format!($msg, $($args),*);
|
||||||
|
$ctx.set_last_error(&formatted);
|
||||||
$ctx.emit_event($crate::EventType::Error(formatted));
|
$ctx.emit_event($crate::EventType::Error(formatted));
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Context {
|
||||||
|
/// Set last error string.
|
||||||
|
/// Implemented as blocking as used from macros in different, not always async blocks.
|
||||||
|
pub fn set_last_error(&self, error: &str) {
|
||||||
|
block_on(async move {
|
||||||
|
let mut last_error = self.last_error.write().await;
|
||||||
|
*last_error = error.to_string();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get last error string.
|
||||||
|
pub async fn get_last_error(&self) -> String {
|
||||||
|
let last_error = &*self.last_error.read().await;
|
||||||
|
last_error.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait LogExt<T, E>
|
pub trait LogExt<T, E>
|
||||||
where
|
where
|
||||||
Self: std::marker::Sized,
|
Self: std::marker::Sized,
|
||||||
@@ -134,3 +153,31 @@ impl<T, E: std::fmt::Display> LogExt<T, E> for Result<T, E> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::test_utils::TestContext;
|
||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
#[async_std::test]
|
||||||
|
async fn test_get_last_error() -> Result<()> {
|
||||||
|
let t = TestContext::new().await;
|
||||||
|
|
||||||
|
assert_eq!(t.get_last_error().await, "");
|
||||||
|
|
||||||
|
error!(t, "foo-error");
|
||||||
|
assert_eq!(t.get_last_error().await, "foo-error");
|
||||||
|
|
||||||
|
warn!(t, "foo-warning");
|
||||||
|
assert_eq!(t.get_last_error().await, "foo-error");
|
||||||
|
|
||||||
|
info!(t, "foo-info");
|
||||||
|
assert_eq!(t.get_last_error().await, "foo-error");
|
||||||
|
|
||||||
|
error!(t, "bar-error");
|
||||||
|
error!(t, "baz-error");
|
||||||
|
assert_eq!(t.get_last_error().await, "baz-error");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user