From f7735b573c1aca65c53eba823dd8ae74d3cd2c4e Mon Sep 17 00:00:00 2001 From: Steven Hawkins Date: Mon, 3 Nov 2025 06:37:13 -0500 Subject: [PATCH] fix: removing the fast start optimization (#43686) * fix: removing the fast start optimization closes: #38790 #42960 Signed-off-by: Steve Hawkins * updating the docs based upon a review comment Signed-off-by: Steve Hawkins --------- Signed-off-by: Steve Hawkins --- docs/guides/server/configuration.adoc | 4 +--- .../keycloak/quarkus/runtime/KeycloakMain.java | 10 ---------- .../keycloak/quarkus/runtime/cli/Picocli.java | 7 +++++++ .../runtime/cli/command/HelpAllMixin.java | 3 --- .../runtime/cli/command/ImportRealmMixin.java | 3 --- .../quarkus/runtime/cli/command/Start.java | 17 ----------------- .../quarkus/runtime/cli/PicocliTest.java | 2 +- 7 files changed, 9 insertions(+), 37 deletions(-) diff --git a/docs/guides/server/configuration.adoc b/docs/guides/server/configuration.adoc index 295564a29a5..ffe4f25be2f 100644 --- a/docs/guides/server/configuration.adoc +++ b/docs/guides/server/configuration.adoc @@ -264,7 +264,7 @@ The `--optimized` parameter tells {project_name} to assume a pre-built, already You can enter all configuration options at startup; these options are the ones in <@links.server id="all-config"/> that are **not** marked with a tool icon. * If a build option is found at startup with a value that is equal to the value used when entering the `build`, that option gets silently ignored when you use the `--optimized` parameter. -* If that option has a different value than the value used when a build was entered, a warning appears in the logs and the previously built value is used. For this value to take effect, run a new `build` before starting. +* If that option has a different value than the value used when a build was entered, an error occurs. For this value to take effect, run a new `build` before starting. .Create an optimized build @@ -289,8 +289,6 @@ https-certificate-file + <@kc.start parameters="--optimized"/> -You can achieve most optimizations to startup and runtime behavior by using the `build` command. Also, by using the `keycloak.conf` file as a configuration source, you avoid some steps at startup that would otherwise require command line parameters, such as initializing the CLI itself. As a result, the server starts up even faster. - == Using system variables in the realm configuration Some of the realm capabilities allow administrators to reference system variables such as environment variables and system properties when configuring diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/KeycloakMain.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/KeycloakMain.java index 0a24f889a8b..d72001ae711 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/KeycloakMain.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/KeycloakMain.java @@ -20,7 +20,6 @@ package org.keycloak.quarkus.runtime; import static org.keycloak.quarkus.runtime.Environment.getKeycloakModeFromProfile; import static org.keycloak.quarkus.runtime.Environment.isNonServerMode; import static org.keycloak.quarkus.runtime.Environment.isTestLaunchMode; -import static org.keycloak.quarkus.runtime.cli.command.AbstractAutoBuildCommand.OPTIMIZED_BUILD_OPTION_LONG; import java.util.ArrayList; import java.util.List; @@ -45,7 +44,6 @@ import org.keycloak.quarkus.runtime.cli.Picocli; import org.keycloak.common.Version; import org.keycloak.quarkus.runtime.cli.command.AbstractNonServerCommand; import org.keycloak.quarkus.runtime.cli.command.DryRunMixin; -import org.keycloak.quarkus.runtime.cli.command.Start; import io.quarkus.runtime.QuarkusApplication; import io.quarkus.runtime.annotations.QuarkusMain; @@ -100,9 +98,6 @@ public class KeycloakMain implements QuarkusApplication { cliArgs = new ArrayList<>(cliArgs); // default to show help message cliArgs.add("-h"); - } else if (isFastStart(cliArgs)) { // fast path for starting the server without bootstrapping CLI - Start.fastStart(picocli, Boolean.valueOf(System.getenv().get(DryRunMixin.KC_DRY_RUN_ENV))); - return; } // parse arguments and execute any of the configured commands @@ -128,11 +123,6 @@ public class KeycloakMain implements QuarkusApplication { } } - private static boolean isFastStart(List cliArgs) { - // 'start --optimized' should start the server without parsing CLI - return cliArgs.size() == 2 && cliArgs.get(0).equals(Start.NAME) && cliArgs.stream().anyMatch(OPTIMIZED_BUILD_OPTION_LONG::equals); - } - public static void start(Picocli picocli, AbstractNonServerCommand command, ExecutionExceptionHandler errorHandler) { COMMAND = command; // it would be nice to not do this statically - start quarkus with an instance of KeycloakMain, rather than a class for example try { diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/Picocli.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/Picocli.java index b4582c0bd6b..0e2fdd4de15 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/Picocli.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/Picocli.java @@ -170,6 +170,13 @@ public class Picocli { addCommandOptions(cliArgs, cl); } + // ParseResult retain memory. Clear it, so it's not on the stack while the command runs + result = null; + + // there's another ParseResult being created under the covers here. + // to reuse the previous result either means we need to duplicate the logic in the execute method + // or refactor the above logic so that it happens in the command logic + // We could also reduce the memory footprint of the ParseResult, but that looks a little hackish int exitCode = cmd.execute(argArray); exit(exitCode); diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/HelpAllMixin.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/HelpAllMixin.java index 40c30750a05..c8382069383 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/HelpAllMixin.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/HelpAllMixin.java @@ -25,9 +25,6 @@ public final class HelpAllMixin { public static final String HELP_ALL_OPTION = "--help-all"; - @CommandLine.Spec - private CommandLine.Model.CommandSpec spec; - @CommandLine.Option(names = {HELP_ALL_OPTION}, usageHelp = true, description = "This same help message but with additional options.") public void setHelpAll(boolean allOptions) { Help.setAllOptions(true); diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/ImportRealmMixin.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/ImportRealmMixin.java index f6ff8cef0e7..e62cd5e700e 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/ImportRealmMixin.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/ImportRealmMixin.java @@ -30,9 +30,6 @@ public final class ImportRealmMixin { public static final String IMPORT_REALM = "--import-realm"; - @CommandLine.Spec - private CommandLine.Model.CommandSpec spec; - @CommandLine.Option(names = IMPORT_REALM, description = "Import realms during startup by reading any realm configuration file from the 'data/import' directory.", paramLabel = NO_PARAM_LABEL, diff --git a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/Start.java b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/Start.java index 671c23df263..d82fa5201a4 100644 --- a/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/Start.java +++ b/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/Start.java @@ -19,12 +19,8 @@ package org.keycloak.quarkus.runtime.cli.command; import static org.keycloak.quarkus.runtime.cli.command.AbstractAutoBuildCommand.OPTIMIZED_BUILD_OPTION_LONG; -import java.util.List; - import org.keycloak.quarkus.runtime.Environment; import org.keycloak.quarkus.runtime.Messages; -import org.keycloak.common.profile.ProfileException; -import org.keycloak.quarkus.runtime.cli.Picocli; import org.keycloak.quarkus.runtime.cli.PropertyException; import picocli.CommandLine; @@ -65,19 +61,6 @@ public final class Start extends AbstractAutoBuildCommand { return NAME; } - public static void fastStart(Picocli picocli, boolean dryRun) { - try { - Start start = new Start(); - start.optimizedMixin.optimized = true; - start.dryRunMixin.dryRun = dryRun; - start.setPicocli(picocli); - picocli.initConfig(List.of(OPTIMIZED_BUILD_OPTION_LONG), start); - picocli.exit(start.call()); - } catch (PropertyException | ProfileException e) { - picocli.usageException(e.getMessage(), e.getCause()); - } - } - @Override public boolean isServing() { return true; diff --git a/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/cli/PicocliTest.java b/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/cli/PicocliTest.java index 209a29c3c65..094f7ecb2f2 100644 --- a/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/cli/PicocliTest.java +++ b/quarkus/runtime/src/test/java/org/keycloak/quarkus/runtime/cli/PicocliTest.java @@ -474,7 +474,7 @@ public class PicocliTest extends AbstractConfigurationTest { } @Test - public void fastStartOptimizedSucceeds() { + public void startOptimizedSucceeds() { build("build", "--db=dev-file"); System.setProperty("kc.http-enabled", "true");