-
Notifications
You must be signed in to change notification settings - Fork 1.1k
[IOTDB-17179] CLI: support automatic reconnection when connection is lost #17181
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -51,6 +51,35 @@ public class Cli extends AbstractCli { | |||||||
| // TODO: Make non-static | ||||||||
| private static final Properties info = new Properties(); | ||||||||
|
|
||||||||
| /** Number of reconnection attempts when connection is lost during interactive session. */ | ||||||||
| private static final int RECONNECT_RETRY_NUM = 3; | ||||||||
|
|
||||||||
| /** Delay in ms between reconnection attempts. */ | ||||||||
| private static final long RECONNECT_RETRY_INTERVAL_MS = 1000; | ||||||||
|
|
||||||||
| /** Result of reading and processing one line; used to support reconnection. */ | ||||||||
| private static class ReadLineResult { | ||||||||
| final boolean stop; | ||||||||
| final String failedCommand; | ||||||||
|
|
||||||||
| ReadLineResult(boolean stop, String failedCommand) { | ||||||||
| this.stop = stop; | ||||||||
| this.failedCommand = failedCommand; | ||||||||
| } | ||||||||
|
|
||||||||
| static ReadLineResult continueLoop() { | ||||||||
| return new ReadLineResult(false, null); | ||||||||
| } | ||||||||
|
|
||||||||
| static ReadLineResult stopLoop() { | ||||||||
| return new ReadLineResult(true, null); | ||||||||
| } | ||||||||
|
|
||||||||
| static ReadLineResult reconnectAndRetry(String command) { | ||||||||
| return new ReadLineResult(false, command); | ||||||||
| } | ||||||||
| } | ||||||||
|
|
||||||||
| /** | ||||||||
| * IoTDB Client main function. | ||||||||
| * | ||||||||
|
|
@@ -155,6 +184,29 @@ private static boolean parseCommandLine( | |||||||
| return true; | ||||||||
| } | ||||||||
|
|
||||||||
| private static IoTDBConnection openConnection() throws SQLException { | ||||||||
| return (IoTDBConnection) | ||||||||
| DriverManager.getConnection(Config.IOTDB_URL_PREFIX + host + ":" + port + "/", info); | ||||||||
| } | ||||||||
|
|
||||||||
| private static void setupConnection(IoTDBConnection connection) | ||||||||
| throws java.sql.SQLException, org.apache.thrift.TException { | ||||||||
| connection.setQueryTimeout(queryTimeout); | ||||||||
| properties = connection.getServerProperties(); | ||||||||
|
||||||||
| properties = connection.getServerProperties(); | |
| properties = connection.getServerProperties(); | |
| AGGREGRATE_TIME_LIST.clear(); |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test is always true, because of this condition.
Test is always true, because of this condition.
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reconnect retry try { connection = openConnection(); setupConnection(connection); ... } can throw TException from setupConnection(), but the retry loop only catches SQLException. This means some connection-loss cases can bypass the reconnect logic and bubble out immediately. Suggestion: include TException (or a common supertype) in the reconnect-attempt catch and handle it as a reconnect failure (with the same retry/backoff), while still distinguishing non-connection SQL errors from command execution.
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the reconnect-and-retry path, the return value of processCommand(...) is ignored. If the retried input contains an exit/quit statement (or otherwise returns false), the CLI will continue the main loop instead of stopping as it normally would. Suggestion: capture the boolean return from processCommand and convert it into a result.stop / break out of the outer loop when it indicates the user requested exit.
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the reconnect loop, any SQLException thrown while retrying the failed command is treated as a reconnect failure. This can incorrectly trigger further reconnect attempts (and eventually exit with "Could not reconnect") for non-connection SQL errors (e.g., syntax/permission errors) that happen after the reconnect succeeds. Suggestion: only retry when isConnectionRelated(e) is true; otherwise report the SQL error from the retried command and continue the main loop (or stop) without attempting further reconnects.
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On reconnect attempts, if openConnection() succeeds but setupConnection() or processCommand() throws, the newly created connection is not closed before the next attempt (the variable is overwritten on the next iteration). This can leak sockets/sessions across retries. Suggestion: in the catch path, call closeConnectionQuietly(connection) and set connection = null before continuing to the next attempt.
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reconnection trigger/loop is a significant behavior change but there are no unit tests exercising it (e.g., simulating a connection-related SQLException from processCommand, verifying retry count/backoff, and ensuring non-connection SQLExceptions do not trigger reconnect or an incorrect "Could not reconnect" exit). Consider adding focused tests around this new flow to prevent regressions.
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a connection-related SQLException occurs, the CLI retries the entire raw input line s. If the line contains multiple statements separated by ;, some statements may already have executed successfully before the failure, and retrying the whole line can re-run those statements (duplicate writes / side effects). Suggestion: either only retry the specific statement that failed (track progress inside processCommand), or disable auto-retry for multi-statement input and ask the user to rerun manually.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
executeQueryprints "Reconnected, but the previous command could not be completed..." for session/statement-state errors, but this method cannot know whether a reconnect actually happened. If the same server-side error occurs without any reconnect, this message is misleading. Suggestion: make the message not assume reconnection (e.g., "Session state was reset..."), or only print this in the reconnect-and-retry path where reconnection is known to have occurred.