refactor: docker functions

This commit is contained in:
Jack Wills
2022-04-29 17:03:34 +00:00
parent 679203cf2d
commit 28bf0e603d
4 changed files with 60 additions and 75 deletions
+52 -66
View File
@@ -183,8 +183,7 @@ impl DockerData {
} }
/// Update all logs, spawn each container into own tokio::spawn thread /// Update all logs, spawn each container into own tokio::spawn thread
// rename init all logs, as only gets run once async fn init_all_logs(&mut self, all_ids: &[(bool, String)]) {
async fn update_all_logs(&mut self, all_ids: &[(bool, String)]) {
let mut handles = vec![]; let mut handles = vec![];
for (_, id) in all_ids.iter() { for (_, id) in all_ids.iter() {
@@ -212,7 +211,9 @@ impl DockerData {
self.update_all_container_stats(&all_ids).await; self.update_all_container_stats(&all_ids).await;
} }
async fn loading_spin(gui_state: Arc<Mutex<GuiState>>) -> JoinHandle<()> { /// Animate the loading icon
async fn loading_spin(&mut self ) -> JoinHandle<()> {
let gui_state = Arc::clone(&self.gui_state);
tokio::spawn(async move { tokio::spawn(async move {
loop { loop {
tokio::time::sleep(std::time::Duration::from_millis(100)).await; tokio::time::sleep(std::time::Duration::from_millis(100)).await;
@@ -221,20 +222,22 @@ impl DockerData {
}) })
} }
fn stop_loading_spin(handle: JoinHandle<()>, gui_state: &Arc<Mutex<GuiState>>) { /// Stop the loading_spin fn, and reset gui loading status
fn stop_loading_spin(&mut self, handle: JoinHandle<()>) {
handle.abort(); handle.abort();
gui_state.lock().reset_loading(); self.gui_state.lock().reset_loading();
} }
// Initialize docker container data, before any messages are received
async fn initialise_container_data(&mut self) { async fn initialise_container_data(&mut self) {
let gui_state = Arc::clone(&self.gui_state); let loading_spin = self.loading_spin().await;
let loading_spin = Self::loading_spin(gui_state).await;
let all_ids = self.update_all_containers().await; let all_ids = self.update_all_containers().await;
self.update_all_container_stats(&all_ids).await; self.update_all_container_stats(&all_ids).await;
// Maybe only do a single one at first? // Maybe only do a single one at first?
self.update_all_logs(&all_ids).await; self.init_all_logs(&all_ids).await;
if all_ids.is_empty() { if all_ids.is_empty() {
self.initialised = true; self.initialised = true;
@@ -246,7 +249,7 @@ impl DockerData {
self.initialised = self.app_data.lock().initialised(&all_ids); self.initialised = self.app_data.lock().initialised(&all_ids);
} }
self.app_data.lock().init = true; self.app_data.lock().init = true;
Self::stop_loading_spin(loading_spin, &self.gui_state); self.stop_loading_spin(loading_spin);
} }
/// Handle incoming messages, container controls & all container information update /// Handle incoming messages, container controls & all container information update
@@ -254,80 +257,65 @@ impl DockerData {
while let Some(message) = self.receiver.recv().await { while let Some(message) = self.receiver.recv().await {
let docker = Arc::clone(&self.docker); let docker = Arc::clone(&self.docker);
let app_data = Arc::clone(&self.app_data); let app_data = Arc::clone(&self.app_data);
let gui_state = Arc::clone(&self.gui_state);
match message { match message {
DockerMessage::Pause(id) => { DockerMessage::Pause(id) => {
let spin_gui = Arc::clone(&gui_state); let loading_spin =self.loading_spin().await;
let loading_spin = Self::loading_spin(gui_state).await; docker.pause_container(&id).await.unwrap_or_else(|_| {
tokio::spawn(async move { app_data
docker.pause_container(&id).await.unwrap_or_else(|_| { .lock()
app_data .set_error(AppError::DockerCommand(DockerControls::Pause))
.lock()
.set_error(AppError::DockerCommand(DockerControls::Pause))
});
Self::stop_loading_spin(loading_spin, &spin_gui);
}); });
self.stop_loading_spin(loading_spin);
} }
DockerMessage::Restart(id) => { DockerMessage::Restart(id) => {
let spin_gui = Arc::clone(&gui_state); let loading_spin =self.loading_spin().await;
let loading_spin = Self::loading_spin(gui_state).await; docker
tokio::spawn(async move { .restart_container(&id, None)
docker .await
.restart_container(&id, None) .unwrap_or_else(|_| {
.await app_data
.unwrap_or_else(|_| { .lock()
app_data .set_error(AppError::DockerCommand(DockerControls::Restart))
.lock() });
.set_error(AppError::DockerCommand(DockerControls::Restart)) self.stop_loading_spin(loading_spin);
});
Self::stop_loading_spin(loading_spin, &spin_gui);
});
} }
DockerMessage::Start(id) => { DockerMessage::Start(id) => {
let spin_gui = Arc::clone(&gui_state); let loading_spin =self.loading_spin().await;
let loading_spin = Self::loading_spin(gui_state).await; docker
tokio::spawn(async move { .start_container(&id, None::<StartContainerOptions<String>>)
docker .await
.start_container(&id, None::<StartContainerOptions<String>>) .unwrap_or_else(|_| {
.await app_data
.unwrap_or_else(|_| { .lock()
app_data .set_error(AppError::DockerCommand(DockerControls::Start))
.lock() });
.set_error(AppError::DockerCommand(DockerControls::Start)) self.stop_loading_spin(loading_spin);
});
Self::stop_loading_spin(loading_spin, &spin_gui);
});
} }
DockerMessage::Stop(id) => { DockerMessage::Stop(id) => {
let spin_gui = Arc::clone(&gui_state); let loading_spin =self.loading_spin().await;
let loading_spin = Self::loading_spin(gui_state).await; docker.stop_container(&id, None).await.unwrap_or_else(|_| {
tokio::spawn(async move { app_data
docker.stop_container(&id, None).await.unwrap_or_else(|_| { .lock()
app_data .set_error(AppError::DockerCommand(DockerControls::Stop))
.lock()
.set_error(AppError::DockerCommand(DockerControls::Stop))
});
Self::stop_loading_spin(loading_spin, &spin_gui);
}); });
self.stop_loading_spin(loading_spin);
} }
DockerMessage::Unpause(id) => { DockerMessage::Unpause(id) => {
let spin_gui = Arc::clone(&gui_state); let loading_spin =self.loading_spin().await;
let loading_spin = Self::loading_spin(gui_state).await; docker.unpause_container(&id).await.unwrap_or_else(|_| {
tokio::spawn(async move { app_data
docker.unpause_container(&id).await.unwrap_or_else(|_| { .lock()
app_data .set_error(AppError::DockerCommand(DockerControls::Unpause))
.lock()
.set_error(AppError::DockerCommand(DockerControls::Unpause))
});
Self::stop_loading_spin(loading_spin, &spin_gui);
}); });
self.stop_loading_spin(loading_spin);
self.update_everything().await
} }
DockerMessage::Update => self.update_everything().await, DockerMessage::Update => self.update_everything().await,
} }
} }
} }
/// Initialise self, and start the updated loop /// Initialise self, and start the message receiving loop
pub async fn init( pub async fn init(
args: CliArgs, args: CliArgs,
app_data: Arc<Mutex<AppData>>, app_data: Arc<Mutex<AppData>>,
@@ -346,8 +334,6 @@ impl DockerData {
}; };
inner.initialise_container_data().await; inner.initialise_container_data().await;
// todo!(" change this to recv.next()");
// inner.update_loop().await;
inner.message_handler().await; inner.message_handler().await;
} }
} }
+2 -2
View File
@@ -223,7 +223,7 @@ pub fn draw_logs<B: Backend>(
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
gui_state: &Arc<Mutex<GuiState>>, gui_state: &Arc<Mutex<GuiState>>,
index: Option<usize>, index: Option<usize>,
loading_icon: String, loading_icon: String,
selected_panel: &SelectablePanel, selected_panel: &SelectablePanel,
) { ) {
let panel = SelectablePanel::Logs; let panel = SelectablePanel::Logs;
@@ -368,7 +368,7 @@ pub fn draw_heading_bar<B: Backend>(
columns: &Columns, columns: &Columns,
f: &mut Frame<'_, B>, f: &mut Frame<'_, B>,
has_containers: bool, has_containers: bool,
loading_icon: String, loading_icon: String,
info_visible: bool, info_visible: bool,
) { ) {
let block = || Block::default().style(Style::default().bg(Color::Magenta).fg(Color::Black)); let block = || Block::default().style(Style::default().bg(Color::Magenta).fg(Color::Black));
+2 -2
View File
@@ -167,8 +167,8 @@ pub struct GuiState {
// If a BMapTree think it would mean have to implement ordering for SelectablePanel // If a BMapTree think it would mean have to implement ordering for SelectablePanel
area_map: HashMap<SelectablePanel, Rect>, area_map: HashMap<SelectablePanel, Rect>,
loading_icon: Loading, loading_icon: Loading,
// Should be a vec, each time loading add a new to the vec, and reset remove from vec // Should be a vec, each time loading add a new to the vec, and reset remove from vec
// for for if is_loading just check if vec is empty or not // for for if is_loading just check if vec is empty or not
is_loading: bool, is_loading: bool,
pub selected_panel: SelectablePanel, pub selected_panel: SelectablePanel,
pub show_help: bool, pub show_help: bool,
+4 -5
View File
@@ -14,7 +14,6 @@ use std::{
time::{Duration, Instant}, time::{Duration, Instant},
}; };
use tokio::sync::mpsc::Sender; use tokio::sync::mpsc::Sender;
use tracing::error;
use tui::{ use tui::{
backend::{Backend, CrosstermBackend}, backend::{Backend, CrosstermBackend},
layout::{Constraint, Direction, Layout}, layout::{Constraint, Direction, Layout},
@@ -68,7 +67,7 @@ pub async fn create_ui(
terminal.show_cursor().unwrap(); terminal.show_cursor().unwrap();
if let Err(err) = res { if let Err(err) = res {
error!(%err); println!("{}", err);
} }
Ok(()) Ok(())
} }
@@ -157,7 +156,7 @@ fn ui<B: Backend>(
let selected_panel = gui_state.lock().selected_panel; let selected_panel = gui_state.lock().selected_panel;
let show_help = gui_state.lock().show_help; let show_help = gui_state.lock().show_help;
let info_text = gui_state.lock().info_box_text.clone(); let info_text = gui_state.lock().info_box_text.clone();
let loading_icon = gui_state.lock().get_loading(); let loading_icon = gui_state.lock().get_loading();
let whole_layout = Layout::default() let whole_layout = Layout::default()
.direction(Direction::Vertical) .direction(Direction::Vertical)
@@ -219,7 +218,7 @@ fn ui<B: Backend>(
f, f,
gui_state, gui_state,
log_index, log_index,
loading_icon.to_owned(), loading_icon.to_owned(),
&selected_panel, &selected_panel,
); );
@@ -228,7 +227,7 @@ fn ui<B: Backend>(
&column_widths, &column_widths,
f, f,
has_containers, has_containers,
loading_icon, loading_icon,
show_help, show_help,
); );