davsclaus commented on code in PR #27399:
URL: https://github.com/apache/camel/pull/27399#discussion_r4194085706


##########
dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/IntegrationLauncher.java:
##########
@@ -218,6 +238,61 @@ private static RuntimeHelper.ProcessInfo findByPid(long 
pid) {
         return null;
     }
 
+    /**
+     * The console output of a run that failed to start, as camel_get_log 
shows a log (CAMEL-25364): each record keeps
+     * its message, an error its root cause and the first line of the user's 
code, and the stack frames are left out.
+     * The end of the raw output is mostly frames of the runtime, and the line 
that says what went wrong is above them.
+     */
+    static String failureOutput(Path output) {
+        List<String> lines;
+        try {
+            lines = Files.readAllLines(output, StandardCharsets.UTF_8);
+        } catch (IOException e) {
+            return readTail(output);
+        }
+        if (lines.size() > 5000) {
+            lines = lines.subList(lines.size() - 5000, lines.size());
+        }
+        lines = lines.stream().filter(l -> !l.isBlank()).toList();
+        JsonObject log = LogFileReader.build(lines, FAILURE_RECORDS, null, 
null, false, new JsonObject());

Review Comment:
   Thanks, the javac case is exactly the one that matters. Fixed in 57b420404b: 
the frames (`at ...` and `... N more`) are taken out of the lines before they 
are folded a second time, so each record keeps its exception lines: the 
exception, its `Caused by:` lines and a message over several lines such as the 
javac diagnostics. The first frame of the user's code still comes from the 
folded view, and the output ends with "(stack frames left out)". Output with no 
log records goes back to `readTail`, so the end is kept. New tests: 
`failureOutputKeepsAMessageOverSeveralLines` (a `ReflectException` with 
`OrderNumber.java:12: error: cannot find symbol`) and 
`failureOutputWithoutLogRecordsKeepsTheEnd`.
   
   _Claude Code on behalf of davsclaus_



##########
dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/IntegrationLauncher.java:
##########
@@ -218,6 +238,61 @@ private static RuntimeHelper.ProcessInfo findByPid(long 
pid) {
         return null;
     }
 
+    /**
+     * The console output of a run that failed to start, as camel_get_log 
shows a log (CAMEL-25364): each record keeps
+     * its message, an error its root cause and the first line of the user's 
code, and the stack frames are left out.
+     * The end of the raw output is mostly frames of the runtime, and the line 
that says what went wrong is above them.
+     */
+    static String failureOutput(Path output) {
+        List<String> lines;
+        try {
+            lines = Files.readAllLines(output, StandardCharsets.UTF_8);
+        } catch (IOException e) {
+            return readTail(output);
+        }
+        if (lines.size() > 5000) {
+            lines = lines.subList(lines.size() - 5000, lines.size());
+        }
+        lines = lines.stream().filter(l -> !l.isBlank()).toList();
+        JsonObject log = LogFileReader.build(lines, FAILURE_RECORDS, null, 
null, false, new JsonObject());
+        JsonArray rows = (JsonArray) log.get("lines");
+        if (rows == null || rows.isEmpty()) {
+            return readTail(output);
+        }
+        StringBuilder sb = new StringBuilder();
+        // newest first in the log tool; oldest first here, so it reads as the 
console did
+        for (int i = rows.size() - 1; i >= 0; i--) {
+            JsonObject r = (JsonObject) rows.get(i);
+            String level = r.getStringOrDefault("time", "").isEmpty() ? "" : 
r.getStringOrDefault("level", "") + " ";
+            sb.append(level).append(r.getStringOrDefault("message", ""));
+            if (r.get("cause") != null) {
+                sb.append("\n  cause: ").append(r.getString("cause"));
+            }
+            if (r.get("at") != null) {
+                sb.append("\n  at: ").append(r.getString("at"));
+            }
+            if (r.get("detailLines") != null) {
+                sb.append("\n  (").append(r.get("detailLines")).append(" lines 
of stack trace left out)");
+            } else if (r.get("detail") != null) {
+                sb.append("\n").append(r.getString("detail"));
+            }
+            sb.append("\n");
+        }
+        return sb.toString().strip();
+    }
+
+    /** The integration that runs with this directory as its working 
directory, or null. */
+    private static RuntimeHelper.ProcessInfo runningFrom(Path directory) {
+        Path wanted = directory.toAbsolutePath().normalize();
+        for (RuntimeHelper.ProcessInfo p : RuntimeHelper.discoverProcesses()) {
+            Path dir = workingDirectory(p.pid());
+            if (dir != null && 
dir.toAbsolutePath().normalize().equals(wanted)) {

Review Comment:
   Fixed in 57b420404b: the directories are compared with `Files.isSameFile`, 
falling back to the normalized paths on an `IOException`. 
`IntegrationLauncherGuardTest.theRunningIntegrationIsFoundThroughASymlink` pins 
it.
   
   _Claude Code on behalf of davsclaus_



##########
dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/IntegrationLauncher.java:
##########
@@ -72,6 +76,22 @@ public static JsonObject run(Path directory, List<String> 
files, String name, bo
             return result;
         }
         result.put("directory", directory.toString());
+        if (sourceDir) {
+            // the whole directory is the app: one already running from it is 
that app, and a second copy only fights
+            // it for ports and files and makes its name ambiguous to the 
other tools
+            RuntimeHelper.ProcessInfo running = runningFrom(directory);

Review Comment:
   Fixed in 57b420404b: the launcher remembers the processes it started with 
`--source-dir` (a map from the real path of the directory to the 
`ProcessHandle`). The guard returns `status: starting` with the pid while that 
process is alive and has no status file yet. The check and the start happen 
under one lock, so two calls in flight do not both start a copy.
   
   _Claude Code on behalf of davsclaus_



##########
dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ai/IntegrationLauncher.java:
##########
@@ -72,6 +76,22 @@ public static JsonObject run(Path directory, List<String> 
files, String name, bo
             return result;
         }
         result.put("directory", directory.toString());
+        if (sourceDir) {
+            // the whole directory is the app: one already running from it is 
that app, and a second copy only fights
+            // it for ports and files and makes its name ambiguous to the 
other tools
+            RuntimeHelper.ProcessInfo running = runningFrom(directory);
+            if (running != null) {
+                String runningName = running.contextName() != null && 
!running.contextName().isBlank()
+                        ? running.contextName() : running.name();
+                result.put("status", "running");
+                result.put("pid", running.pid());
+                result.put("name", runningName);
+                result.put("message", runningName + " (pid " + running.pid() + 
") already runs from this directory;"
+                                      + " a second copy was not started. In 
dev mode a changed or added file is reloaded;"
+                                      + " camel_control restart restarts it, 
for example after adding a Java class.");

Review Comment:
   Fixed in 57b420404b: the guard reads the process arguments. With 
`--source-dir` and `--dev` it says an added file is reloaded and restart picks 
up a Java class; with `--source-dir` and no dev mode it says restart picks up 
the change; and an integration started with its own files is reported as such, 
with the advice to stop it and run the whole directory. It is still returned 
rather than starting a second copy next to it. The guard test checks that an 
app without `--source-dir` (the test JVM) is not said to reload added files.
   
   _Claude Code on behalf of davsclaus_



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to