JSON-RPC: retrieve events via long polling

This way is more compatible to JSON-RPC libraries
that do not support receiving notifications from the server
and allows describing event types in the OpenRPC specification.

Event thread converting events to notifications in the FFI
is removed, so it is now possible to construct a dc_jsonrpc_instance_t
while still retrieving events via dc_event_emitter_t.
This commit is contained in:
link2xt
2023-04-20 10:03:13 +00:00
parent e7aab5c67c
commit 514074de8b
9 changed files with 120 additions and 142 deletions

View File

@@ -7,7 +7,6 @@ use std::sync::Arc;
use anyhow::{anyhow, Context as _, Result};
use deltachat::constants::DC_VERSION_STR;
use deltachat_jsonrpc::api::events::event_to_json_rpc_notification;
use deltachat_jsonrpc::api::{Accounts, CommandApi};
use futures_lite::stream::StreamExt;
use tokio::io::{self, AsyncBufReadExt, BufReader};
@@ -58,7 +57,6 @@ async fn main_impl() -> Result<()> {
let path = std::env::var("DC_ACCOUNTS_PATH").unwrap_or_else(|_| "accounts".to_string());
log::info!("Starting with accounts directory `{}`.", path);
let accounts = Accounts::new(PathBuf::from(&path)).await?;
let events = accounts.get_event_emitter();
log::info!("Creating JSON-RPC API.");
let accounts = Arc::new(RwLock::new(accounts));
@@ -68,21 +66,6 @@ async fn main_impl() -> Result<()> {
let session = RpcSession::new(client.clone(), state.clone());
let main_cancel = CancellationToken::new();
// Events task converts core events to JSON-RPC notifications.
let cancel = main_cancel.clone();
let events_task: JoinHandle<Result<()>> = tokio::spawn(async move {
let _cancel_guard = cancel.clone().drop_guard();
let mut r = Ok(());
while let Some(event) = events.recv().await {
if r.is_err() {
continue;
}
let event = event_to_json_rpc_notification(event);
r = client.send_notification("event", Some(event)).await;
}
Ok(())
});
// Send task prints JSON responses to stdout.
let cancel = main_cancel.clone();
let send_task: JoinHandle<anyhow::Result<()>> = tokio::spawn(async move {
@@ -148,16 +131,13 @@ async fn main_impl() -> Result<()> {
Ok(())
});
// See "Thread safety" section in deltachat-ffi/deltachat.h for explanation.
// NB: Events are drained by events_task.
main_cancel.cancelled().await;
accounts.read().await.stop_io().await;
drop(accounts);
drop(state);
let (r0, r1, r2, r3) = tokio::join!(events_task, send_task, sigterm_task, recv_task);
for r in [r0, r1, r2, r3] {
r??;
}
send_task.await??;
sigterm_task.await??;
recv_task.await??;
Ok(())
}