Compare commits

...

33 Commits

Author SHA1 Message Date
Septias
299ac4b39e clean up rebase 2022-12-06 19:14:40 +01:00
Hocuri
d14ae03356 Don't add the webxdc twice if the setting is set twice 2022-12-06 17:23:12 +01:00
Hocuri
55922db33c link2xt's review 2022-12-06 17:23:12 +01:00
Hocuri
d28ed719be Change to using block_on() 2022-12-06 17:23:12 +01:00
Septias
593ad9f7cf another try 2022-12-06 17:23:12 +01:00
Septias
28313a1b85 try pushing 2022-12-06 17:23:12 +01:00
Septias
7b7929ff78 debug xdc 2022-12-06 17:23:12 +01:00
Septias
738114752d new xdc 2022-12-06 17:23:12 +01:00
Septias
84b73a9e6a debug xdc 2022-12-06 17:23:12 +01:00
Septias
181996873b new webxdc 2022-12-06 17:23:12 +01:00
Septias
2749c1d52d fix problems 2022-12-06 17:23:12 +01:00
Sebastian Klähn
4dd6bf591f new xdc fixing mentioned problems 2022-12-06 17:23:12 +01:00
Hocuri
0e0decfd8a Unify duplicate code 2022-12-06 17:23:12 +01:00
Hocuri
9b8a95b69f Docs 2022-12-06 17:21:51 +01:00
Hocuri
0fb3c4c8ca bugfix 2022-12-06 17:21:12 +01:00
Hocuri
5a856eccef Use spawn() instead of block_on() again because it reportedly might lead to deadlocks
Also, fix some minor stuff
2022-12-06 17:21:12 +01:00
Hocuri
2fdab88d19 Introduce a flag debug_logging on the core 2022-12-06 17:21:12 +01:00
Septias
fc30bbbe4f change styling of webxdc 2022-12-06 17:18:56 +01:00
Septias
aef84cfd69 use event name instead of event id 2022-12-06 17:18:56 +01:00
Hocuri
86fc553294 Add send_events benchmark 2022-12-06 17:18:12 +01:00
Septias
c3d99e1016 new webxdc 2022-12-06 17:18:12 +01:00
Hocuri
7d19b87f44 . 2022-12-06 17:18:12 +01:00
Septias
2e5456eb3a new wexdc 2022-12-06 17:18:12 +01:00
Septias
ae3ae6717d add webxdc 2022-12-06 17:18:12 +01:00
Hocuri
7479b97a00 Actually set the config 2022-12-06 17:18:12 +01:00
Simon Laux
c46d61356d fix context::tests::test_get_info_completeness 2022-12-06 17:18:12 +01:00
Simon Laux
948f6906cb log to status update
& send webxdc update event
2022-12-06 17:18:12 +01:00
Hocuri
0538e68638 Disable debug logging if the webxdc message is deleted 2022-12-06 17:15:26 +01:00
Hocuri
e6ae2170a8 Fix more compiler problems 2022-12-06 17:15:26 +01:00
Simon Laux
63162394f6 fix compile error on events.rs 2022-12-06 17:14:08 +01:00
Hocuri
c6369ce691 fix some compiler issues 2022-12-06 17:14:08 +01:00
Simon Laux
b20f03775a events to json 2022-12-06 17:13:05 +01:00
Hocuri
b5d6f44b13 Debug logging, second try 2022-12-06 17:11:52 +01:00
12 changed files with 394 additions and 138 deletions

View File

@@ -1,7 +1,6 @@
# Changelog
## Unreleased
### Changes
- Disable Autocrypt & Authres-checking for mailing lists,
because they don't work well with mailing lists #3765
@@ -14,6 +13,7 @@
- Add Python API to send reactions #3762
- jsonrpc: add message errors to MessageObject #3788
- jsonrpc: Add async Python client #3734
- add `debug_logging` setting #3296
### Fixes
- Make sure malformed messsages will never block receiving further messages anymore #3771

View File

@@ -137,6 +137,10 @@ harness = false
name = "get_chatlist"
harness = false
[[bench]]
name = "send_events"
harness = false
[features]
default = ["vendored"]
internals = []

BIN
assets/webxdc_logging.xdc Normal file

Binary file not shown.

48
benches/send_events.rs Normal file
View File

@@ -0,0 +1,48 @@
use criterion::{criterion_group, criterion_main, Criterion};
use deltachat::context::Context;
use deltachat::stock_str::StockStrings;
use deltachat::{info, Event, EventType, Events};
use tempfile::tempdir;
async fn send_events_benchmark(context: &Context) {
let emitter = context.get_event_emitter();
for _i in 0..1_000_000 {
info!(context, "interesting event...");
}
info!(context, "DONE");
loop {
match emitter.recv().await.unwrap() {
Event {
typ: EventType::Info(info),
..
} if info.contains("DONE") => {
break;
}
_ => {}
}
}
}
fn criterion_benchmark(c: &mut Criterion) {
let dir = tempdir().unwrap();
let dbfile = dir.path().join("db.sqlite");
let id = 100;
let rt = tokio::runtime::Runtime::new().unwrap();
let context = rt.block_on(async {
Context::new(&dbfile, id, Events::new(), StockStrings::new())
.await
.expect("failed to create context")
});
let executor = tokio::runtime::Runtime::new().unwrap();
c.bench_function("Sending 1000 events", |b| {
b.to_async(&executor)
.iter(|| send_events_benchmark(&context))
});
}
criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);

View File

@@ -407,6 +407,10 @@ char* dc_get_blobdir (const dc_context_t* context);
* to not mess up with non-delivery-reports or read-receipts.
* 0=no limit (default).
* Changes affect future messages only.
* - `debug_logging` = 1=Let the core save all events to the database. You should expose this as an advanced
* setting to the user. When they enable it, the core automatically adds a webxdc
* message to the device chat where the user can see the log messages.
* 0=disable debug logging (default)
* - `ui.*` = All keys prefixed by `ui.` can be used by the user-interfaces for system-specific purposes.
* The prefix should be followed by the system and maybe subsystem,
* e.g. `ui.desktop.foo`, `ui.desktop.linux.bar`, `ui.android.foo`, `ui.dc40.bar`, `ui.bot.simplebot.baz`.

View File

@@ -530,47 +530,8 @@ pub unsafe extern "C" fn dc_event_get_data1_int(event: *mut dc_event_t) -> libc:
eprintln!("ignoring careless call to dc_event_get_data1_int()");
return 0;
}
let event = &(*event).typ;
match event {
EventType::Info(_)
| EventType::SmtpConnected(_)
| EventType::ImapConnected(_)
| EventType::SmtpMessageSent(_)
| EventType::ImapMessageDeleted(_)
| EventType::ImapMessageMoved(_)
| EventType::NewBlobFile(_)
| EventType::DeletedBlobFile(_)
| EventType::Warning(_)
| EventType::Error(_)
| EventType::ConnectivityChanged
| EventType::SelfavatarChanged
| EventType::IncomingMsgBunch { .. }
| EventType::ErrorSelfNotInGroup(_) => 0,
EventType::MsgsChanged { chat_id, .. }
| EventType::ReactionsChanged { chat_id, .. }
| EventType::IncomingMsg { chat_id, .. }
| EventType::MsgsNoticed(chat_id)
| EventType::MsgDelivered { chat_id, .. }
| EventType::MsgFailed { chat_id, .. }
| EventType::MsgRead { chat_id, .. }
| EventType::ChatModified(chat_id)
| EventType::ChatEphemeralTimerModified { chat_id, .. } => chat_id.to_u32() as libc::c_int,
EventType::ContactsChanged(id) | EventType::LocationChanged(id) => {
let id = id.unwrap_or_default();
id.to_u32() as libc::c_int
}
EventType::ConfigureProgress { progress, .. } | EventType::ImexProgress(progress) => {
*progress as libc::c_int
}
EventType::ImexFileWritten(_) => 0,
EventType::SecurejoinInviterProgress { contact_id, .. }
| EventType::SecurejoinJoinerProgress { contact_id, .. } => {
contact_id.to_u32() as libc::c_int
}
EventType::WebxdcStatusUpdate { msg_id, .. } => msg_id.to_u32() as libc::c_int,
EventType::WebxdcInstanceDeleted { msg_id, .. } => msg_id.to_u32() as libc::c_int,
}
event.get_data1_int() as libc::c_int
}
#[no_mangle]
@@ -581,43 +542,10 @@ pub unsafe extern "C" fn dc_event_get_data2_int(event: *mut dc_event_t) -> libc:
}
let event = &(*event).typ;
match event {
EventType::Info(_)
| EventType::SmtpConnected(_)
| EventType::ImapConnected(_)
| EventType::SmtpMessageSent(_)
| EventType::ImapMessageDeleted(_)
| EventType::ImapMessageMoved(_)
| EventType::NewBlobFile(_)
| EventType::DeletedBlobFile(_)
| EventType::Warning(_)
| EventType::Error(_)
| EventType::ErrorSelfNotInGroup(_)
| EventType::ContactsChanged(_)
| EventType::LocationChanged(_)
| EventType::ConfigureProgress { .. }
| EventType::ImexProgress(_)
| EventType::ImexFileWritten(_)
| EventType::MsgsNoticed(_)
| EventType::ConnectivityChanged
| EventType::WebxdcInstanceDeleted { .. }
| EventType::IncomingMsgBunch { .. }
| EventType::SelfavatarChanged => 0,
EventType::ChatModified(_) => 0,
EventType::MsgsChanged { msg_id, .. }
| EventType::ReactionsChanged { msg_id, .. }
| EventType::IncomingMsg { msg_id, .. }
| EventType::MsgDelivered { msg_id, .. }
| EventType::MsgFailed { msg_id, .. }
| EventType::MsgRead { msg_id, .. } => msg_id.to_u32() as libc::c_int,
EventType::SecurejoinInviterProgress { progress, .. }
| EventType::SecurejoinJoinerProgress { progress, .. } => *progress as libc::c_int,
EventType::ChatEphemeralTimerModified { timer, .. } => timer.to_u32() as libc::c_int,
EventType::WebxdcStatusUpdate {
status_update_serial,
..
} => status_update_serial.to_u32() as libc::c_int,
if let Some(data2) = event.get_data2_int() {
data2 as libc::c_int
} else {
0
}
}
@@ -629,56 +557,25 @@ pub unsafe extern "C" fn dc_event_get_data2_str(event: *mut dc_event_t) -> *mut
}
let event = &(*event).typ;
match event {
EventType::Info(msg)
| EventType::SmtpConnected(msg)
| EventType::ImapConnected(msg)
| EventType::SmtpMessageSent(msg)
| EventType::ImapMessageDeleted(msg)
| EventType::ImapMessageMoved(msg)
| EventType::NewBlobFile(msg)
| EventType::DeletedBlobFile(msg)
| EventType::Warning(msg)
| EventType::Error(msg)
| EventType::ErrorSelfNotInGroup(msg) => {
let data2 = msg.to_c_string().unwrap_or_default();
data2.into_raw()
}
EventType::MsgsChanged { .. }
| EventType::ReactionsChanged { .. }
| EventType::IncomingMsg { .. }
| EventType::MsgsNoticed(_)
| EventType::MsgDelivered { .. }
| EventType::MsgFailed { .. }
| EventType::MsgRead { .. }
| EventType::ChatModified(_)
| EventType::ContactsChanged(_)
| EventType::LocationChanged(_)
| EventType::ImexProgress(_)
| EventType::SecurejoinInviterProgress { .. }
| EventType::SecurejoinJoinerProgress { .. }
| EventType::ConnectivityChanged
| EventType::SelfavatarChanged
| EventType::WebxdcStatusUpdate { .. }
| EventType::WebxdcInstanceDeleted { .. }
| EventType::ChatEphemeralTimerModified { .. } => ptr::null_mut(),
EventType::ConfigureProgress { comment, .. } => {
if let Some(comment) = comment {
comment.to_c_string().unwrap_or_default().into_raw()
} else {
ptr::null_mut()
}
}
EventType::ImexFileWritten(file) => {
let data2 = file.to_c_string().unwrap_or_default();
data2.into_raw()
}
EventType::IncomingMsgBunch { msg_ids } => serde_json::to_string(msg_ids)
.unwrap_or_default()
.to_c_string()
.unwrap_or_default()
.into_raw(),
EventType::ImexFileWritten(file) => {
// Directly convert the PathBuf file to a CString, since both can contain invalid
// UTF-8, but a Rust `String` can't
let data2 = file.to_c_string().unwrap_or_default();
data2.into_raw()
}
_ => {
if let Some(data2) = event.get_data2_str() {
data2.to_c_string().unwrap_or_default().into_raw()
} else {
ptr::null_mut()
}
}
}
}

View File

@@ -1,14 +1,20 @@
//! # Key-value configuration management.
use std::sync::atomic;
use anyhow::{ensure, Context as _, Result};
use strum::{EnumProperty as EnumPropertyTrait, IntoEnumIterator};
use strum::{EnumProperty, IntoEnumIterator};
use strum_macros::{AsRefStr, Display, EnumIter, EnumProperty, EnumString};
use crate::blob::BlobObject;
use crate::chat;
use crate::constants::DC_VERSION_STR;
use crate::contact::addr_cmp;
use crate::context::Context;
use crate::events::EventType;
use crate::message::{self, Message, MsgId, Viewtype};
use crate::mimefactory::RECOMMENDED_FILE_SIZE;
use crate::provider::{get_provider_by_id, Provider};
use crate::tools::{get_abs_path, improve_single_line_input, EmailAddress};
@@ -190,6 +196,13 @@ pub enum Config {
///
/// See `crate::authres::update_authservid_candidates`.
AuthservIdCandidates,
// TODO docs, deltachat.h
/// Let the core save all events to the database. You should expose this as an advanced
/// setting to the user. When they enable it, the core automatically adds a webxdc
/// message to the device chat where the user can see the log messages.
#[strum(props(default = "0"))]
DebugLogging,
}
impl Context {
@@ -319,6 +332,39 @@ impl Context {
.set_raw_config(key.as_ref(), value.as_deref())
.await?;
}
Config::DebugLogging => {
if value == Some("0") || value == Some("") || value == None {
if let Some(webxdc_message_id) =
self.sql.get_raw_config_u32(Config::DebugLogging.as_ref()).await?
{
message::delete_msgs(self, &[MsgId::new(webxdc_message_id)]).await?;
}
self.sql.set_raw_config(key.as_ref(), None).await?;
self.debug_logging.store(0, atomic::Ordering::Relaxed);
} else if self
.sql
.get_raw_config_u32(Config::DebugLogging.as_ref())
.await?
.unwrap_or(0)
== 0
{
// the unbundled version lives at https://github.com/webxdc/webxdc_logging
let data: &[u8] = include_bytes!("../assets/webxdc_logging.xdc");
let file = BlobObject::create(self, "webxdc_debug_logging.xdc", data).await?;
let mut instance = Message::new(Viewtype::Webxdc);
instance.set_file(
file.to_abs_path().to_str().context("Non-UTF-8 blob file")?,
None,
);
let msg_id = chat::add_device_msg(self, None, Some(&mut instance)).await?;
self.sql
.set_raw_config(key.as_ref(), Some(&msg_id.to_u32().to_string()))
.await?;
self.debug_logging
.store(msg_id.to_u32(), atomic::Ordering::Relaxed);
}
}
_ => {
self.sql.set_raw_config(key.as_ref(), value).await?;
}

View File

@@ -6,6 +6,7 @@ use std::ops::Deref;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::time::{Duration, Instant, SystemTime};
use std::sync::atomic::{self, AtomicU32};
use anyhow::{ensure, Result};
use async_channel::{self as channel, Receiver, Sender};
@@ -25,6 +26,7 @@ use crate::scheduler::Scheduler;
use crate::sql::Sql;
use crate::stock_str::StockStrings;
use crate::tools::{duration_to_str, time};
use crate::webxdc::StatusUpdateItem;
/// Builder for the [`Context`].
///
@@ -231,6 +233,8 @@ pub struct InnerContext {
/// 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: std::sync::RwLock<String>,
pub(crate) debug_logging: AtomicU32,
}
/// The state of ongoing process.
@@ -361,6 +365,7 @@ impl Context {
creation_time: std::time::SystemTime::now(),
last_full_folder_scan: Mutex::new(None),
last_error: std::sync::RwLock::new("".to_string()),
debug_logging: AtomicU32::default(),
};
let ctx = Context {
@@ -434,8 +439,62 @@ impl Context {
pub fn emit_event(&self, event: EventType) {
self.events.emit(Event {
id: self.id,
typ: event,
typ: event.clone(),
});
// `task::block_on()` below is not how async is meant to be used
// since `emit_event()` is often called from an async context.
// This could generally lead to deadlocks, so we make sure to only
// call it if `debug_logging` is on. It's not that much of a problem
// since most of the things we do in the `async` block - esp. the
// database access - is blocking anyway.
//
// A better solution would be to make `emit_event()` async or to
// create a debug_logger background loop.
//
// Alternatively, we could use `task::spawn()`; this would be
// non-deterministic, so that the logs might get out of order, and
// it could make e.g. backups fail since it could still run in the
// background while trying to move/close the database.
let debug_logging = self.debug_logging.load(atomic::Ordering::Relaxed);
if debug_logging > 0 {
let time = SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.unwrap_or_default()
.as_millis() as i64;
let context = self.clone();
let rt = tokio::runtime::Runtime::new().unwrap();
rt.block_on(async move {
let webxdc_instance_id = MsgId::new(debug_logging as u32);
match context
.write_status_update_inner(
&webxdc_instance_id,
StatusUpdateItem {
payload: event.to_json(Some(time)),
info: None,
summary: None,
document: None,
},
)
.await
{
Err(err) => {
eprintln!("Can't log event to webxdc status update: {:#}", err);
}
Ok(serial) => {
context.events.emit(Event {
id: context.id,
typ: EventType::WebxdcStatusUpdate {
msg_id: webxdc_instance_id,
status_update_serial: serial,
},
});
}
}
});
}
}
/// Emits a generic MsgsChanged event (without chat or message id)
@@ -706,6 +765,11 @@ impl Context {
.unwrap_or_default(),
);
res.insert(
"debug_logging",
self.get_config_int(Config::DebugLogging).await?.to_string(),
);
let elapsed = self.creation_time.elapsed();
res.insert("uptime", duration_to_str(elapsed.unwrap_or_default()));

View File

@@ -3,6 +3,8 @@
use std::path::PathBuf;
use async_channel::{self as channel, Receiver, Sender, TrySendError};
use num_traits::ToPrimitive;
use serde_json::Value;
use crate::chat::ChatId;
use crate::contact::ContactId;
@@ -106,7 +108,7 @@ pub struct Event {
pub typ: EventType,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, Display)]
pub enum EventType {
/// The library-user may write an informational string to the log.
///
@@ -319,3 +321,155 @@ pub enum EventType {
msg_id: MsgId,
},
}
impl EventType {
pub fn get_data1_int(&self) -> u32 {
match self {
EventType::Info(_)
| EventType::SmtpConnected(_)
| EventType::ImapConnected(_)
| EventType::SmtpMessageSent(_)
| EventType::ImapMessageDeleted(_)
| EventType::ImapMessageMoved(_)
| EventType::NewBlobFile(_)
| EventType::DeletedBlobFile(_)
| EventType::Warning(_)
| EventType::Error(_)
| EventType::ConnectivityChanged
| EventType::SelfavatarChanged
| EventType::IncomingMsgBunch { .. }
| EventType::ErrorSelfNotInGroup(_) => 0,
EventType::MsgsChanged { chat_id, .. }
| EventType::ReactionsChanged { chat_id, .. }
| EventType::IncomingMsg { chat_id, .. }
| EventType::MsgsNoticed(chat_id)
| EventType::MsgDelivered { chat_id, .. }
| EventType::MsgFailed { chat_id, .. }
| EventType::MsgRead { chat_id, .. }
| EventType::ChatModified(chat_id)
| EventType::ChatEphemeralTimerModified { chat_id, .. } => chat_id.to_u32(),
EventType::ContactsChanged(id) | EventType::LocationChanged(id) => {
id.unwrap_or_default().to_u32()
}
EventType::ConfigureProgress { progress, .. } | EventType::ImexProgress(progress) => {
(*progress).to_u32().unwrap_or_default()
}
EventType::ImexFileWritten(_) => 0,
EventType::SecurejoinInviterProgress { contact_id, .. }
| EventType::SecurejoinJoinerProgress { contact_id, .. } => contact_id.to_u32(),
EventType::WebxdcStatusUpdate { msg_id, .. } => msg_id.to_u32(),
EventType::WebxdcInstanceDeleted { msg_id, .. } => msg_id.to_u32(),
}
}
pub fn get_data2_int(&self) -> Option<u32> {
match self {
EventType::Info(_)
| EventType::SmtpConnected(_)
| EventType::ImapConnected(_)
| EventType::SmtpMessageSent(_)
| EventType::ImapMessageDeleted(_)
| EventType::ImapMessageMoved(_)
| EventType::NewBlobFile(_)
| EventType::DeletedBlobFile(_)
| EventType::Warning(_)
| EventType::Error(_)
| EventType::ErrorSelfNotInGroup(_)
| EventType::ContactsChanged(_)
| EventType::LocationChanged(_)
| EventType::ConfigureProgress { .. }
| EventType::ImexProgress(_)
| EventType::ImexFileWritten(_)
| EventType::MsgsNoticed(_)
| EventType::ConnectivityChanged
| EventType::WebxdcInstanceDeleted { .. }
| EventType::IncomingMsgBunch { .. }
| EventType::ChatModified(_)
| EventType::SelfavatarChanged => None,
EventType::MsgsChanged { msg_id, .. }
| EventType::ReactionsChanged { msg_id, .. }
| EventType::IncomingMsg { msg_id, .. }
| EventType::MsgDelivered { msg_id, .. }
| EventType::MsgFailed { msg_id, .. }
| EventType::MsgRead { msg_id, .. } => Some(msg_id.to_u32()),
EventType::SecurejoinInviterProgress { progress, .. }
| EventType::SecurejoinJoinerProgress { progress, .. } => (*progress).to_u32(),
EventType::ChatEphemeralTimerModified { timer, .. } => Some(timer.to_u32()),
EventType::WebxdcStatusUpdate {
status_update_serial,
..
} => Some(status_update_serial.to_u32()),
}
}
pub fn get_data2_str(&self) -> Option<&str> {
match self {
EventType::Info(msg)
| EventType::SmtpConnected(msg)
| EventType::ImapConnected(msg)
| EventType::SmtpMessageSent(msg)
| EventType::ImapMessageDeleted(msg)
| EventType::ImapMessageMoved(msg)
| EventType::NewBlobFile(msg)
| EventType::DeletedBlobFile(msg)
| EventType::Warning(msg)
| EventType::Error(msg)
| EventType::ErrorSelfNotInGroup(msg) => Some(msg),
EventType::MsgsChanged { .. }
| EventType::ReactionsChanged { .. }
| EventType::IncomingMsg { .. }
| EventType::MsgsNoticed(_)
| EventType::MsgDelivered { .. }
| EventType::MsgFailed { .. }
| EventType::MsgRead { .. }
| EventType::ChatModified(_)
| EventType::ContactsChanged(_)
| EventType::LocationChanged(_)
| EventType::ImexProgress(_)
| EventType::SecurejoinInviterProgress { .. }
| EventType::SecurejoinJoinerProgress { .. }
| EventType::ConnectivityChanged
| EventType::SelfavatarChanged
| EventType::WebxdcStatusUpdate { .. }
| EventType::WebxdcInstanceDeleted { .. }
| EventType::ChatEphemeralTimerModified { .. } => None,
EventType::ConfigureProgress { comment, .. } => {
if let Some(comment) = comment {
Some(comment)
} else {
None
}
}
EventType::ImexFileWritten(file) => file.to_str(),
EventType::IncomingMsgBunch { .. } => {
//serde_json::to_string(msg_ids).ok().map(|str| str.as_str())
Some("fix me!!")
}
}
}
pub fn to_json(&self, timestamp: Option<i64>) -> Value {
let mut tree: serde_json::Map<String, Value> = serde_json::Map::new();
tree.insert("event_type".to_string(), Value::String(self.to_string()));
let data1 = Value::Number(self.get_data1_int().into());
let data2 = if let Some(number) = self.get_data2_int() {
Value::Number(number.into())
} else if let Some(string) = self.get_data2_str() {
Value::String(string.to_string())
} else {
Value::Null
};
tree.insert("data1".to_string(), data1);
tree.insert("data2".to_string(), data2);
if let Some(ts) = timestamp {
tree.insert("ts".to_string(), Value::Number(ts.into()));
}
Value::Object(tree)
}
}

View File

@@ -2,6 +2,7 @@
use std::collections::BTreeSet;
use std::path::{Path, PathBuf};
use std::sync::atomic;
use anyhow::{ensure, format_err, Context as _, Result};
use deltachat_derive::{FromSql, ToSql};
@@ -1281,13 +1282,26 @@ pub async fn delete_msgs(context: &Context, msg_ids: &[MsgId]) -> Result<()> {
paramsv![msg.rfc724_mid],
)
.await?;
if context.get_config(Config::DebugLogging).await? == Some(msg_id.to_u32().to_string()) {
context
.sql
.set_raw_config(Config::DebugLogging.as_ref(), None)
.await?;
context.debug_logging.store(0, atomic::Ordering::Relaxed);
}
}
if !msg_ids.is_empty() {
context.emit_msgs_changed_without_ids();
// Run housekeeping to delete unused blobs.
context.set_config(Config::LastHousekeeping, None).await?;
// We need to use set_raw_config() here since with set_config() it
// wouldn't compile ("recursion in an `async fn`")
context
.sql
.set_raw_config(Config::LastHousekeeping.as_ref(), None)
.await?;
}
// Interrupt Inbox loop to start message deletion and run housekeeping.

View File

@@ -4,6 +4,7 @@ use std::collections::{HashMap, HashSet};
use std::convert::TryFrom;
use std::path::Path;
use std::path::PathBuf;
use std::sync::atomic;
use std::time::Duration;
use anyhow::{bail, Context as _, Result};
@@ -341,6 +342,14 @@ impl Sql {
} else {
info!(context, "Opened database {:?}.", self.dbfile);
*self.is_encrypted.write().await = Some(passphrase_nonempty);
let debug_logging = self
.get_raw_config_u32(Config::DebugLogging.as_ref())
.await?;
context
.debug_logging
.store(debug_logging.unwrap_or(0), atomic::Ordering::Relaxed);
Ok(())
}
}
@@ -592,6 +601,12 @@ impl Sql {
.map(|s| s.and_then(|s| s.parse().ok()))
}
pub async fn get_raw_config_u32(&self, key: &str) -> Result<Option<u32>> {
self.get_raw_config(key)
.await
.map(|s| s.and_then(|s| s.parse().ok()))
}
pub async fn get_raw_config_bool(&self, key: &str) -> Result<bool> {
// Not the most obvious way to encode bool as string, but it is matter
// of backward compatibility.

View File

@@ -118,16 +118,16 @@ struct StatusUpdates {
/// Update items as sent on the wire and as stored in the database.
#[derive(Debug, Serialize, Deserialize)]
pub(crate) struct StatusUpdateItem {
payload: Value,
pub(crate) payload: Value,
#[serde(skip_serializing_if = "Option::is_none")]
info: Option<String>,
pub(crate) info: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
document: Option<String>,
pub(crate) document: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
summary: Option<String>,
pub(crate) summary: Option<String>,
}
/// Update items as passed to the UIs.
@@ -323,16 +323,10 @@ impl Context {
self.emit_msgs_changed(instance.chat_id, instance.id);
}
let rowid = self
.sql
.insert(
"INSERT INTO msgs_status_updates (msg_id, update_item) VALUES(?, ?);",
paramsv![instance.id, serde_json::to_string(&status_update_item)?],
)
let status_update_serial = self
.write_status_update_inner(&instance.id, status_update_item)
.await?;
let status_update_serial = StatusUpdateSerial(u32::try_from(rowid)?);
if instance.viewtype == Viewtype::Webxdc {
self.emit_event(EventType::WebxdcStatusUpdate {
msg_id: instance.id,
@@ -343,6 +337,22 @@ impl Context {
Ok(status_update_serial)
}
pub(crate) async fn write_status_update_inner(
&self,
instance_id: &MsgId,
status_update_item: StatusUpdateItem,
) -> Result<StatusUpdateSerial> {
let rowid = self
.sql
.insert(
"INSERT INTO msgs_status_updates (msg_id, update_item) VALUES(?, ?);",
paramsv![instance_id, serde_json::to_string(&status_update_item)?],
)
.await?;
let status_update_serial = StatusUpdateSerial(u32::try_from(rowid)?);
Ok(status_update_serial)
}
/// Sends a status update for an webxdc instance.
///
/// If the instance is a draft,