Fix asset inventory update
build-windows / build-hello-agent-x64 (push) Successful in 6m6s
build-windows / sign-hello-agent-x64 (push) Successful in 6s
build-windows / validate-hello-agent-x64 (push) Successful in 7s

This commit is contained in:
2026-05-09 11:32:12 +02:00
parent e815776329
commit 8025f8558a
2 changed files with 30 additions and 6 deletions
+6 -2
View File
@@ -12,8 +12,12 @@
//! Get-CimInstance and emits compact JSON. One subprocess for the whole
//! inventory is cheaper than per-field WMI queries and avoids pulling a
//! `wmi`/COM crate into the dep tree. Inventory is collected once at
//! startup; the sysinfo loop's hash-compare suppresses re-uploads of
//! unchanged data, so this isn't repeated on every 120 s tick.
//! startup. Collection routinely outruns the first sysinfo tick (TIME_CONN
//! = 3 s) — `Invoke-RestMethod 'api.ipify.org' -TimeoutSec 5` alone can
//! burn that budget on hosts with blocked egress — so the sysinfo loop in
//! `hbbs_http::sync` watches for INVENTORY transitioning empty → populated
//! and forces a re-upload at that point. Subsequent ticks are suppressed
//! by the loop's `had_inventory` / `uploaded` bookkeeping.
//!
//! Non-Windows builds return an empty JSON object — hello-agent v0 only
//! ships on Windows, but keeping the cross-platform surface compiling
+24 -4
View File
@@ -57,6 +57,13 @@ struct InfoUploaded {
last_uploaded: Option<Instant>,
id: String,
username: Option<String>,
// hello-agent local patch: tracks whether the most recent successful
// sysinfo upload carried the `inventory` key. The CMDB collector
// (hello-agent's `inventory.rs`) runs on a background thread and can
// finish *after* the first sysinfo tick has already fired; without
// this flag the loop would never re-upload because `uploaded == true`
// and `username` is unchanged. Re-apply on vendor resync.
had_inventory: bool,
}
impl Default for InfoUploaded {
@@ -67,18 +74,20 @@ impl Default for InfoUploaded {
last_uploaded: None,
id: "".to_owned(),
username: None,
had_inventory: false,
}
}
}
impl InfoUploaded {
fn uploaded(url: String, id: String, username: String) -> Self {
fn uploaded(url: String, id: String, username: String, had_inventory: bool) -> Self {
Self {
uploaded: true,
url,
last_uploaded: None,
id,
username: Some(username),
had_inventory,
}
}
}
@@ -126,9 +135,18 @@ async fn start_hbbs_sync_async() {
// we may not be able to get the username before login after the next restart.
let mut v = crate::get_sysinfo();
let sys_username = v["username"].as_str().unwrap_or_default().to_string();
// hello-agent local patch: the inventory collector is async
// (PowerShell + WMI + ipify, see `inventory::collect_inventory`)
// and routinely finishes after the first sysinfo tick. When
// INVENTORY transitions from empty → populated we need to
// re-upload, even though `uploaded == true` and the username
// hasn't changed. Re-apply on vendor resync.
let inventory_now_available = !config::INVENTORY.read().unwrap().is_empty();
// Though the username comparison is only necessary on Windows,
// we still keep the comparison on other platforms for consistency.
let need_upload = (!info_uploaded.uploaded || info_uploaded.username.as_ref() != Some(&sys_username)) &&
let need_upload = (!info_uploaded.uploaded
|| info_uploaded.username.as_ref() != Some(&sys_username)
|| (inventory_now_available && !info_uploaded.had_inventory)) &&
info_uploaded.last_uploaded.map(|x| x.elapsed() >= UPLOAD_SYSINFO_TIMEOUT).unwrap_or(true);
if need_upload {
v["version"] = json!(crate::VERSION);
@@ -158,9 +176,11 @@ async fn start_hbbs_sync_async() {
// the `inventory` key, identical to a vanilla rustdesk
// install.
let inventory = config::INVENTORY.read().unwrap().clone();
let mut had_inventory = false;
if !inventory.is_empty() {
if let Ok(inv_v) = serde_json::from_str::<Value>(&inventory) {
v["inventory"] = inv_v;
had_inventory = true;
}
}
let ab_name = Config::get_option(keys::OPTION_PRESET_ADDRESS_BOOK_NAME);
@@ -232,7 +252,7 @@ async fn start_hbbs_sync_async() {
}
};
if samever {
info_uploaded = InfoUploaded::uploaded(url.clone(), id.clone(), sys_username);
info_uploaded = InfoUploaded::uploaded(url.clone(), id.clone(), sys_username, had_inventory);
log::info!("sysinfo not changed, skip upload");
continue;
}
@@ -241,7 +261,7 @@ async fn start_hbbs_sync_async() {
match crate::post_request(url.replace("heartbeat", "sysinfo"), v, "").await {
Ok(x) => {
if x == "SYSINFO_UPDATED" {
info_uploaded = InfoUploaded::uploaded(url.clone(), id.clone(), sys_username);
info_uploaded = InfoUploaded::uploaded(url.clone(), id.clone(), sys_username, had_inventory);
log::info!("sysinfo updated");
if !hash.is_empty() {
config::Status::set("sysinfo_hash", hash);