davsclaus commented on code in PR #27927:
URL: https://github.com/apache/camel/pull/27927#discussion_r4289875166
##########
dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/RestartProcess.java:
##########
@@ -99,40 +93,93 @@ public Integer doCall() throws Exception {
}
if (cmd.isEmpty()) {
- printer().println("Cannot restart: command line not available for
PID " + pid);
- return 1;
+ throw CliException.failure("Cannot restart: command line not
available for PID " + pid);
}
- // stop the process gracefully
- printer().println("Stopping Camel integration: " + displayName + "
(PID: " + pid + ")");
- ph.destroy();
-
- // wait for termination
- CompletableFuture<ProcessHandle> exitFuture =
ph.onExit().toCompletableFuture();
- try {
- exitFuture.get(10, TimeUnit.SECONDS);
- } catch (Exception e) {
- printer().println("Graceful shutdown timed out, force killing...");
- ph.destroyForcibly();
- Thread.sleep(500);
- }
+ stop(ph, displayName);
- // re-launch
+ // re-launch, with its output in a log file that stays (the path is
printed)
ProcessBuilder pb = new ProcessBuilder(cmd);
if (directory != null) {
pb.directory(new File(directory));
}
pb.redirectErrorStream(true);
- Path outputFile = Files.createTempFile("camel-restart-", ".log");
- outputFile.toFile().deleteOnExit();
- pb.redirectOutput(outputFile.toFile());
- Process process = pb.start();
-
- printer().println("Restarted Camel integration: " + displayName + "
(PID: " + process.pid() + ")");
+ Path log = Files.createTempFile(CommandLineHelper.getCamelDir(),
"restart-" + pid + "-", ".log");
Review Comment:
Right, in this PR alone the restart logs pile up. The next PR of this series
(CAMEL-25397, `camel run --background`) gives them a lifecycle: the log of an
integration in the background becomes `~/.camel/<pid>-run.log`
(`BackgroundLog`), `camel restart` uses it for the new integration and removes
the log of the old one, `camel stop` removes it once the integration has
exited, and `camel dirty` removes the log of an integration that is gone.
Deleting it after a successful start is not an option: the restarted
integration keeps writing its output there while it runs. So no change here; it
is solved one PR later.
_Claude Code on behalf of davsclaus_
##########
dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/RestartProcess.java:
##########
@@ -99,40 +93,93 @@ public Integer doCall() throws Exception {
}
if (cmd.isEmpty()) {
- printer().println("Cannot restart: command line not available for
PID " + pid);
- return 1;
+ throw CliException.failure("Cannot restart: command line not
available for PID " + pid);
}
- // stop the process gracefully
- printer().println("Stopping Camel integration: " + displayName + "
(PID: " + pid + ")");
- ph.destroy();
-
- // wait for termination
- CompletableFuture<ProcessHandle> exitFuture =
ph.onExit().toCompletableFuture();
- try {
- exitFuture.get(10, TimeUnit.SECONDS);
- } catch (Exception e) {
- printer().println("Graceful shutdown timed out, force killing...");
- ph.destroyForcibly();
- Thread.sleep(500);
- }
+ stop(ph, displayName);
- // re-launch
+ // re-launch, with its output in a log file that stays (the path is
printed)
ProcessBuilder pb = new ProcessBuilder(cmd);
if (directory != null) {
pb.directory(new File(directory));
}
pb.redirectErrorStream(true);
- Path outputFile = Files.createTempFile("camel-restart-", ".log");
- outputFile.toFile().deleteOnExit();
- pb.redirectOutput(outputFile.toFile());
- Process process = pb.start();
-
- printer().println("Restarted Camel integration: " + displayName + "
(PID: " + process.pid() + ")");
+ Path log = Files.createTempFile(CommandLineHelper.getCamelDir(),
"restart-" + pid + "-", ".log");
+ pb.redirectOutput(log.toFile());
+ Process started = pb.start();
+ awaitStarted(started, displayName, log);
+ printer().println("Restarted Camel integration: " + displayName + "
(PID: " + started.pid() + ")");
+ printer().println("Log: " + log);
return 0;
}
+ /**
+ * Stops the integration like camel stop does, and terminates it when it
does not stop in time: the old one must be
+ * gone before the new one starts.
+ */
+ private void stop(ProcessHandle ph, String displayName) {
+ long pid = ph.pid();
+ printer().println("Stopping Camel integration: " + displayName + "
(PID: " + pid + ")");
+ Path pidFile =
CommandLineHelper.getCamelDir().resolve(Long.toString(pid));
+ if (Files.exists(pidFile)) {
+ PathUtils.deleteFile(pidFile);
+ } else {
+ ph.destroy();
+ }
+ if (StopProcess.awaitExit(pid, System.currentTimeMillis() + timeout)) {
+ return;
+ }
+ printer().printWarn("Camel integration (PID: " + pid + ") did not stop
within "
+ + TimeUtils.printDuration(timeout) + ";
terminating it");
+ ph.destroy();
+ if (StopProcess.awaitExit(pid, System.currentTimeMillis() + 10000)) {
+ return;
+ }
+ ph.destroyForcibly();
+ if (!StopProcess.awaitExit(pid, System.currentTimeMillis() + 5000)) {
+ throw CliException.timeout("Camel integration (PID: " + pid + ")
did not stop, so it is not restarted");
+ }
+ }
+
+ /**
+ * Waits until the new integration has started.
+ *
+ * @throws CliException with exit code 1 when it stopped right away, or
124 when it did not start in time (it is
+ * left running)
+ */
+ private void awaitStarted(Process started, String displayName, Path log)
throws Exception {
+ long deadline = System.currentTimeMillis() + timeout;
+ while (System.currentTimeMillis() < deadline) {
+ if (!started.isAlive()) {
+ printer().printDiagnostic(tail(log, 20));
+ throw CliException.failure("Camel integration " + displayName
+ " stopped right after the restart (exit code "
+ + started.exitValue() + "); the log
is in " + log);
+ }
+ JsonObject status = loadStatus(started.pid());
+ if (status != null && status.get("context") instanceof JsonObject
context
+ && context.getIntegerOrDefault("phase", 0) == STARTED) {
Review Comment:
Keeping `== 5` on purpose: the phases above 5 are suspending (6), suspended
(7), terminating (8) and terminated (9) (see
`CamelCommandHelper.extractState`), so `>= 5` would report an integration that
is shutting down right after the restart as started.
_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]