Add refresh shortkey 'r' for on-demand metrics refresh
Implements ZMQ command protocol for dashboard-to-agent communication: - Agents listen on port 6131 for REQ/REP commands - Dashboard sends "refresh" command when 'r' key is pressed - Agents force immediate collection of all metrics via force_refresh_all() - Fresh data is broadcast immediately to dashboard - Updated help text to show "r: Refresh all metrics" Also includes metric-level caching architecture foundation for future granular control over individual metric update frequencies.
This commit is contained in:
@@ -69,6 +69,7 @@ pub struct App {
|
||||
active_host_index: usize,
|
||||
show_help: bool,
|
||||
should_quit: bool,
|
||||
refresh_requested: bool,
|
||||
last_tick: Instant,
|
||||
tick_count: u64,
|
||||
status: String,
|
||||
@@ -106,6 +107,7 @@ impl App {
|
||||
active_host_index: 0,
|
||||
show_help: false,
|
||||
should_quit: false,
|
||||
refresh_requested: false,
|
||||
last_tick: Instant::now(),
|
||||
tick_count: 0,
|
||||
status,
|
||||
@@ -138,7 +140,8 @@ impl App {
|
||||
self.status = "Exiting…".to_string();
|
||||
}
|
||||
KeyCode::Char('r') | KeyCode::Char('R') => {
|
||||
self.status = "Manual refresh requested".to_string();
|
||||
self.refresh_requested = true;
|
||||
self.status = "Refresh requested - sending commands to agents...".to_string();
|
||||
}
|
||||
KeyCode::Left | KeyCode::Char('h') => {
|
||||
self.select_previous_host();
|
||||
@@ -156,6 +159,15 @@ impl App {
|
||||
pub fn should_quit(&self) -> bool {
|
||||
self.should_quit
|
||||
}
|
||||
|
||||
pub fn check_refresh_request(&mut self) -> bool {
|
||||
if self.refresh_requested {
|
||||
self.refresh_requested = false;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn status_text(&self) -> &str {
|
||||
@@ -256,6 +268,10 @@ impl App {
|
||||
self.zmq_subscription.clone(),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn zmq_endpoints(&self) -> &[String] {
|
||||
&self.zmq_endpoints
|
||||
}
|
||||
|
||||
pub fn handle_app_event(&mut self, event: AppEvent) {
|
||||
match event {
|
||||
@@ -337,6 +353,10 @@ impl App {
|
||||
|
||||
self.status = format!("Fetch failed • host: {} • {}", host, error);
|
||||
}
|
||||
AppEvent::RefreshRequested => {
|
||||
// Handle refresh command - will be implemented in the main loop
|
||||
self.status = "Refresh command sent to all agents".to_string();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -641,5 +661,6 @@ pub enum AppEvent {
|
||||
error: String,
|
||||
timestamp: DateTime<Utc>,
|
||||
},
|
||||
RefreshRequested,
|
||||
Shutdown,
|
||||
}
|
||||
|
||||
@@ -153,6 +153,12 @@ fn run_app(
|
||||
|
||||
while !app.should_quit() {
|
||||
drain_app_events(app, event_rx);
|
||||
|
||||
// Check for refresh requests
|
||||
if app.check_refresh_request() {
|
||||
send_refresh_commands(app)?;
|
||||
}
|
||||
|
||||
terminal.draw(|frame| ui::render(frame, app))?;
|
||||
|
||||
if event::poll(tick_rate)? {
|
||||
@@ -301,6 +307,58 @@ fn metrics_blocking_loop(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn send_refresh_commands(app: &mut App) -> Result<()> {
|
||||
let endpoints = app.zmq_endpoints();
|
||||
if endpoints.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let zmq_context = NativeZmqContext::new();
|
||||
|
||||
for endpoint in endpoints {
|
||||
// Convert metrics endpoint (6130) to command endpoint (6131)
|
||||
let command_endpoint = endpoint.replace(":6130", ":6131");
|
||||
|
||||
let socket = zmq_context.socket(zmq::REQ)?;
|
||||
socket.set_linger(0)?;
|
||||
socket.set_rcvtimeo(5000)?; // 5 second timeout
|
||||
socket.set_sndtimeo(5000)?; // 5 second timeout
|
||||
|
||||
match socket.connect(&command_endpoint) {
|
||||
Ok(()) => {
|
||||
debug!("Sending refresh command to {}", command_endpoint);
|
||||
|
||||
match socket.send("refresh", 0) {
|
||||
Ok(()) => {
|
||||
// Wait for response
|
||||
match socket.recv_string(0) {
|
||||
Ok(Ok(response)) => {
|
||||
debug!("Refresh response from {}: {}", command_endpoint, response);
|
||||
// Update status via public method would be needed, for now just log
|
||||
debug!("Refresh sent to agents - response: {}", response);
|
||||
}
|
||||
Ok(Err(e)) => {
|
||||
warn!("String conversion error from {}: {:?}", command_endpoint, e);
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("No response from {}: {}", command_endpoint, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Failed to send refresh to {}: {}", command_endpoint, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Failed to connect to command endpoint {}: {}", command_endpoint, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_zmq_message(
|
||||
message: &NativeZmqMessage,
|
||||
sender: &UnboundedSender<AppEvent>,
|
||||
|
||||
@@ -80,7 +80,7 @@ fn render_help(frame: &mut Frame, area: Rect) {
|
||||
let lines = vec![
|
||||
Line::from("Keyboard Shortcuts"),
|
||||
Line::from("←/→ or h/l: Switch active host"),
|
||||
Line::from("r: Manual refresh status"),
|
||||
Line::from("r: Refresh all metrics"),
|
||||
Line::from("?: Toggle this help"),
|
||||
Line::from("q / Esc: Quit dashboard"),
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user