mirror of
https://gitlab.com/schmiddi-on-mobile/flare.git
synced 2026-10-29 06:57:46 -04:00
Merge branch 'backend-localset' into 'master'
Partial fix for messages loading a long time if backend busy See merge request schmiddi-on-mobile/flare!184
This commit is contained in:
commit
f0ca0ae9bd
1 file changed
+125
-86
+125
-86
@@ -9,6 +9,7 @@
|
||||
//! to those of [presage::Manager]. The other way is with a separate channel which has to be given to [ManagerThread]
|
||||
//! when it is constructed.
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::{cell::OnceCell, ops::Bound};
|
||||
|
||||
use futures::channel::{mpsc, oneshot};
|
||||
@@ -32,6 +33,7 @@ use presage::{
|
||||
store::{ContentsStore, Thread},
|
||||
};
|
||||
use presage_store_sqlite::SqliteStore as Store;
|
||||
use tokio::sync::RwLock;
|
||||
use url::Url;
|
||||
|
||||
use crate::ApplicationError;
|
||||
@@ -181,10 +183,10 @@ impl ManagerThread {
|
||||
// XXX: Make sure the initial sync is finished (requires upstream presage changes).
|
||||
// See https://github.com/whisperfish/presage/pull/212.
|
||||
let manager_receive = setup_manager(config_store, setup_callback).await;
|
||||
if let Ok(mut manager_receive) = manager_receive {
|
||||
if let Ok(manager_receive) = manager_receive {
|
||||
log::trace!("Starting command loop");
|
||||
drop(error_callback);
|
||||
command_loop(&mut manager_receive, receiver, content, error).await;
|
||||
command_loop(manager_receive, receiver, content, error).await;
|
||||
} else {
|
||||
let e = manager_receive.err().unwrap();
|
||||
log::trace!("Got error: {}", e);
|
||||
@@ -568,117 +570,146 @@ async fn setup_manager(
|
||||
|
||||
/// The command loop where messages are received and commands from the UI thread are executed.
|
||||
async fn command_loop(
|
||||
manager: &mut Manager<Store, Registered>,
|
||||
manager: Manager<Store, Registered>,
|
||||
mut receiver: mpsc::Receiver<Command>,
|
||||
mut content: mpsc::UnboundedSender<Content>,
|
||||
mut error: mpsc::Sender<ApplicationError>,
|
||||
) {
|
||||
'outer: loop {
|
||||
let msgs: Result<_, presage::Error<<Store as presage::store::Store>::Error>> =
|
||||
manager.receive_messages().await;
|
||||
let manager = Arc::new(RwLock::new(manager));
|
||||
let local = tokio::task::LocalSet::new();
|
||||
local.run_until(async move {
|
||||
'outer: loop {
|
||||
let msgs: Result<_, presage::Error<<Store as presage::store::Store>::Error>> = manager
|
||||
.write()
|
||||
.await
|
||||
.receive_messages()
|
||||
.await;
|
||||
|
||||
let (need_loop_restart_sender, mut need_loop_restart_receiver) = mpsc::unbounded();
|
||||
let network_monitor = gio::NetworkMonitor::default();
|
||||
network_monitor.connect_network_available_notify(clone!(
|
||||
#[strong]
|
||||
need_loop_restart_sender,
|
||||
move |m| {
|
||||
if m.is_network_available() {
|
||||
let _ = need_loop_restart_sender.unbounded_send(());
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
match msgs {
|
||||
Ok(messages) => {
|
||||
futures::pin_mut!(messages);
|
||||
let mut next_msg = messages.next().fuse();
|
||||
loop {
|
||||
select! {
|
||||
// Receiving a message.
|
||||
msg = next_msg => {
|
||||
if let Some(msg) = msg {
|
||||
if let Received::Content(msg) = msg &&
|
||||
content.send(*msg).await.is_err() {
|
||||
log::info!("Failed to send message to `Manager`, exiting");
|
||||
break 'outer;
|
||||
}
|
||||
} else {
|
||||
log::error!("Message stream finished. Restarting command loop.");
|
||||
break;
|
||||
}
|
||||
next_msg = messages.next().fuse();
|
||||
},
|
||||
// Receiving a command.
|
||||
cmd = receiver.next() => {
|
||||
if let Some(cmd) = cmd {
|
||||
handle_command(manager, cmd).await;
|
||||
}
|
||||
},
|
||||
// The network status changed; restart the loop to restart the signal websockets.
|
||||
_ = need_loop_restart_receiver.next() => {
|
||||
log::trace!("Network changed. Restarting command loop.");
|
||||
break;
|
||||
},
|
||||
complete => {
|
||||
log::trace!("Command loop complete. Restarting command loop.");
|
||||
break
|
||||
},
|
||||
let (need_loop_restart_sender, mut need_loop_restart_receiver) = mpsc::unbounded();
|
||||
let network_monitor = gio::NetworkMonitor::default();
|
||||
network_monitor.connect_network_available_notify(clone!(
|
||||
#[strong]
|
||||
need_loop_restart_sender,
|
||||
move |m| {
|
||||
if m.is_network_available() {
|
||||
let _ = need_loop_restart_sender.unbounded_send(());
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Got error receiving: {}, {:?}", e, e);
|
||||
let e = e.into();
|
||||
// Don't send no-internet errors, Flare is able to handle them automatically.
|
||||
if !matches!(e, ApplicationError::NoInternet) {
|
||||
error.send(e).await.expect("Callback sending failed");
|
||||
}
|
||||
));
|
||||
|
||||
// Handle all commands while sleeping; this ensures Flare can start up without internet.
|
||||
loop {
|
||||
select! {
|
||||
cmd = receiver.next().fuse() => {
|
||||
if let Some(cmd) = cmd {
|
||||
handle_command(manager, cmd).await;
|
||||
match msgs {
|
||||
Ok(messages) => {
|
||||
futures::pin_mut!(messages);
|
||||
let mut next_msg = messages.next().fuse();
|
||||
loop {
|
||||
select! {
|
||||
// Receiving a message.
|
||||
msg = next_msg => {
|
||||
if let Some(msg) = msg {
|
||||
if let Received::Content(msg) = msg &&
|
||||
content.send(*msg).await.is_err() {
|
||||
log::info!("Failed to send message to `Manager`, exiting");
|
||||
break 'outer;
|
||||
}
|
||||
} else {
|
||||
log::error!("Message stream finished. Restarting command loop.");
|
||||
break;
|
||||
}
|
||||
next_msg = messages.next().fuse();
|
||||
},
|
||||
// Receiving a command.
|
||||
cmd = receiver.next() => {
|
||||
if let Some(cmd) = cmd {
|
||||
tokio::task::spawn_local(handle_command(manager.clone(), cmd));
|
||||
}
|
||||
},
|
||||
// The network status changed; restart the loop to restart the signal websockets.
|
||||
_ = need_loop_restart_receiver.next() => {
|
||||
log::trace!("Network changed. Restarting command loop.");
|
||||
break;
|
||||
},
|
||||
complete => {
|
||||
log::trace!("Command loop complete. Restarting command loop.");
|
||||
break
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Got error receiving: {}, {:?}", e, e);
|
||||
let e = e.into();
|
||||
// Don't send no-internet errors, Flare is able to handle them automatically.
|
||||
if !matches!(e, ApplicationError::NoInternet) {
|
||||
error.send(e).await.expect("Callback sending failed");
|
||||
}
|
||||
|
||||
// Handle all commands while sleeping; this ensures Flare can start up without internet.
|
||||
loop {
|
||||
select! {
|
||||
cmd = receiver.next().fuse() => {
|
||||
if let Some(cmd) = cmd {
|
||||
tokio::task::spawn_local(handle_command(manager.clone(), cmd));
|
||||
}
|
||||
},
|
||||
_ = tokio::time::sleep(std::time::Duration::from_secs(OFFLINE_SLEEP_TIMEOUT)).fuse() => {
|
||||
break;
|
||||
}
|
||||
},
|
||||
_ = tokio::time::sleep(std::time::Duration::from_secs(OFFLINE_SLEEP_TIMEOUT)).fuse() => {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
log::debug!("Websocket closed, trying again");
|
||||
}
|
||||
log::debug!("Websocket closed, trying again");
|
||||
}
|
||||
log::info!("Exiting `ManagerThread::command_loop`");
|
||||
}).await;
|
||||
}
|
||||
|
||||
async fn handle_command(manager: &mut Manager<Store, Registered>, command: Command) {
|
||||
async fn handle_command(manager: Arc<RwLock<Manager<Store, Registered>>>, command: Command) {
|
||||
log::trace!("Got command: {:#?}", command);
|
||||
match command {
|
||||
// XXX: Uuid should not be used anymore.
|
||||
// XXX: Don't use nil.
|
||||
Command::Uuid(callback) => callback
|
||||
.send(manager.registration_data().service_ids.aci().into())
|
||||
.send(
|
||||
manager
|
||||
.read()
|
||||
.await
|
||||
.registration_data()
|
||||
.service_ids
|
||||
.aci()
|
||||
.into(),
|
||||
)
|
||||
.expect("Callback sending failed"),
|
||||
Command::SubmitRecaptchaChallenge(token, captcha, callback) => callback
|
||||
.send(manager.submit_recaptcha_challenge(&token, &captcha).await)
|
||||
.send(
|
||||
manager
|
||||
.read()
|
||||
.await
|
||||
.submit_recaptcha_challenge(&token, &captcha)
|
||||
.await,
|
||||
)
|
||||
.expect("Callback sending failed"),
|
||||
Command::RetrieveProfileByUuid(uuid, profile_key, callback) => callback
|
||||
.send(manager.retrieve_profile_by_uuid(uuid, profile_key).await)
|
||||
.send(
|
||||
manager
|
||||
.write()
|
||||
.await
|
||||
.retrieve_profile_by_uuid(uuid, profile_key)
|
||||
.await,
|
||||
)
|
||||
.expect("Callback sending failed"),
|
||||
Command::RetrieveProfile(callback) => callback
|
||||
.send(manager.retrieve_profile().await)
|
||||
.send(manager.write().await.retrieve_profile().await)
|
||||
.expect("Callback sending failed"),
|
||||
Command::GetGroupV2(master_key, callback) => callback
|
||||
.send(manager.store().group(master_key).await)
|
||||
.send(manager.read().await.store().group(master_key).await)
|
||||
.map_err(|_| ())
|
||||
.expect("Callback sending failed"),
|
||||
Command::SendSessionReset(recipient_address, timestamp, callback) => callback
|
||||
.send(
|
||||
manager
|
||||
.write()
|
||||
.await
|
||||
.send_session_reset(&recipient_address, timestamp)
|
||||
.await,
|
||||
)
|
||||
@@ -686,6 +717,8 @@ async fn handle_command(manager: &mut Manager<Store, Registered>, command: Comma
|
||||
Command::SendMessage(recipient_address, message, timestamp, callback) => callback
|
||||
.send(
|
||||
manager
|
||||
.write()
|
||||
.await
|
||||
.send_message(recipient_address, *message, timestamp)
|
||||
.await,
|
||||
)
|
||||
@@ -693,20 +726,24 @@ async fn handle_command(manager: &mut Manager<Store, Registered>, command: Comma
|
||||
Command::SendMessageToGroup(group_key, message, timestamp, callback) => callback
|
||||
.send(
|
||||
manager
|
||||
.write()
|
||||
.await
|
||||
.send_message_to_group(&group_key[..], *message, timestamp)
|
||||
.await,
|
||||
)
|
||||
.expect("Callback sending failed"),
|
||||
Command::GetAttachment(attachment, callback) => callback
|
||||
.send(manager.get_attachment(&attachment).await)
|
||||
.send(manager.read().await.get_attachment(&attachment).await)
|
||||
.expect("Callback sending failed"),
|
||||
Command::UploadAttachments(attachments, callback) => callback
|
||||
.send(manager.upload_attachments(attachments).await)
|
||||
.send(manager.read().await.upload_attachments(attachments).await)
|
||||
.expect("Callback sending failed"),
|
||||
Command::Messages(thread, range, callback) => {
|
||||
// XXX: Cannot format iterator.
|
||||
let _ = callback.send(
|
||||
manager
|
||||
.read()
|
||||
.await
|
||||
.store()
|
||||
.messages(&thread, range)
|
||||
.await
|
||||
@@ -714,29 +751,31 @@ async fn handle_command(manager: &mut Manager<Store, Registered>, command: Comma
|
||||
);
|
||||
}
|
||||
Command::RegistrationType(callback) => callback
|
||||
.send(manager.registration_type())
|
||||
.send(manager.read().await.registration_type())
|
||||
.expect("Callback sending failed"),
|
||||
Command::LinkSecondary(url, callback) => callback
|
||||
.send(manager.link_secondary(url).await)
|
||||
.send(manager.write().await.link_secondary(url).await)
|
||||
.expect("Callback sending failed"),
|
||||
Command::UnlinkSecondary(id, callback) => callback
|
||||
.send(manager.unlink_secondary(id).await)
|
||||
.send(manager.read().await.unlink_secondary(id).await)
|
||||
.expect("Callback sending failed"),
|
||||
Command::Devices(callback) => callback
|
||||
.send(manager.devices().await)
|
||||
.send(manager.read().await.devices().await)
|
||||
.expect("Callback sending failed"),
|
||||
Command::RequestContacts(callback) => callback
|
||||
.send(manager.request_contacts().await)
|
||||
.send(manager.write().await.request_contacts().await)
|
||||
.expect("Callback sending failed"),
|
||||
Command::RetrieveProfileAvatarByUuid(uuid, profile_key, callback) => callback
|
||||
.send(
|
||||
manager
|
||||
.write()
|
||||
.await
|
||||
.retrieve_profile_avatar_by_uuid(uuid, profile_key)
|
||||
.await,
|
||||
)
|
||||
.expect("Callback sending failed"),
|
||||
Command::RetrieveGroupAvatar(context, callback) => callback
|
||||
.send(manager.retrieve_group_avatar(context).await)
|
||||
.send(manager.write().await.retrieve_group_avatar(context).await)
|
||||
.expect("Callback sending failed"),
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user