This is an automated email from the ASF dual-hosted git repository.
apkhmv pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new b88e8eaa86a IGNITE-27530 Optimize CLI startup time for non-interactive
commands (#7382)
b88e8eaa86a is described below
commit b88e8eaa86a181db6045409551700713a58cf3c6
Author: Aleksandr Pakhomov <[email protected]>
AuthorDate: Tue Jan 13 13:44:23 2026 +0300
IGNITE-27530 Optimize CLI startup time for non-interactive commands (#7382)
Co-authored-by: Claude Opus 4.5 <[email protected]>
---
CLAUDE.md | 8 ++++++
.../java/org/apache/ignite/internal/cli/Main.java | 32 ++++++++++++++++------
.../cli/commands/connect/ConnectCommand.java | 4 ++-
packaging/cli/build.gradle | 8 +++++-
packaging/cli/start.sh | 3 ++
5 files changed, 44 insertions(+), 11 deletions(-)
diff --git a/CLAUDE.md b/CLAUDE.md
index eb3496617b3..972fe4bc91b 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -106,6 +106,14 @@ Run checkstyle and PMD on the modified module(s):
./gradlew :ignite-<module>:checkstyleMain :ignite-<module>:checkstyleTest
:ignite-<module>:pmdMain :ignite-<module>:pmdTest
```
+Run IDEA inspections on the modified module(s):
+```bash
+idea inspect . .idea/inspectionProfiles/Project_Default.xml /tmp/results -d
modules/<module>
+```
+Notes:
+- IntelliJ IDEA must be closed for command-line inspections to work.
+- If `idea` command is not available, ask the user to install it via: **Tools
> Create Command-line Launcher** in IntelliJ IDEA.
+
### Git Push
**Never use `git push` without specifying the target branch.** Always push
explicitly:
```bash
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/Main.java
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/Main.java
index 7ab70ad6f18..5625b842840 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/Main.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/Main.java
@@ -53,25 +53,39 @@ public class Main {
public static void main(String[] args) {
initJavaLoggerProps();
+ // Determine if we're entering interactive REPL mode.
+ // REPL mode is only entered when no args AND stdin/stdout are
terminals.
+ boolean interactiveMode = args.length == 0 && isatty();
+
int exitCode = 0;
ApplicationContextBuilder builder =
ApplicationContext.builder(Environment.CLI).deduceEnvironment(false);
try (MicronautFactory micronautFactory = new
MicronautFactory(builder.start())) {
- AnsiConsole.systemInstall();
- initReplExecutor(micronautFactory);
- initQuestionAsker(micronautFactory);
- if (args.length != 0 || !isatty()) { // do not enter REPL if input
or output is redirected
+ if (interactiveMode) {
+ // REPL mode: full initialization with Jansi ANSI console and
JLine terminal.
+ AnsiConsole.systemInstall();
+ initReplExecutor(micronautFactory);
+ initQuestionAsker(micronautFactory);
+ enterRepl(micronautFactory);
+ } else {
+ // Non-interactive mode: skip JLine terminal initialization
for faster startup.
+ // Only install ANSI console if stdout is a terminal (for
colored output).
+ if (isatty()) {
+ AnsiConsole.systemInstall();
+ }
try {
exitCode = executeCommand(args, micronautFactory);
} catch (Exception e) {
- System.err.println("Error occurred during command
execution");
+ System.err.println("Error occurred during command
execution: " + e.getMessage());
+ exitCode = 1;
}
- } else {
- enterRepl(micronautFactory);
}
} catch (Exception e) {
- System.err.println("Error occurred during initialization");
+ System.err.println("Error occurred during initialization: " +
e.getMessage());
+ exitCode = 1;
} finally {
- AnsiConsole.systemUninstall();
+ if (AnsiConsole.isInstalled()) {
+ AnsiConsole.systemUninstall();
+ }
}
System.exit(exitCode);
}
diff --git
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/connect/ConnectCommand.java
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/connect/ConnectCommand.java
index 0cc8e01fad3..055ed7be933 100644
---
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/connect/ConnectCommand.java
+++
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/connect/ConnectCommand.java
@@ -21,6 +21,7 @@ import static
org.apache.ignite.internal.cli.commands.Options.Constants.CLUSTER_
import static
org.apache.ignite.internal.cli.commands.Options.Constants.NODE_URL_OPTION_DESC;
import jakarta.inject.Inject;
+import jakarta.inject.Provider;
import java.net.URL;
import java.util.concurrent.Callable;
import org.apache.ignite.internal.cli.ReplManager;
@@ -50,11 +51,12 @@ public class ConnectCommand extends BaseCommand implements
Callable<Integer> {
private ConnectWizardCall connectCall;
@Inject
- private ReplManager replManager;
+ private Provider<ReplManager> replManagerProvider;
/** {@inheritDoc} */
@Override
public Integer call() {
+ ReplManager replManager = replManagerProvider.get();
// We need to do this before the connect call since it will fire
events even before repl start.
replManager.subscribe();
diff --git a/packaging/cli/build.gradle b/packaging/cli/build.gradle
index d84feda4ac1..835a414ccd6 100644
--- a/packaging/cli/build.gradle
+++ b/packaging/cli/build.gradle
@@ -84,7 +84,13 @@ def cliStartScript = tasks.register('cliStartScript',
CreateStartScripts) {
classpath = files(new File("../lib/*"))
outputDir = file "$buildDir/scripts"
applicationName = 'ignite3'
- defaultJvmOpts += ['--add-opens=java.base/java.lang=ALL-UNNAMED',
'-Xmx256m']
+ defaultJvmOpts += [
+ '--add-opens=java.base/java.lang=ALL-UNNAMED',
+ '--enable-native-access=ALL-UNNAMED',
+ '-Xmx256m',
+ '-XX:TieredStopAtLevel=1',
+ '-XX:+UseSerialGC'
+ ]
}
def windowsCliStartScript = tasks.register('windowsCliStartScript', Copy) {
diff --git a/packaging/cli/start.sh b/packaging/cli/start.sh
index d5085c35f59..dce73fc8ca8 100644
--- a/packaging/cli/start.sh
+++ b/packaging/cli/start.sh
@@ -25,7 +25,10 @@ MAIN_CLASS="@MAIN_CLASS@"
DEFAULT_JVM_OPTS="-Dfile.encoding=UTF-8 \
--add-opens=java.base/java.lang=ALL-UNNAMED \
+ --enable-native-access=ALL-UNNAMED \
-Xmx256m \
+ -XX:TieredStopAtLevel=1 \
+ -XX:+UseSerialGC \
-XX:+HeapDumpOnOutOfMemoryError \
-XX:+ExitOnOutOfMemoryError \
-XX:HeapDumpPath=${LOG_DIR}"