This is an automated email from the ASF dual-hosted git repository.

davidzollo pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/seatunnel.git


The following commit(s) were added to refs/heads/dev by this push:
     new 6d3e50c6de [Fix][Zeta] Fix job info REST API fails when floating-point 
metric is NaN (#11517)
6d3e50c6de is described below

commit 6d3e50c6debf150a0160c563cd69a695da1d1213
Author: Kareemingit <[email protected]>
AuthorDate: Thu Jul 23 06:08:50 2026 +0300

    [Fix][Zeta] Fix job info REST API fails when floating-point metric is NaN 
(#11517)
    
    Co-authored-by: David Zollo <[email protected]>
---
 .../engine/server/rest/service/BaseService.java    |  9 +++--
 .../rest/service/BaseServiceNullSafetyTest.java    | 41 ++++++++++++++++++++++
 2 files changed, 48 insertions(+), 2 deletions(-)

diff --git 
a/seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/rest/service/BaseService.java
 
b/seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/rest/service/BaseService.java
index 49bf017034..9f8cd58bfc 100644
--- 
a/seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/rest/service/BaseService.java
+++ 
b/seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/rest/service/BaseService.java
@@ -1175,7 +1175,7 @@ public abstract class BaseService {
                                                         .sum()));
     }
 
-    private JsonObject metricsToJsonObject(Map<String, Object> jobMetrics) {
+    public JsonObject metricsToJsonObject(Map<String, Object> jobMetrics) {
         JsonObject members = new JsonObject();
         jobMetrics.forEach(
                 (key, value) -> {
@@ -1186,7 +1186,12 @@ public abstract class BaseService {
                         if (value instanceof Float
                                 || value instanceof Double
                                 || value instanceof BigDecimal) {
-                            strValue = new 
BigDecimal(value.toString()).toPlainString();
+                            if ((value instanceof Double && 
!Double.isFinite((Double) value))
+                                    || (value instanceof Float && 
!Float.isFinite((Float) value))) {
+                                strValue = value.toString();
+                            } else {
+                                strValue = new 
BigDecimal(value.toString()).toPlainString();
+                            }
                         } else {
                             strValue = value.toString();
                         }
diff --git 
a/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/rest/service/BaseServiceNullSafetyTest.java
 
b/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/rest/service/BaseServiceNullSafetyTest.java
index b771157ca4..2ab28648a8 100644
--- 
a/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/rest/service/BaseServiceNullSafetyTest.java
+++ 
b/seatunnel-engine/seatunnel-engine-server/src/test/java/org/apache/seatunnel/engine/server/rest/service/BaseServiceNullSafetyTest.java
@@ -30,6 +30,8 @@ import com.hazelcast.internal.json.JsonObject;
 import com.hazelcast.spi.impl.NodeEngineImpl;
 
 import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 
 import static org.mockito.Mockito.mock;
 
@@ -108,4 +110,43 @@ public class BaseServiceNullSafetyTest {
         Assertions.assertEquals("", result.getString(RestConstant.START_TIME, 
null));
         Assertions.assertEquals("", result.getString(RestConstant.FINISH_TIME, 
null));
     }
+
+    @Test
+    public void testMetricsToJsonObjectWithNonFiniteFloats() {
+        // 1. We create an anonymous subclass of BaseService if it's abstract,
+        // or just instantiate it if it's concrete.
+        // Passing null for dependencies since metricsToJsonObject doesn't 
rely on them.
+        BaseService baseService = new BaseService(null) {
+                    // Dummy anonymous class in case BaseService is abstract 
in the codebase
+                };
+
+        // 2. Prepare the boundary condition metrics
+        Map<String, Object> jobMetrics = new HashMap<>();
+        jobMetrics.put("normal_double", 123.456d);
+        jobMetrics.put("normal_float", 78.9f);
+        jobMetrics.put("nan_double", Double.NaN);
+        jobMetrics.put("nan_float", Float.NaN);
+        jobMetrics.put("positive_infinity", Double.POSITIVE_INFINITY);
+        jobMetrics.put("negative_infinity", Double.NEGATIVE_INFINITY);
+
+        // 3. Nested map to test the recursive loop in your fix
+        Map<String, Object> nestedMetrics = new HashMap<>();
+        nestedMetrics.put("nested_nan", Double.NaN);
+        jobMetrics.put("nested_map", nestedMetrics);
+
+        // 4. Execute your fixed method
+        JsonObject result = baseService.metricsToJsonObject(jobMetrics);
+
+        // 5. Assert the values were parsed to strings safely without throwing 
an exception
+        Assertions.assertEquals("123.456", result.getString("normal_double", 
""));
+        Assertions.assertEquals("78.9", result.getString("normal_float", ""));
+        Assertions.assertEquals("NaN", result.getString("nan_double", ""));
+        Assertions.assertEquals("NaN", result.getString("nan_float", ""));
+        Assertions.assertEquals("Infinity", 
result.getString("positive_infinity", ""));
+        Assertions.assertEquals("-Infinity", 
result.getString("negative_infinity", ""));
+
+        // Check the nested map
+        JsonObject nestedResult = result.get("nested_map").asObject();
+        Assertions.assertEquals("NaN", 
nestedResult.get("nested_nan").asString());
+    }
 }

Reply via email to