refactor: asyncify stop and exit for Tui
This commit is contained in:
parent
764cddee0e
commit
21de453415
2 changed files with 37 additions and 19 deletions
|
@ -154,12 +154,12 @@ impl App {
|
||||||
action_tx.send(Action::ClearScreen)?;
|
action_tx.send(Action::ClearScreen)?;
|
||||||
block_in_place(|| tui.enter())?;
|
block_in_place(|| tui.enter())?;
|
||||||
} else if self.should_quit {
|
} else if self.should_quit {
|
||||||
block_in_place(|| tui.stop())?;
|
tui.stop().await?;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
block_in_place(|| tui.exit())
|
tui.exit().await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_events(&mut self, tui: &mut Tui) -> Result<()> {
|
async fn handle_events(&mut self, tui: &mut Tui) -> Result<()> {
|
||||||
|
|
|
@ -15,18 +15,19 @@ use crossterm::{
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use status::TuiStatus;
|
use status::TuiStatus;
|
||||||
use tokio::{
|
use tokio::{
|
||||||
|
runtime::Handle,
|
||||||
sync::{
|
sync::{
|
||||||
mpsc::{self, UnboundedReceiver, UnboundedSender},
|
mpsc::{self, UnboundedReceiver, UnboundedSender},
|
||||||
Mutex, RwLock,
|
Mutex, RwLock,
|
||||||
},
|
},
|
||||||
task::JoinHandle,
|
task::{block_in_place, JoinHandle},
|
||||||
time::interval,
|
time::{interval, sleep, timeout},
|
||||||
};
|
};
|
||||||
use tokio_util::sync::CancellationToken;
|
use tokio_util::sync::CancellationToken;
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
||||||
pub(crate) mod status;
|
|
||||||
pub(crate) mod backend;
|
pub(crate) mod backend;
|
||||||
|
pub(crate) mod status;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub enum Event {
|
pub enum Event {
|
||||||
|
@ -148,20 +149,30 @@ impl Tui {
|
||||||
cancellation_token.cancel();
|
cancellation_token.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stop(&self) -> Result<()> {
|
async fn await_shutdown(&self) {
|
||||||
self.cancel();
|
|
||||||
let mut counter = 0;
|
|
||||||
while !self.task.is_finished() {
|
while !self.task.is_finished() {
|
||||||
std::thread::sleep(Duration::from_millis(1));
|
sleep(Duration::from_millis(1)).await;
|
||||||
counter += 1;
|
}
|
||||||
if counter > 50 {
|
}
|
||||||
|
|
||||||
|
pub async fn stop(&self) -> Result<()> {
|
||||||
|
self.cancel();
|
||||||
|
|
||||||
|
let attempt_timeout = Duration::from_millis(50);
|
||||||
|
let abort_shutdown = async {
|
||||||
|
while !self.task.is_finished() {
|
||||||
self.task.abort();
|
self.task.abort();
|
||||||
}
|
}
|
||||||
if counter > 100 {
|
};
|
||||||
error!("Failed to abort task in 100 milliseconds for unknown reason");
|
|
||||||
break;
|
if let Err(_) = timeout(attempt_timeout, self.await_shutdown()).await {
|
||||||
}
|
timeout(attempt_timeout, abort_shutdown)
|
||||||
|
.await
|
||||||
|
.inspect_err(|_| {
|
||||||
|
error!("Failed to abort task in 100 milliseconds for unknown reason")
|
||||||
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,8 +195,8 @@ impl Tui {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exit(&mut self) -> Result<()> {
|
pub async fn exit(&mut self) -> Result<()> {
|
||||||
self.stop()?;
|
self.stop().await?;
|
||||||
// TODO: enable raw mode for pty
|
// TODO: enable raw mode for pty
|
||||||
if true || crossterm::terminal::is_raw_mode_enabled()? {
|
if true || crossterm::terminal::is_raw_mode_enabled()? {
|
||||||
let mut term = self.terminal.try_lock()?;
|
let mut term = self.terminal.try_lock()?;
|
||||||
|
@ -211,7 +222,7 @@ impl Tui {
|
||||||
|
|
||||||
pub async fn suspend(&mut self) -> Result<Arc<CancellationToken>> {
|
pub async fn suspend(&mut self) -> Result<Arc<CancellationToken>> {
|
||||||
// Exit the current Tui
|
// Exit the current Tui
|
||||||
tokio::task::block_in_place(|| self.exit())?;
|
self.exit().await?;
|
||||||
|
|
||||||
// Update the status and initialize a cancellation token
|
// Update the status and initialize a cancellation token
|
||||||
let token = Arc::new(CancellationToken::new());
|
let token = Arc::new(CancellationToken::new());
|
||||||
|
@ -244,6 +255,13 @@ impl Tui {
|
||||||
|
|
||||||
impl Drop for Tui {
|
impl Drop for Tui {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let _ = self.exit().inspect_err(|err| error!("Failed to exit Tui: {err}"));
|
block_in_place(|| {
|
||||||
|
let handle = Handle::current();
|
||||||
|
let _ = handle.block_on(async {
|
||||||
|
self.exit()
|
||||||
|
.await
|
||||||
|
.inspect_err(|err| error!("Failed to exit Tui: {err}"))
|
||||||
|
});
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue