Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d0f8cd50d
|
||
|
|
b8e957fe33
|
No files matched your search
@@ -1,5 +1,21 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [2.0.1] - 2026-04-25
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- **TUI quit no longer hangs on a misleading "updating DHT" screen.**
|
||||||
|
The 2.0.0 migration to `iroh-gossip-rendezvous` removed the
|
||||||
|
synchronous mainline-DHT publish that the old `Gossip::shutdown()`
|
||||||
|
performed (rendezvous entries age out instead), but the TUI flow
|
||||||
|
was unchanged: pressing `q` drew an "updating DHT…" overlay,
|
||||||
|
awaited `swarm.shutdown()`, and only then restored the terminal —
|
||||||
|
so the user sat on the stale message for as long as
|
||||||
|
`endpoint.close()` took to flush in-flight connections. Restore
|
||||||
|
the terminal the moment `q` is pressed, drop the overlay, and
|
||||||
|
cap the graceful-shutdown wait at 2 s so a slow endpoint close
|
||||||
|
can't stall the process.
|
||||||
|
|
||||||
## [2.0.0] - 2026-04-23
|
## [2.0.0] - 2026-04-23
|
||||||
|
|
||||||
### Breaking
|
### Breaking
|
||||||
|
|||||||
Generated
+1
-1
@@ -1031,7 +1031,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "donglora-bridge"
|
name = "donglora-bridge"
|
||||||
version = "2.0.0"
|
version = "2.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"blake3",
|
"blake3",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "donglora-bridge"
|
name = "donglora-bridge"
|
||||||
version = "2.0.0"
|
version = "2.0.1"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
authors = ["Stephen Waits <steve@waits.net>"]
|
authors = ["Stephen Waits <steve@waits.net>"]
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|||||||
+10
-5
@@ -1,7 +1,7 @@
|
|||||||
use donglora_bridge::{config, gossip, radio, rate_limit, router, setup, tui};
|
use donglora_bridge::{config, gossip, radio, rate_limit, router, setup, tui};
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Instant;
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
@@ -174,13 +174,18 @@ async fn main() -> Result<()> {
|
|||||||
} else {
|
} else {
|
||||||
let terminal = tui::run(config_watch_rx, swarm.clone(), stats, log_rx, cancel.clone(), start_time);
|
let terminal = tui::run(config_watch_rx, swarm.clone(), stats, log_rx, cancel.clone(), start_time);
|
||||||
|
|
||||||
cancel.cancel();
|
// Restore the terminal first so the user's shell reappears the moment
|
||||||
swarm.shutdown().await;
|
// they hit `q`. iroh-gossip-rendezvous needs no synchronous DHT work
|
||||||
info!("donglora-bridge stopped");
|
// on shutdown — entries age out — so the only remaining wait is
|
||||||
|
// `endpoint.close()` flushing in-flight connections. Bound it.
|
||||||
if let Ok(mut term) = terminal {
|
if let Ok(mut term) = terminal {
|
||||||
tui::restore_terminal(&mut term);
|
tui::restore_terminal(&mut term);
|
||||||
}
|
}
|
||||||
|
cancel.cancel();
|
||||||
|
if tokio::time::timeout(Duration::from_secs(2), swarm.shutdown()).await.is_err() {
|
||||||
|
warn!("graceful shutdown timed out — exiting anyway");
|
||||||
|
}
|
||||||
|
info!("donglora-bridge stopped");
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-25
@@ -17,7 +17,7 @@ use ratatui::layout::{Alignment, Constraint, Direction, Layout, Rect};
|
|||||||
use ratatui::style::{Color, Modifier, Style};
|
use ratatui::style::{Color, Modifier, Style};
|
||||||
use ratatui::symbols;
|
use ratatui::symbols;
|
||||||
use ratatui::text::{Line, Span};
|
use ratatui::text::{Line, Span};
|
||||||
use ratatui::widgets::{Block, Borders, Clear, Paragraph, Sparkline};
|
use ratatui::widgets::{Block, Borders, Paragraph, Sparkline};
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use tokio_util::sync::CancellationToken;
|
use tokio_util::sync::CancellationToken;
|
||||||
|
|
||||||
@@ -173,7 +173,6 @@ pub fn run(
|
|||||||
&mut series,
|
&mut series,
|
||||||
);
|
);
|
||||||
|
|
||||||
terminal.draw(|frame| draw_shutdown_overlay(frame, frame.area()))?;
|
|
||||||
Ok(terminal)
|
Ok(terminal)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -631,29 +630,6 @@ fn pad_right_align(data: &[u64], width: usize) -> Vec<u64> {
|
|||||||
padded
|
padded
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Shutdown overlay ─────────────────────────────────────────────
|
|
||||||
|
|
||||||
fn draw_shutdown_overlay(frame: &mut ratatui::Frame, area: Rect) {
|
|
||||||
let dim = Paragraph::new("").style(Style::default().bg(Color::Black));
|
|
||||||
frame.render_widget(dim, area);
|
|
||||||
|
|
||||||
let w = 36u16;
|
|
||||||
let h = 3u16;
|
|
||||||
let x = area.x + area.width.saturating_sub(w) / 2;
|
|
||||||
let y = area.y + area.height.saturating_sub(h) / 2;
|
|
||||||
let popup = Rect::new(x, y, w.min(area.width), h.min(area.height));
|
|
||||||
|
|
||||||
frame.render_widget(Clear, popup);
|
|
||||||
let block = Block::default().borders(Borders::ALL).border_style(Style::default().fg(C_BORDER));
|
|
||||||
let text = Paragraph::new(Line::from(vec![
|
|
||||||
Span::styled(" Shutting down", Style::default().fg(C_RATE_DROP)),
|
|
||||||
Span::styled(" — updating DHT...", Style::default().fg(C_LABEL)),
|
|
||||||
]))
|
|
||||||
.alignment(Alignment::Center)
|
|
||||||
.block(block);
|
|
||||||
frame.render_widget(text, popup);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Shared helpers ───────────────────────────────────────────────
|
// ── Shared helpers ───────────────────────────────────────────────
|
||||||
|
|
||||||
fn panel_block(title: &str) -> Block<'static> {
|
fn panel_block(title: &str) -> Block<'static> {
|
||||||
|
|||||||
Reference in new issue
Block a user