diff --git a/CHANGELOG.md b/CHANGELOG.md index 68f0d10f..75f23bc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## v1.7.61-alpha (2026-05-18) + +- Multi-container stack installs now keep their app card in the `Installing` state for up to 20 minutes while dependency containers are being pulled and prepared. +- BTCPay Server installs no longer appear to vanish or fail after two minutes while Postgres and NBXplorer are still being created before the primary `btcpay-server` container exists. +- The stale-transition escape hatch remains short for start, stop, restart, update, and removal operations, so genuinely wedged lifecycle actions still recover quickly. +- Live validation on `100.70.96.88` confirmed BTCPay Server completed installation and responds on port `23000` with the expected HTTP redirect. + ## v1.7.60-alpha (2026-05-18) - Meshtastic serial detection now rejects malformed or incomplete handshakes instead of accepting unrelated serial devices as a fallback Meshtastic radio. diff --git a/core/Cargo.lock b/core/Cargo.lock index 7687feb1..8b6cbbc9 100644 --- a/core/Cargo.lock +++ b/core/Cargo.lock @@ -80,7 +80,7 @@ checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "archipelago" -version = "1.7.60-alpha" +version = "1.7.61-alpha" dependencies = [ "anyhow", "archipelago-container", diff --git a/core/archipelago/Cargo.toml b/core/archipelago/Cargo.toml index 6030b661..f41cfd5b 100644 --- a/core/archipelago/Cargo.toml +++ b/core/archipelago/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "archipelago" -version = "1.7.60-alpha" +version = "1.7.61-alpha" edition = "2021" description = "Archipelago Bitcoin Node OS - Native backend" authors = ["Archipelago Team"] diff --git a/core/archipelago/src/server.rs b/core/archipelago/src/server.rs index bd19ebae..30eaa3d2 100644 --- a/core/archipelago/src/server.rs +++ b/core/archipelago/src/server.rs @@ -840,6 +840,20 @@ const CONTAINER_ABSENCE_THRESHOLD: u32 = 3; /// scanner's authoritative view. Applies to all transitional variants. const TRANSITIONAL_STUCK_TIMEOUT: Duration = Duration::from_secs(120); +/// Multi-container installs can legitimately spend several minutes before the +/// primary user-facing container exists. BTCPay, for example, pulls/starts +/// Postgres and NBXplorer before `btcpay-server`; do not erase its installing +/// card just because the primary container is absent during that setup window. +const INSTALLING_STUCK_TIMEOUT: Duration = Duration::from_secs(20 * 60); + +fn transitional_stuck_timeout(state: &crate::data_model::PackageState) -> Duration { + if *state == crate::data_model::PackageState::Installing { + INSTALLING_STUCK_TIMEOUT + } else { + TRANSITIONAL_STUCK_TIMEOUT + } +} + /// Returns true if `state` is one of the transitional variants that a /// `spawn_transitional`-style background task owns. While such a state is /// set, the package scanner must not overwrite it with whatever podman @@ -961,13 +975,14 @@ async fn scan_and_update_packages( let overwrite = match existing { Some(existing_entry) if is_transitional(&existing_entry.state) => { let entered = *transitional_since.entry(id.clone()).or_insert(now); - let stuck = now.duration_since(entered) > TRANSITIONAL_STUCK_TIMEOUT; + let timeout = transitional_stuck_timeout(&existing_entry.state); + let stuck = now.duration_since(entered) > timeout; if stuck { warn!( "Container {} stuck in {:?} for >{}s; overriding with scan state {:?}", id, existing_entry.state, - TRANSITIONAL_STUCK_TIMEOUT.as_secs(), + timeout.as_secs(), pkg.state ); transitional_since.remove(id); @@ -1015,12 +1030,13 @@ async fn scan_and_update_packages( if let Some(entry) = merged.get(&id) { if is_transitional(&entry.state) { let entered = *transitional_since.entry(id.clone()).or_insert(now); - if now.duration_since(entered) > TRANSITIONAL_STUCK_TIMEOUT { + let timeout = transitional_stuck_timeout(&entry.state); + if now.duration_since(entered) > timeout { warn!( "Container {} stuck in {:?} and absent for >{}s; removing stale transitional state", id, entry.state, - TRANSITIONAL_STUCK_TIMEOUT.as_secs() + timeout.as_secs() ); merged.remove(&id); transitional_since.remove(&id); @@ -1247,4 +1263,13 @@ mod merge_tests { assert!(!is_transitional(&s), "{:?} should NOT be transitional", s); } } + + #[test] + fn installing_uses_longer_stale_timeout_than_other_transitions() { + assert!(transitional_stuck_timeout(&PackageState::Installing) > TRANSITIONAL_STUCK_TIMEOUT); + assert_eq!( + transitional_stuck_timeout(&PackageState::Stopping), + TRANSITIONAL_STUCK_TIMEOUT + ); + } } diff --git a/neode-ui/package-lock.json b/neode-ui/package-lock.json index 7164dfac..b7377495 100644 --- a/neode-ui/package-lock.json +++ b/neode-ui/package-lock.json @@ -1,12 +1,12 @@ { "name": "neode-ui", - "version": "1.7.60-alpha", + "version": "1.7.61-alpha", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "neode-ui", - "version": "1.7.60-alpha", + "version": "1.7.61-alpha", "dependencies": { "@types/dompurify": "^3.0.5", "@vue-leaflet/vue-leaflet": "^0.10.1", diff --git a/neode-ui/package.json b/neode-ui/package.json index c4db76dd..bddc6b73 100644 --- a/neode-ui/package.json +++ b/neode-ui/package.json @@ -1,7 +1,7 @@ { "name": "neode-ui", "private": true, - "version": "1.7.60-alpha", + "version": "1.7.61-alpha", "type": "module", "scripts": { "start": "./start-dev.sh", diff --git a/release-manifest.json b/release-manifest.json index b12c312c..b2340540 100644 --- a/release-manifest.json +++ b/release-manifest.json @@ -1,29 +1,28 @@ { - "version": "1.7.60-alpha", + "version": "1.7.61-alpha", "release_date": "2026-05-18", "changelog": [ - "Meshtastic serial detection now rejects malformed or incomplete handshakes instead of accepting unrelated serial devices as a fallback Meshtastic radio.", - "Mesh radio auto-detection now skips known non-mesh serial devices such as Sierra Wireless LTE modems and Zooz/Z-Wave sticks, avoiding interference with production peripherals.", - "Meshtastic config sync now sends `want_config_id` with the correct protobuf wire type, fixing radio-side `ignore malformed toradio` errors and allowing node-info/contact ingestion.", - "The stable `/dev/mesh-radio` udev rule no longer claims every `ttyACM*` device; it only matches known mesh USB serial adapters and known USB CDC ACM radio vendors.", - "Live validation on `100.70.96.88` confirmed Archipelago selects `/dev/ttyUSB0`, identifies the Meshtastic node, and refreshes 103 mesh contacts." + "Multi-container stack installs now keep their app card in the `Installing` state for up to 20 minutes while dependency containers are being pulled and prepared.", + "BTCPay Server installs no longer appear to vanish or fail after two minutes while Postgres and NBXplorer are still being created before the primary `btcpay-server` container exists.", + "The stale-transition escape hatch remains short for start, stop, restart, update, and removal operations, so genuinely wedged lifecycle actions still recover quickly.", + "Live validation on `100.70.96.88` confirmed BTCPay Server completed installation and responds on port `23000` with the expected HTTP redirect." ], "components": [ { "name": "archipelago", - "current_version": "1.7.60-alpha", - "new_version": "1.7.60-alpha", - "download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.60-alpha/archipelago", - "sha256": "ef67a16686e1a5f05385455589c56b22243b690b79a914b8b341b3ff4f063be9", - "size_bytes": 42737160 + "current_version": "1.7.61-alpha", + "new_version": "1.7.61-alpha", + "download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.61-alpha/archipelago", + "sha256": "5b08f66aa9a685475b86cdcbabe96c3132f3cc0e72d8daaeb0ddd52a01ca87b6", + "size_bytes": 42738544 }, { - "name": "archipelago-frontend-1.7.60-alpha.tar.gz", - "current_version": "1.7.60-alpha", - "new_version": "1.7.60-alpha", - "download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.60-alpha/archipelago-frontend-1.7.60-alpha.tar.gz", - "sha256": "f781295c9dbd6a18098e63a73e0783dec403ca9598ab4b60defcb717bf1ef5f2", - "size_bytes": 166468694 + "name": "archipelago-frontend-1.7.61-alpha.tar.gz", + "current_version": "1.7.61-alpha", + "new_version": "1.7.61-alpha", + "download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.61-alpha/archipelago-frontend-1.7.61-alpha.tar.gz", + "sha256": "80c5bef31460ece8c1416a8f4e5e88626d1ef4103d40fec0e4872aafb3332dcc", + "size_bytes": 166470847 } ] } diff --git a/releases/manifest.json b/releases/manifest.json index b12c312c..b2340540 100644 --- a/releases/manifest.json +++ b/releases/manifest.json @@ -1,29 +1,28 @@ { - "version": "1.7.60-alpha", + "version": "1.7.61-alpha", "release_date": "2026-05-18", "changelog": [ - "Meshtastic serial detection now rejects malformed or incomplete handshakes instead of accepting unrelated serial devices as a fallback Meshtastic radio.", - "Mesh radio auto-detection now skips known non-mesh serial devices such as Sierra Wireless LTE modems and Zooz/Z-Wave sticks, avoiding interference with production peripherals.", - "Meshtastic config sync now sends `want_config_id` with the correct protobuf wire type, fixing radio-side `ignore malformed toradio` errors and allowing node-info/contact ingestion.", - "The stable `/dev/mesh-radio` udev rule no longer claims every `ttyACM*` device; it only matches known mesh USB serial adapters and known USB CDC ACM radio vendors.", - "Live validation on `100.70.96.88` confirmed Archipelago selects `/dev/ttyUSB0`, identifies the Meshtastic node, and refreshes 103 mesh contacts." + "Multi-container stack installs now keep their app card in the `Installing` state for up to 20 minutes while dependency containers are being pulled and prepared.", + "BTCPay Server installs no longer appear to vanish or fail after two minutes while Postgres and NBXplorer are still being created before the primary `btcpay-server` container exists.", + "The stale-transition escape hatch remains short for start, stop, restart, update, and removal operations, so genuinely wedged lifecycle actions still recover quickly.", + "Live validation on `100.70.96.88` confirmed BTCPay Server completed installation and responds on port `23000` with the expected HTTP redirect." ], "components": [ { "name": "archipelago", - "current_version": "1.7.60-alpha", - "new_version": "1.7.60-alpha", - "download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.60-alpha/archipelago", - "sha256": "ef67a16686e1a5f05385455589c56b22243b690b79a914b8b341b3ff4f063be9", - "size_bytes": 42737160 + "current_version": "1.7.61-alpha", + "new_version": "1.7.61-alpha", + "download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.61-alpha/archipelago", + "sha256": "5b08f66aa9a685475b86cdcbabe96c3132f3cc0e72d8daaeb0ddd52a01ca87b6", + "size_bytes": 42738544 }, { - "name": "archipelago-frontend-1.7.60-alpha.tar.gz", - "current_version": "1.7.60-alpha", - "new_version": "1.7.60-alpha", - "download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.60-alpha/archipelago-frontend-1.7.60-alpha.tar.gz", - "sha256": "f781295c9dbd6a18098e63a73e0783dec403ca9598ab4b60defcb717bf1ef5f2", - "size_bytes": 166468694 + "name": "archipelago-frontend-1.7.61-alpha.tar.gz", + "current_version": "1.7.61-alpha", + "new_version": "1.7.61-alpha", + "download_url": "http://146.59.87.168:3000/lfg2025/archy/releases/download/v1.7.61-alpha/archipelago-frontend-1.7.61-alpha.tar.gz", + "sha256": "80c5bef31460ece8c1416a8f4e5e88626d1ef4103d40fec0e4872aafb3332dcc", + "size_bytes": 166470847 } ] }