From b588b401201ac974b78fbb2036dbe95ca7b4e695 Mon Sep 17 00:00:00 2001
From: Loakesh Indiran <66478092+Loaki07@users.noreply.github.com>
Date: Fri, 11 Jul 2025 20:04:14 +0530
Subject: [PATCH] fix: f32 deserialization nats (#7543) (#7544)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
### **User description**
fix #7543
___
### **PR Type**
Bug fix
___
### **Description**
- Add JSON parse error handling in cluster module
- Log and skip invalid node payloads
- Prevent infinite or NaN CPU usage
- Warn and reset invalid CPU usage to zero
___
### **Changes diagram**
```mermaid
flowchart LR
A["cluster::watch_node_list"] -- "on JSON parse error" --> B["log error and continue"]
C["sysinfo::get_node_metrics"] -- "on CPU infinite or NaN" --> D["log warning and set zero"]
```
___
### **Changes walkthrough** 📝
| Relevant
files |
|---|
| Error
handling |
mod.rsAdd JSON parse error
handling
src/common/infra/cluster/mod.rs
Replace unwrap with match on JSON
deserialization Log detailed error and payload on parse
failure Continue loop instead of panicking on invalid node
|
+12/-1
|
mod.rsSanitize CPU usage
values
src/config/src/utils/sysinfo/mod.rs
Introduce sanity check for CPU usage value Log warning on
infinite or NaN CPU usage Reset cpu_usage to zero
when invalid
|
+8/-1
|
|
___
> Need help?
Type /help how to
... in the comments thread for any questions about PR-Agent
usage.Check out the documentation
for more information.
---
src/common/infra/cluster/mod.rs | 13 ++++++++++++-
src/config/src/utils/sysinfo/mod.rs | 9 ++++++++-
2 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/src/common/infra/cluster/mod.rs b/src/common/infra/cluster/mod.rs
index cff9ae3fb6..ccd1ae40d3 100644
--- a/src/common/infra/cluster/mod.rs
+++ b/src/common/infra/cluster/mod.rs
@@ -326,7 +326,18 @@ async fn watch_node_list() -> Result<()> {
match ev {
Event::Put(ev) => {
let item_key = ev.key.strip_prefix(key).unwrap();
- let mut item_value: Node = json::from_slice(&ev.value.unwrap()).unwrap();
+ let mut item_value: Node = match json::from_slice(ev.value.as_ref().unwrap()) {
+ Ok(v) => v,
+ Err(e) => {
+ let value_str = String::from_utf8_lossy(ev.value.as_ref().unwrap());
+ log::error!(
+ "[CLUSTER] watch_node_list: error parsing node: {}, payload: {}",
+ e,
+ value_str
+ );
+ continue;
+ }
+ };
let (_broadcasted, exist) = match NODES.read().await.get(item_key) {
Some(v) => (v.broadcasted, item_value.is_same(v)),
None => (false, false),
diff --git a/src/config/src/utils/sysinfo/mod.rs b/src/config/src/utils/sysinfo/mod.rs
index 2bf32d6fb5..bc1c92ce6b 100644
--- a/src/config/src/utils/sysinfo/mod.rs
+++ b/src/config/src/utils/sysinfo/mod.rs
@@ -41,7 +41,14 @@ pub struct NodeMetrics {
/// Get the node running metrics
pub fn get_node_metrics() -> NodeMetrics {
let cpu_total = get_cpu_limit();
- let cpu_usage = get_cpu_usage() / cpu_total as f32;
+ let mut cpu_usage = get_cpu_usage() / cpu_total as f32;
+ if cpu_usage.is_infinite() || cpu_usage.is_nan() {
+ log::warn!(
+ "CPU usage is infinite or NaN, setting to 0. cpu_usage: {}, cpu_total: {cpu_total}",
+ get_cpu_usage()
+ );
+ cpu_usage = 0.0;
+ }
let memory_total = get_memory_limit();
let memory_usage = get_memory_usage();
let tcp_conns = get_tcp_connections();