fix(service): Switch from flume to postage to fix out-of-order communication

This commit is contained in:
Michael Aaron Murphy 2021-08-17 12:44:41 +02:00
parent 490c6a6e8b
commit 8b4fbf441f
12 changed files with 156 additions and 208 deletions

View file

@ -1,5 +1,7 @@
use futures_lite::*;
use pop_launcher::*;
use postage::mpsc;
use postage::prelude::{Sink, Stream};
use smol::process::{ChildStdout, Command, Stdio};
use std::borrow::Cow;
use std::cell::Cell;
@ -13,10 +15,10 @@ enum Event {
}
pub async fn main() {
let (event_tx, event_rx) = flume::unbounded::<Event>();
let (mut event_tx, mut event_rx) = mpsc::channel::<Event>(8);
// Channel for cancelling searches that are in progress.
let (interrupt_tx, interrupt_rx) = flume::bounded::<()>(0);
let (interrupt_tx, interrupt_rx) = mpsc::channel::<()>(1);
// Indicates if a search is being performed in the background.
let active = Rc::new(Cell::new(false));
@ -30,7 +32,7 @@ pub async fn main() {
// Manages the external process, tracks search results, and executes activate requests
let search_handler = async move {
while let Ok(search) = event_rx.recv_async().await {
while let Some(search) = event_rx.recv().await {
match search {
Event::Activate(id) => {
if let Some(selection) = app.search_results.get(id as usize) {
@ -52,10 +54,14 @@ pub async fn main() {
// Forwards requests to the search handler, and performs an interrupt as necessary.
let request_handler = async move {
let interrupt = || async {
if active.get() && !interrupt_tx.is_full() {
tracing::debug!("sending interrupt");
let _ = interrupt_tx.send_async(()).await;
let interrupt = || {
let active = active.clone();
let mut tx = interrupt_tx.clone();
async move {
if active.get() {
tracing::debug!("sending interrupt");
let _ = tx.try_send(());
}
}
};
@ -66,7 +72,7 @@ pub async fn main() {
Ok(request) => match request {
// Launch the default application with the selected file
Request::Activate(id) => {
event_tx.send_async(Event::Activate(id)).await?;
event_tx.send(Event::Activate(id)).await?;
}
// Interrupt any active searches being performed
@ -81,7 +87,7 @@ pub async fn main() {
None => &query,
};
event_tx.send_async(Event::Search(query.to_owned())).await?;
event_tx.send(Event::Search(query.to_owned())).await?;
active.set(true);
}
@ -94,7 +100,7 @@ pub async fn main() {
}
}
Ok::<(), flume::SendError<Event>>(())
Ok::<(), postage::sink::SendError<Event>>(())
};
let _ = future::zip(request_handler, search_handler).await;
@ -103,7 +109,7 @@ pub async fn main() {
/// Maintains state for search requests
struct SearchContext {
pub active: Rc<Cell<bool>>,
pub interrupt_rx: flume::Receiver<()>,
pub interrupt_rx: mpsc::Receiver<()>,
pub out: smol::Unblock<io::Stdout>,
pub search_results: Vec<PathBuf>,
}
@ -157,7 +163,7 @@ impl SearchContext {
'stream: loop {
let interrupt = async {
let _ = self.interrupt_rx.recv_async().await;
let _ = self.interrupt_rx.recv().await;
None
};

View file

@ -1,8 +1,9 @@
use crate::*;
use pop_launcher::*;
use flume::Sender;
use futures_lite::{AsyncBufReadExt, StreamExt};
use postage::mpsc::Sender;
use postage::prelude::*;
use std::collections::VecDeque;
use std::os::unix::process::CommandExt;
use std::{
@ -73,7 +74,7 @@ impl App {
}
async fn reload(&mut self) {
let (tx, rx) = flume::unbounded::<ScriptInfo>();
let (tx, mut rx) = postage::mpsc::channel::<ScriptInfo>(8);
let mut queue = VecDeque::new();
@ -92,7 +93,7 @@ impl App {
};
let script_receiver = async {
while let Ok(script) = rx.recv_async().await {
while let Some(script) = rx.recv().await {
tracing::debug!("appending script: {:?}", script);
self.scripts.push(script);
}
@ -148,7 +149,7 @@ struct ScriptInfo {
async fn load_from(path: &Path, paths: &mut VecDeque<PathBuf>, tx: Sender<ScriptInfo>) {
if let Ok(directory) = path.read_dir() {
for entry in directory.filter_map(Result::ok) {
let tx = tx.clone();
let mut tx = tx.clone();
let path = entry.path();
if path.is_dir() {
@ -199,7 +200,7 @@ async fn load_from(path: &Path, paths: &mut VecDeque<PathBuf>, tx: Sender<Script
}
}
let _ = tx.send_async(info).await;
let _ = tx.send(info).await;
})
.detach();
}

View file

@ -35,6 +35,10 @@
matches: ["dev"],
queries: [(name: "DEV Community", query: "dev.to/search?q=")],
),
(
matches: ["docs"],
queries: [(name: "Docs.rs", query: "docs.rs/")]
)
(
matches: ["fh"],
queries: [(name: "Flathub", query: "flathub.org/apps/search/")]

View file

@ -20,9 +20,7 @@ pub async fn main() {
Request::Exit => break,
_ => (),
},
Err(why) => {
tracing::error!("malformed JSON input: {}", why)
}
Err(why) => tracing::error!("malformed JSON input: {}", why),
}
}
}