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

davsclaus pushed a commit to branch fix/CAMEL-23862
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 3f5188ee4039473d7cb83331501ff74c67a55a6b
Author: Claus Ibsen <[email protected]>
AuthorDate: Tue Jun 30 16:08:15 2026 +0200

    chore(tui): speed up process discovery by scanning status files instead of 
all OS processes
    
    Co-Authored-By: Claude Opus 4.6 <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../core/commands/tui/DataRefreshService.java      | 16 +++++
 .../dsl/jbang/core/commands/tui/TuiHelper.java     | 81 ++++++++++++++++------
 2 files changed, 76 insertions(+), 21 deletions(-)

diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DataRefreshService.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DataRefreshService.java
index 2556eae8eef3..1120c041aa92 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DataRefreshService.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/DataRefreshService.java
@@ -50,6 +50,7 @@ import org.apache.camel.util.json.Jsoner;
 class DataRefreshService {
 
     private static final long VANISH_DURATION_MS = 6000;
+    private static final long LIVENESS_CHECK_INTERVAL_MS = 30_000;
     private static final int MAX_TRACES = 200;
 
     /**
@@ -81,6 +82,7 @@ class DataRefreshService {
     // Cached PID list -- full process scan throttled to every 2 seconds (1 
second in burst mode)
     private volatile List<Long> cachedPids = Collections.emptyList();
     private volatile long lastFullScanTime;
+    private volatile long lastLivenessCheckTime;
     private volatile long burstModeUntil;
     final Set<String> stoppingPids = ConcurrentHashMap.newKeySet();
 
@@ -266,9 +268,23 @@ class DataRefreshService {
             }
         }
         if (!fullScan && ctx.selectedPid != null) {
+            boolean checkLiveness = now - lastLivenessCheckTime >= 
LIVENESS_CHECK_INTERVAL_MS;
+            if (checkLiveness) {
+                lastLivenessCheckTime = now;
+            }
             List<IntegrationInfo> previous = data.get();
             for (IntegrationInfo prev : previous) {
                 if (!prev.vanishing && !ctx.selectedPid.equals(prev.pid)) {
+                    if (checkLiveness) {
+                        try {
+                            long pid = Long.parseLong(prev.pid);
+                            if 
(!ProcessHandle.of(pid).map(ProcessHandle::isAlive).orElse(false)) {
+                                continue;
+                            }
+                        } catch (NumberFormatException e) {
+                            // keep it
+                        }
+                    }
                     infos.add(prev);
                 }
             }
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiHelper.java
 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiHelper.java
index d7335aab1f9e..586d04ec5a0c 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiHelper.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/TuiHelper.java
@@ -16,6 +16,7 @@
  */
 package org.apache.camel.dsl.jbang.core.commands.tui;
 
+import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.ArrayList;
@@ -28,6 +29,7 @@ import dev.tamboui.style.Style;
 import dev.tamboui.text.CharWidth;
 import dev.tamboui.text.Line;
 import dev.tamboui.text.Span;
+import org.apache.camel.dsl.jbang.core.common.CommandLineHelper;
 import org.apache.camel.dsl.jbang.core.common.ProcessHelper;
 import org.apache.camel.support.PatternHelper;
 import org.apache.camel.util.FileUtil;
@@ -43,7 +45,8 @@ final class TuiHelper {
     }
 
     /**
-     * Find PIDs of running Camel integrations matching the given name pattern.
+     * Find PIDs of running Camel integrations matching the given name 
pattern. Scans the {@code ~/.camel/} directory
+     * for status files rather than iterating all OS processes, which is 
significantly faster.
      */
     static List<Long> findPids(String name, Function<String, Path> 
statusFileResolver) {
         List<Long> pids = new ArrayList<>();
@@ -53,29 +56,65 @@ final class TuiHelper {
             pattern = pattern + "*";
         }
         final String pat = pattern;
-        ProcessHandle.allProcesses()
-                .filter(ph -> ph.pid() != cur)
-                .forEach(ph -> {
-                    JsonObject root = loadStatus(ph.pid(), statusFileResolver);
-                    if (root != null) {
-                        String pName = ProcessHelper.extractName(root, ph);
-                        pName = FileUtil.onlyName(pName);
+
+        for (long pid : findCandidatePids()) {
+            if (pid == cur) {
+                continue;
+            }
+            // check process is still alive
+            if 
(!ProcessHandle.of(pid).map(ProcessHandle::isAlive).orElse(false)) {
+                continue;
+            }
+            JsonObject root = loadStatus(pid, statusFileResolver);
+            if (root != null) {
+                ProcessHandle ph = ProcessHandle.of(pid).orElse(null);
+                String pName = ProcessHelper.extractName(root, ph);
+                pName = FileUtil.onlyName(pName);
+                if (pName != null && !pName.isEmpty() && 
PatternHelper.matchPattern(pName, pat)) {
+                    pids.add(pid);
+                } else {
+                    JsonObject context = (JsonObject) root.get("context");
+                    if (context != null) {
+                        pName = context.getString("name");
+                        if ("CamelJBang".equals(pName)) {
+                            pName = null;
+                        }
                         if (pName != null && !pName.isEmpty() && 
PatternHelper.matchPattern(pName, pat)) {
-                            pids.add(ph.pid());
-                        } else {
-                            JsonObject context = (JsonObject) 
root.get("context");
-                            if (context != null) {
-                                pName = context.getString("name");
-                                if ("CamelJBang".equals(pName)) {
-                                    pName = null;
-                                }
-                                if (pName != null && !pName.isEmpty() && 
PatternHelper.matchPattern(pName, pat)) {
-                                    pids.add(ph.pid());
-                                }
-                            }
+                            pids.add(pid);
                         }
                     }
-                });
+                }
+            }
+        }
+        return pids;
+    }
+
+    /**
+     * List candidate PIDs by scanning {@code ~/.camel/} for {@code 
*-status.json} files. This is O(number of status
+     * files) rather than O(total OS processes).
+     */
+    static List<Long> findCandidatePids() {
+        List<Long> pids = new ArrayList<>();
+        try {
+            Path camelDir = CommandLineHelper.getCamelDir();
+            if (Files.isDirectory(camelDir)) {
+                try (var files = Files.list(camelDir)) {
+                    files.forEach(p -> {
+                        String fn = p.getFileName().toString();
+                        if (fn.endsWith("-status.json")) {
+                            try {
+                                long pid = Long.parseLong(fn.substring(0, 
fn.length() - "-status.json".length()));
+                                pids.add(pid);
+                            } catch (NumberFormatException e) {
+                                // not a PID-based status file
+                            }
+                        }
+                    });
+                }
+            }
+        } catch (IOException e) {
+            // ignore
+        }
         return pids;
     }
 

Reply via email to