This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch fix/CAMEL-25784
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/fix/CAMEL-25784 by this push:
new 777f82f9b41f CAMEL-25784: compare the times of the files for the log
of a killed process, and keep no stale info after a failed keep
777f82f9b41f is described below
commit 777f82f9b41f6a2d0c9431dc83f5238309a80ca3
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Oct 19 13:28:21 2026 +0200
CAMEL-25784: compare the times of the files for the log of a killed
process, and keep no stale info after a failed keep
From the review: the log of a killed process was compared with when the
previous run ended (the clock of the JVM) instead of the time of its log
(the
clock of the file system, which a network file system has of its own). And a
keep that failed (such as on a full disk) left what was kept about the run
before next to the log of this one: that file now goes first.
Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01STT6whBgK1AqsSsUKrnE8m
---
.../jbang/core/commands/action/CamelLogAction.java | 2 +-
.../camel/dsl/jbang/core/common/PreviousRun.java | 7 ++++-
.../dsl/jbang/core/common/PreviousRunTest.java | 35 ++++++++++++++++++++++
3 files changed, 42 insertions(+), 2 deletions(-)
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelLogAction.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelLogAction.java
index e87f8f9ee84e..f10009dbeb5d 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelLogAction.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/action/CamelLogAction.java
@@ -267,7 +267,7 @@ public class CamelLogAction extends ActionBaseCommand {
private void findRunning() {
try {
if (findProcesses(name).isEmpty()) {
- // nothing runs
+ // nothing runs: the newest previous run (findAll is newest
first)
List<PreviousRun.Info> found = PreviousRun.findAll();
if (!found.isEmpty()) {
printer().printTip(previousRunHint(found.get(0)));
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/PreviousRun.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/PreviousRun.java
index 134e5621c334..9415bc62eecf 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/PreviousRun.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/PreviousRun.java
@@ -164,6 +164,9 @@ public final class PreviousRun {
String file = fileName(info.name());
Path target = dir.resolve(file + LOG_SUFFIX);
try {
+ // what was kept about the run before goes first, so a keep that
fails (such as on a full disk) does not
+ // leave it next to the log of this run
+ Files.deleteIfExists(dir.resolve(file + INFO_SUFFIX));
if (Files.size(log) > MAX_SIZE || !move(log, target)) {
copyEnd(log, target, MAX_SIZE);
try {
@@ -285,7 +288,9 @@ public final class PreviousRun {
? context.getString("name") : null;
if (name != null && !name.isBlank()) {
Info before =
read(CommandLineHelper.getCamelDir().resolve(fileName(name) + INFO_SUFFIX));
- if (before == null || before.ended() < modified) {
+ // the time of the kept log, not when its run ended, so both
times come from the file system (a
+ // network file system has a clock of its own)
+ if (before == null || before.log().toFile().lastModified() <
modified) {
String directory = status.get("runtime") instanceof
JsonObject runtime
? runtime.getString("directory") : null;
keep(f.toPath(), new Info(name, pid, directory, 0,
modified, null, null, GONE, null));
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/common/PreviousRunTest.java
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/common/PreviousRunTest.java
index 981d81b14d11..7dfe2d5b71cc 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/common/PreviousRunTest.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/common/PreviousRunTest.java
@@ -22,6 +22,7 @@ import java.nio.file.attribute.FileTime;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.List;
+import java.util.concurrent.TimeUnit;
import org.apache.camel.util.json.JsonObject;
import org.junit.jupiter.api.AfterEach;
@@ -160,6 +161,40 @@ class PreviousRunTest {
assertThat(old).doesNotExist();
}
+ @Test
+ void theLogOfAKilledProcessIsComparedByTheTimesOfTheFiles() throws
Exception {
+ // a run kept by a JVM whose clock is a day ahead of the file system
(a network file system)
+ long ahead = System.currentTimeMillis() + TimeUnit.DAYS.toMillis(1);
+ Path kept = PreviousRun.keep(writeLog("123.log", "older run"),
+ new PreviousRun.Info("orders", 123, null, 0, ahead, 0, null,
null, null));
+ Files.setLastModifiedTime(kept, FileTime.from(Instant.now().minus(2,
ChronoUnit.HOURS)));
+ Path killed = writeLog(GONE_PID + ".log", "newer run, killed");
+ Files.setLastModifiedTime(killed, FileTime.from(Instant.now().minus(1,
ChronoUnit.HOURS)));
+ writeStatus(GONE_PID, "orders");
+
+ PreviousRun.Info info = only(PreviousRun.find("orders"));
+
+ assertThat(info.pid()).isEqualTo(GONE_PID);
+ assertThat(Files.readAllLines(info.log())).containsExactly("newer run,
killed");
+ }
+
+ @Test
+ void aKeepThatFailsLeavesNoInfoOfTheRunBefore() throws Exception {
+ PreviousRun.keep(writeLog("123.log", "first run"), "orders", 123, 0,
null);
+ // the log cannot be written: a directory that is not empty has its
name
+ Path kept = camelDir.resolve("orders-previous.log");
+ Files.delete(kept);
+ Files.createDirectories(kept.resolve("in-the-way"));
+ Path log = writeLog("456.log", "second run");
+
+ assertThat(PreviousRun.keep(log, "orders", 456, 70, "boom")).isNull();
+
+ // what was kept about the first run is not left next to something
else, and the log of the second run stays
+ assertThat(camelDir.resolve("orders-previous.json")).doesNotExist();
+ assertThat(PreviousRun.find("orders")).isEmpty();
+ assertThat(log).exists();
+ }
+
@Test
void theLogOfAProcessWithoutNameIsRemovedAfterADay() throws Exception {
Path old = writeLog(GONE_PID + ".log", "old");