fix(tray): live-probe the web console instead of sniffing the install layout
windows-drivers / probe-and-proto (push) Successful in 29s
audit / cargo-audit (push) Successful in 1m31s
apple / swift (push) Successful in 1m8s
windows-drivers / driver-build (push) Successful in 1m35s
android / android (push) Successful in 4m45s
ci / web (push) Successful in 1m2s
ci / docs-site (push) Successful in 1m0s
release / apple (push) Successful in 7m35s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
windows-host / package (push) Has been cancelled
apple / screenshots (push) Has been cancelled
ci / bench (push) Has been cancelled
ci / rust (push) Has been cancelled
deb / build-publish (push) Has been cancelled
decky / build-publish (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
flatpak / build-publish (push) Has been cancelled
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Has been cancelled
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Has been cancelled
windows / build (aarch64-pc-windows-msvc) (push) Has been cancelled
windows / build (x86_64-pc-windows-msvc) (push) Has been cancelled
windows-drivers / probe-and-proto (push) Successful in 29s
audit / cargo-audit (push) Successful in 1m31s
apple / swift (push) Successful in 1m8s
windows-drivers / driver-build (push) Successful in 1m35s
android / android (push) Successful in 4m45s
ci / web (push) Successful in 1m2s
ci / docs-site (push) Successful in 1m0s
release / apple (push) Successful in 7m35s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
windows-host / package (push) Has been cancelled
apple / screenshots (push) Has been cancelled
ci / bench (push) Has been cancelled
ci / rust (push) Has been cancelled
deb / build-publish (push) Has been cancelled
decky / build-publish (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
flatpak / build-publish (push) Has been cancelled
windows-msix / package (x64, C:\Users\Public\ffmpeg, x86_64-pc-windows-msvc, C:\t) (push) Has been cancelled
windows-msix / package (arm64, C:\Users\Public\ffmpeg-arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Has been cancelled
windows / build (aarch64-pc-windows-msvc) (push) Has been cancelled
windows / build (x86_64-pc-windows-msvc) (push) Has been cancelled
The "Open web console" entry was gated on {exe dir}\web\web-run.cmd (Windows)
/ the punktfunk-web unit file (Linux) — which misses consoles run from a repo
checkout (the RTX box, caught on-glass) and shows a dead entry while an
installed console is stopped. The poller now probes https://127.0.0.1:<web
port>/ each cycle (any HTTP response = up, transport failure = down) and the
menu follows live on both platforms.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -118,11 +118,15 @@ struct Shared {
|
||||
}
|
||||
|
||||
impl Poller {
|
||||
/// Spawn the poll thread; `on_change` fires (from that thread) whenever the status changes.
|
||||
/// Spawn the poll thread; `on_change(status, console_up)` fires (from that thread) whenever
|
||||
/// either changes. `console_up` is a live loopback probe of the web console on `web_port` —
|
||||
/// ground truth for the "Open web console" menu entry (a layout sniff would miss consoles run
|
||||
/// from a repo checkout, and shows a dead entry while an installed console is still starting).
|
||||
pub fn spawn(
|
||||
mgmt_addr: String,
|
||||
mgmt_port: u16,
|
||||
on_change: Box<dyn Fn(TrayStatus) + Send>,
|
||||
web_port: u16,
|
||||
on_change: Box<dyn Fn(TrayStatus, bool) + Send>,
|
||||
) -> Poller {
|
||||
let shared = Arc::new(Shared {
|
||||
poked: Mutex::new(false),
|
||||
@@ -131,7 +135,7 @@ impl Poller {
|
||||
let thread_shared = shared.clone();
|
||||
std::thread::Builder::new()
|
||||
.name("status-poll".into())
|
||||
.spawn(move || poll_loop(&thread_shared, &mgmt_addr, mgmt_port, on_change))
|
||||
.spawn(move || poll_loop(&thread_shared, &mgmt_addr, mgmt_port, web_port, on_change))
|
||||
.expect("spawn status-poll thread");
|
||||
Poller { shared }
|
||||
}
|
||||
@@ -147,7 +151,8 @@ fn poll_loop(
|
||||
shared: &Shared,
|
||||
mgmt_addr: &str,
|
||||
mgmt_port: u16,
|
||||
on_change: Box<dyn Fn(TrayStatus) + Send>,
|
||||
web_port: u16,
|
||||
on_change: Box<dyn Fn(TrayStatus, bool) + Send>,
|
||||
) {
|
||||
// IPv6 literals bracketed, like the Linux client's `base_url`.
|
||||
let url = if mgmt_addr.contains(':') {
|
||||
@@ -155,8 +160,9 @@ fn poll_loop(
|
||||
} else {
|
||||
format!("https://{mgmt_addr}:{mgmt_port}/api/v1/local/summary")
|
||||
};
|
||||
let console_url = format!("https://127.0.0.1:{web_port}/");
|
||||
let agent = agent(load_pin());
|
||||
let mut last: Option<TrayStatus> = None;
|
||||
let mut last: Option<(TrayStatus, bool)> = None;
|
||||
// When the summary became unreachable while the service was running (grace anchor).
|
||||
// Runs for the process lifetime (the tray exits by process exit; nothing to unwind).
|
||||
let mut unreachable_since: Option<Instant> = None;
|
||||
@@ -176,12 +182,13 @@ fn poll_loop(
|
||||
};
|
||||
let grace_expired = unreachable_since.is_some_and(|t| t.elapsed() >= START_GRACE);
|
||||
let status = map_status(&svc, summary, grace_expired);
|
||||
if last.as_ref() != Some(&status) {
|
||||
on_change(status.clone());
|
||||
last = Some(status);
|
||||
let console_up = probe_console(&agent, &console_url);
|
||||
if last.as_ref() != Some(&(status.clone(), console_up)) {
|
||||
on_change(status.clone(), console_up);
|
||||
last = Some((status, console_up));
|
||||
}
|
||||
// 3 s while there is anything to watch; back off when the box just doesn't run a host.
|
||||
let cadence = match last {
|
||||
let cadence = match last.as_ref().map(|(s, _)| s) {
|
||||
Some(TrayStatus::Stopped) | Some(TrayStatus::NotInstalled) => Duration::from_secs(10),
|
||||
_ => Duration::from_secs(3),
|
||||
};
|
||||
@@ -193,6 +200,16 @@ fn poll_loop(
|
||||
}
|
||||
}
|
||||
|
||||
/// Is the web console answering on loopback? Any HTTP response (incl. the login redirect / 401)
|
||||
/// counts as up — only a transport failure (nothing listening, TLS handshake dead) means down.
|
||||
fn probe_console(agent: &ureq::Agent, url: &str) -> bool {
|
||||
match agent.get(url).call() {
|
||||
Ok(_) => true,
|
||||
Err(ureq::Error::Status(..)) => true,
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
// ── Summary fetch (loopback HTTPS) ──────────────────────────────────────────────────────────────
|
||||
|
||||
fn fetch_summary(agent: &ureq::Agent, url: &str) -> Option<Summary> {
|
||||
|
||||
Reference in New Issue
Block a user