Skip to content

[Improve] add connection check when get connection #7

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

Open
wants to merge 15 commits into
base: master
Choose a base branch
from

Conversation

arvi18
Copy link

@arvi18 arvi18 commented Apr 21, 2025

Summary by CodeRabbit

  • New Features
    • Added runtime connection validation for database, SSH, JMX, Redis, MongoDB, and Redfish connections to ensure only active connections are returned.
  • Bug Fixes
    • Improved error handling when retrieving cached connections by automatically removing invalid connections and cleaning up resources.
  • Tests
    • Updated tests to support the new connection validation logic.

@arvi18
Copy link
Author

arvi18 commented Apr 21, 2025

hi, the connection cache is the underlying code. If it throws an exception, more upper-level code logic should be considered.

Copy link

coderabbitai bot commented Apr 21, 2025

Walkthrough

This update introduces a standardized runtime validation mechanism for connection classes within the collector module. An abstract check() method is added to the base AbstractConnection class, and each concrete connection class (such as JDBC, JMX, MongoDB, Redfish, Redis, and SSH) now implements this method to verify the validity or openness of its underlying resource. The getConnection() methods in these classes are updated to invoke check() before returning the connection, returning null if the check fails. Related error handling and logging are also updated. Tests are adjusted to accommodate the new abstract method.

Changes

File(s) Change Summary
collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/AbstractConnection.java Removed Lombok @Slf4j; added abstract check() method; adjusted close() to use this.closeConnection().
collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/JdbcConnect.java Implemented check() to validate JDBC connection; updated getConnection() to use check().
collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/JmxConnect.java Implemented check() for JMX connection; updated getConnection() to use check().
collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/MongodbConnect.java Implemented check() for MongoDB client; updated getConnection() to use check().
collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/RedfishConnect.java Implemented check() for Redfish session; updated getConnection() to use check().
collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/RedisConnect.java Implemented check() for Redis connection; updated getConnection() to use check().
collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/SshConnect.java Implemented check() for SSH session; updated getConnection() to use check().
collector/src/main/java/org/apache/hertzbeat/collector/collect/redis/RedisCommonCollectImpl.java Refactored connection retrieval to use exception handling for invalid connections and cleanup.
collector/src/test/java/org/apache/hertzbeat/collector/collect/common/cache/CommonCacheTest.java Added empty check() override in test subclass of AbstractConnection to satisfy new abstract method.

Sequence Diagram(s)

sequenceDiagram
    participant Caller
    participant Cache
    participant Connection

    Caller->>Cache: getConnection()
    Cache->>Connection: check()
    alt Connection is valid
        Cache-->>Caller: return connection
    else Connection is invalid
        Cache->>Cache: log error
        Cache-->>Caller: return null
    end
Loading

Poem

In the warren of code, connections abound,
Now each one gets checked before passing around.
If a tunnel is blocked, a log will appear,
And null will be sent—no surprises here!
With checks in each burrow, the system’s robust,
Connections are healthy, in rabbits we trust!
🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@visz11
Copy link
Collaborator

visz11 commented Apr 23, 2025

@coderabbitai full review

Copy link

coderabbitai bot commented Apr 23, 2025

✅ Actions performed

Full review triggered.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (6)
collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/SshConnect.java (1)

41-47: Good implementation of connection validation

The check() method properly verifies that the SSH session is open before it's used, improving connection reliability.

Consider using a more specific exception type rather than generic Exception for better error handling by callers.

@Override
public void check() throws Exception {
    if (!clientSession.isOpen()) {
-        throw new Exception("ssh connection is not open");
+        throw new IllegalStateException("ssh connection is not open");
    }
}
collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/RedfishConnect.java (1)

41-47: Good implementation of connection validation

The check() method properly validates the Redfish connection before use.

Note that this implementation uses RuntimeException while SshConnect uses a checked Exception. Consider standardizing exception types across similar implementations for consistency.

@Override
public void check() throws Exception {
    if (!reddishConnectSession.isOpen()) {
-        throw new RuntimeException("Connection is closed");
+        throw new IllegalStateException("Redfish connection is closed");
    }
}
collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/RedisConnect.java (1)

51-60: Consider enhanced error logging for better troubleshooting

While the error handling works correctly, logging only the error message without the stack trace might make debugging harder in production environments.

        try {
            this.check();
        }
        catch (Exception e) {
-            log.error(e.getMessage());
+            log.error("Redis connection check failed", e);
            return null;
        }
collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/MongodbConnect.java (1)

48-58: Improve error logging and remove unnecessary whitespace

The implementation correctly handles connection validation before returning the client, but could benefit from enhanced error logging and removal of unnecessary whitespace.

    @Override
    public MongoClient getConnection() {
        try {
            this.check();
        }
        catch (Exception e) {
-            log.error(e.getMessage());
+            log.error("MongoDB connection check failed", e);
            return null;
        }
-
        return mongoClient;
    }
collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/JmxConnect.java (1)

51-61: Consider enhanced error logging for better diagnostics

While the implementation works correctly, logging only the error message without the stack trace might make troubleshooting more difficult in production environments.

        try {
            this.check();
        }
        catch (Exception e) {
-            log.error(e.getMessage());
+            log.error("JMX connection check failed", e);
            return null;
        }
collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/JdbcConnect.java (1)

51-61: Consider enhanced error logging for better diagnostics

While the error handling works correctly, logging only the error message without the stack trace might make debugging more challenging.

        try {
            this.check();
        }
        catch (SQLException e) {
-            log.error(e.getMessage());
+            log.error("JDBC connection check failed", e);
            return null;
        }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b02837b and 53ffca0.

📒 Files selected for processing (9)
  • collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/AbstractConnection.java (2 hunks)
  • collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/JdbcConnect.java (2 hunks)
  • collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/JmxConnect.java (1 hunks)
  • collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/MongodbConnect.java (2 hunks)
  • collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/RedfishConnect.java (1 hunks)
  • collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/RedisConnect.java (1 hunks)
  • collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/SshConnect.java (1 hunks)
  • collector/src/main/java/org/apache/hertzbeat/collector/collect/redis/RedisCommonCollectImpl.java (1 hunks)
  • collector/src/test/java/org/apache/hertzbeat/collector/collect/common/cache/CommonCacheTest.java (1 hunks)
🔇 Additional comments (10)
collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/AbstractConnection.java (2)

36-39: Good addition of abstract check() method

Adding this abstract method establishes a consistent validation contract across all connection implementations, ensuring connections are verified before being returned to clients.


43-44: Improved clarity with explicit this reference

Making the call to closeConnection() explicit with this prefix improves code readability and clarity.

collector/src/test/java/org/apache/hertzbeat/collector/collect/common/cache/CommonCacheTest.java (1)

49-51: Appropriate test implementation for abstract method

The empty implementation of the check() method satisfies the new abstract method requirement without changing test behavior.

collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/SshConnect.java (1)

50-58: Proper error handling in getConnection()

Good implementation of try-catch block to handle connection check failures gracefully. Returning null when the connection is invalid allows higher-level code to handle the situation appropriately.

collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/RedfishConnect.java (1)

51-58: Proper error handling in getConnection()

Effective implementation of try-catch pattern to handle connection validation failures gracefully. This approach aligns with the PR objective of improving connection handling.

collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/RedisConnect.java (1)

42-48: Robust connection validation added

The implementation correctly validates that the Redis connection is open before use, throwing a clear RuntimeException when the connection is closed. This is a valuable addition for preventing downstream errors.

collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/MongodbConnect.java (1)

42-46: Effective MongoDB connection validation

The implementation appropriately validates the MongoDB connection by running a ping command on the admin database, which is the standard way to check MongoDB connection health.

collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/JmxConnect.java (1)

43-49: Good JMX connection validation approach

The implementation validates the JMX connection by checking if the connection ID is empty, which is appropriate for detecting closed JMX connections.

collector/src/main/java/org/apache/hertzbeat/collector/collect/common/cache/JdbcConnect.java (1)

43-49: Proper JDBC connection validation

The implementation correctly validates that the JDBC connection is not closed before use, throwing a SQLException with a clear message when the connection is invalid.

collector/src/main/java/org/apache/hertzbeat/collector/collect/redis/RedisCommonCollectImpl.java (1)

239-259: Improved error handling with connection validation.

The refactored getStatefulConnection method now properly handles invalid Redis connections by leveraging the new check() mechanism implemented in RedisConnect. This approach correctly catches exceptions from invalid connections, logs the issue, cleans up resources, and removes the invalid connection from the cache.

However, I have a few suggestions to further enhance the implementation:

  1. Consider catching more specific exceptions rather than the broad RuntimeException
  2. Include the full stack trace in the first log message to aid debugging
  3. Consider adding a comment explaining the relationship with the new check() method
            try {
                return redisConnect.getConnection();
-            } catch (RuntimeException e) {
-                log.info("The Redis connection from cache is invalid, closing and removing: {}", e.getMessage());
+            } catch (RuntimeException e) {
+                // RedisConnect.check() throws RuntimeException for invalid connections
+                log.info("The Redis connection from cache is invalid, closing and removing: {}", e.getMessage(), e);
                try {
                    redisConnect.getConnection().closeAsync();
                } catch (Exception closeException) {
                    log.info("Error closing Redis connection: {}", closeException.getMessage());
                }
                connectionCommonCache.removeCache(identifier);
            }

Comment on lines 52 to 61
public Connection getConnection() {

try {
this.check();
}
catch (SQLException e) {
log.error(e.getMessage());
return null;
}
return connection;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Consider handling null returns consistently across all connection classes

All connection classes now return null when validation fails. Ensure that callers are aware of this possibility and check for null before using the connection to prevent NullPointerExceptions.


🏁 Script executed:

#!/bin/bash
# Find places in the codebase where getConnection() is called without null check

echo "Searching for potential NullPointerException risks in getConnection() usages..."

# Search for patterns where getConnection() is called without null checks
rg -U "(\w+\.getConnection\(\)(?!\s*[!=]=\s*null|\s*\?\?|\s*\|\||\s*&&|\s*!=\s*null))" --type java

Length of output: 574


🏁 Script executed:

#!/bin/bash
# List every occurrence of getConnection() in Java source files
echo "Listing all usages of getConnection() in Java files..."
rg --type java "getConnection\s*\(\)" -n

Length of output: 3821


#!/bin/bash
set -e

echo "=== Context in JdbcCommonCollect.java around line 148 ==="
sed -n '135,165p' collector/src/main/java/org/apache/hertzbeat/collector/collect/database/JdbcCommonCollect.java

echo -e "\n=== Context in MongodbSingleCollectImpl.java around lines 170-210 ==="
sed -n '170,210p' collector/src/main/java/org/apache/hertzbeat/collector/collect/mongodb/MongodbSingleCollectImpl.java

echo -e "\n=== Context in JmxCollectImpl.java around lines 175-215 ==="
sed -n '175,215p' collector/src/main/java/org/apache/hertzbeat/collector/collect/jmx/JmxCollectImpl.java

echo -e "\n=== Context in SshCollectImpl.java around lines 280-330 ==="
sed -n '280,330p' collector/src/main/java/org/apache/hertzbeat/collector/collect/ssh/SshCollectImpl.java

echo -e "\n=== Context in RedfishCollectImpl.java around lines 90-120 ==="
sed -n '90,120p' collector/src/main/java/org/apache/hertzbeat/collector/collect/redfish/RedfishCollectImpl.java

echo -e "\n=== Context in RedisCommonCollectImpl.java around lines 235-270 ==="
sed -n '235,270p' collector/src/main/java/org/apache/hertzbeat/collector/collect/redis/RedisCommonCollectImpl.java

Add null‑checks for getConnection() return values

The new behavior in all *Connect.getConnection() implementations is to return null on validation failure. Callers must guard against a null connection to avoid NullPointerExceptions. Please update the following usages to check for null before invoking methods on the returned connection (or consider throwing a checked exception / returning Optional<T> instead):

• collector/src/main/java/org/apache/hertzbeat/collector/collect/database/JdbcCommonCollect.java:148

// before
statement = jdbcConnect.getConnection().createStatement();

// guard
Connection conn = jdbcConnect.getConnection();
if (conn == null) { /* handle error */ }
statement = conn.createStatement();

• collector/src/main/java/org/apache/hertzbeat/collector/collect/redis/RedisCommonCollectImpl.java

  • Line 246: return redisConnect.getConnection();
  • Line 250: redisConnect.getConnection().closeAsync();

• collector/src/main/java/org/apache/hertzbeat/collector/collect/mongodb/MongodbSingleCollectImpl.java:188

MongoClient client = mongodbConnect.getConnection();
// add null-check here

• collector/src/main/java/org/apache/hertzbeat/collector/collect/jmx/JmxCollectImpl.java:191

JMXConnector conn = jmxConnect.getConnection();
// add null-check here

• collector/src/main/java/org/apache/hertzbeat/collector/collect/ssh/SshCollectImpl.java:304

ClientSession session = cacheOption.get().getConnection();
// add null-check here

• collector/src/main/java/org/apache/hertzbeat/collector/collect/redfish/RedfishCollectImpl.java:105

ConnectSession session = redfishConnect.getConnection();
// add null-check here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants