dev mode: prefer the DHP's data, fall back to the local install
A dev run is for working on the client, and the data worth working against lives on the DHP. Deciding this by "is anything installed" guessed wrong both ways: a PC with an old install silently ran on stale local data, with nothing on screen saying so, while a PC with none was refused outright. Now: dev mode + the DHP answering -> the client runs from the checkout against the DHP's API and tiles, installed or not. No DHP -> the local stack, as before. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -696,22 +696,27 @@ impl Launcher {
|
||||
repo.join("tools").join("build").join("build.bat").is_file().then_some(repo)
|
||||
}
|
||||
|
||||
/// Can this PC run a dev client with no install at all, straight against its DHP?
|
||||
/// The DHP-backed dev run: the client comes from the checkout and its data comes from the
|
||||
/// DHP - live tracks, live tiles, nothing installed needed.
|
||||
///
|
||||
/// Only with nothing installed: where there IS an install the local stack is the better
|
||||
/// run - it holds this PC's own data and it is what an operator actually uses. This is
|
||||
/// purely the case that used to be refused outright.
|
||||
/// PREFERRED whenever dev mode is on and the DHP answers, installed or not. A dev run is
|
||||
/// for working on the client, and the DHP holds the data worth working against; the local
|
||||
/// stack is the fallback for when the DHP cannot be reached. Deciding it by "is anything
|
||||
/// installed" guessed wrong in both directions: a PC with an old install silently ran on
|
||||
/// stale local data, and nothing on screen said so.
|
||||
///
|
||||
/// Every reason it might not work is checked here rather than at launch, because the hub
|
||||
/// needs to know whether to offer Launch at all.
|
||||
fn dhp_direct(inner: &Inner) -> Option<DhpDirect> {
|
||||
if Self::dev_engine(inner).is_none() || !inner.online || inner.state.installed_version.is_some() {
|
||||
if Self::dev_engine(inner).is_none() || !inner.online {
|
||||
return None;
|
||||
}
|
||||
let mcp = inner.settings.mcp_url.trim();
|
||||
if mcp.is_empty() {
|
||||
return None;
|
||||
}
|
||||
// The DHP's own Engine API, as its health answer named it. None means the DHP did not
|
||||
// say where it is, so there is nothing to point a client at and the run falls back.
|
||||
Some(DhpDirect {
|
||||
engine_url: inner.engine_url.clone()?,
|
||||
mcp_url: mcp.to_string(),
|
||||
@@ -2975,6 +2980,27 @@ fn swapped_user<'a>(asked: &'a str, operator: Option<&str>) -> Option<&'a str> {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
/// The rule the hub now follows: the DHP is PREFERRED, the install is the fallback.
|
||||
/// Written as a table because the old version decided this by "is anything installed",
|
||||
/// which was wrong in both directions.
|
||||
#[test]
|
||||
fn the_dhp_is_preferred_and_the_install_is_the_fallback() {
|
||||
// (dev mode, online, installed) -> what a dev run should use
|
||||
let cases = [
|
||||
(true, true, true, "dhp"), // installed, but online: the live data wins
|
||||
(true, true, false, "dhp"), // nothing installed: the case that was refused outright
|
||||
(true, false, true, "local"), // no DHP: fall back to what is on this PC
|
||||
(true, false, false, "none"), // no DHP and nothing installed: nothing to run
|
||||
(false, true, true, "local"), // dev mode off: an ordinary operator launch
|
||||
];
|
||||
for (dev, online, installed, want) in cases {
|
||||
// dhp_direct() needs an Inner, so this asserts the DECISION the gate encodes rather
|
||||
// than calling it: dev && online picks the DHP, and only then does install matter.
|
||||
let got = if dev && online { "dhp" } else if installed { "local" } else { "none" };
|
||||
assert_eq!(got, want, "dev={dev} online={online} installed={installed}");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nothing_installed_still_launches_when_the_dhp_can_stand_in() {
|
||||
// The whole point of the DHP-direct run: a checkout and a reachable DHP are enough.
|
||||
|
||||
@@ -243,9 +243,12 @@
|
||||
<p class="secondary">
|
||||
{#if checking}
|
||||
Checking {site}…
|
||||
{:else if !s?.installed}
|
||||
Nothing is installed here: the client comes from your checkout and runs on
|
||||
<strong>{site}</strong>'s data. You sign in inside ODIAN, not here.
|
||||
{:else if s?.dhp_direct}
|
||||
<!-- The DHP is preferred whenever it answers, installed or not: a dev run is for
|
||||
working on the client, and the live data is on the DHP. -->
|
||||
Live from <strong>{site}</strong>: the client comes from your checkout and its data,
|
||||
tracks and map come from the DHP. You sign in inside ODIAN, not here.
|
||||
{#if s?.installed}<span class="dim">Nothing local starts; {s.installed} is used only when the DHP is unreachable.</span>{/if}
|
||||
{:else if s?.update_required}
|
||||
<!-- Only reachable on a dev run: any other PC would be on the "update" action. -->
|
||||
ODIAN <strong>{s.installed}</strong> is installed, <strong>{s.available}</strong> is on {site}. A dev run starts
|
||||
|
||||
Reference in New Issue
Block a user