Skip to content
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

Add async cluster support #96

Merged
merged 6 commits into from
Mar 13, 2025
Merged

Add async cluster support #96

merged 6 commits into from
Mar 13, 2025

Conversation

gkorland
Copy link
Contributor

@gkorland gkorland commented Mar 12, 2025

fix #95

Summary by CodeRabbit

  • New Features
    • Introduced advanced support for connecting to Redis clusters with configurable retry attempts, startup nodes, and additional settings for improved distributed database connectivity.
    • Expanded the connection initialization in the FalkorDB class to include new options for cluster configurations, enhancing reliability, flexibility, and performance in distributed environments.
  • Chores
    • Updated .gitignore to include poetry.lock and retain __pycache__.

@gkorland gkorland requested a review from swilly22 March 12, 2025 12:48
Copy link

coderabbitai bot commented Mar 12, 2025

Walkthrough

This pull request introduces cluster connection support for Redis in the asynchronous FalkorDB implementation. A new file, cluster.py, provides functions to check for cluster mode and establish cluster connections with appropriate configuration and error handling. The FalkorDB class is updated to accept additional parameters related to cluster management and conditionally initialize a cluster connection if detected.

Changes

File(s) Change Summary
falkordb/asyncio/cluster.py
falkordb/asyncio/falkordb.py
Added Redis cluster support: Introduced Is_Cluster and Cluster_Conn in the new cluster.py for managing cluster-specific connection parameters and error handling. Updated the FalkorDB __init__ method to accept additional cluster parameters and to conditionally initialize a cluster connection.
.gitignore Added poetry.lock to be ignored by version control and retained the line for __pycache__.

Possibly related PRs

  • Add the rest of redis cluster arguments #60: The changes in the main PR introduce the Cluster_Conn function in falkordb/asyncio/cluster.py, while the retrieved PR modifies the Cluster_Conn function in falkordb/cluster.py, indicating a direct relationship between the two regarding the same function's implementation.
  • Update README.md with Async examples #90: The changes in the main PR are related to the Is_Cluster function, which is also referenced in the retrieved PR's modifications to the FalkorDB class, indicating a connection in functionality.
  • support cluster connection #51: The changes in the main PR are directly related to those in the retrieved PR, as both modify the Is_Cluster and Cluster_Conn functions and involve the FalkorDB class's connection handling for Redis clusters.

Suggested reviewers

  • dudizimber
  • AviAvni

Poem

I'm a rabbit on the run, hopping through the code,
Redis clusters now connect, down each winding road.
With functions sprouting bright and new,
Async wonders come into view.
Here's to cluster dreams in every byte,
Happy coding, and may your paths be light!
🐰✨

Tip

⚡🧪 Multi-step agentic review comment chat (experimental)
  • We're introducing multi-step agentic chat in review comments. This experimental feature enhances review discussions with the CodeRabbit agentic chat by enabling advanced interactions, including the ability to create pull requests directly from comments.
    - To enable this feature, set early_access to true under in the settings.

📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ff0036d and 9059529.

📒 Files selected for processing (1)
  • falkordb/cluster.py (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • falkordb/cluster.py

🪧 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 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.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Hello @gkorland, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

Summary of Changes

This pull request adds support for asynchronous Redis Cluster functionality to the falkordb library. It introduces a new module falkordb/asyncio/cluster.py which contains functions to detect if a connection is a cluster and to create a cluster connection from a standard Redis connection. The changes also modify falkordb/asyncio/falkordb.py to incorporate cluster-specific parameters and logic during initialization, allowing the library to connect to and interact with Redis clusters.

Highlights

  • Async Cluster Support: Adds the ability to connect to and interact with Redis clusters asynchronously.
  • New Cluster Module: Introduces falkordb/asyncio/cluster.py with functions for cluster detection and connection creation.
  • Falkordb Initialization: Modifies falkordb/asyncio/falkordb.py to include cluster-specific parameters and connection logic.

Changelog

  • falkordb/asyncio/cluster.py
    • Created a new module to handle asynchronous Redis Cluster connections.
    • Implemented Is_Cluster function to detect if a connection is a Redis Cluster.
    • Implemented Cluster_Conn function to create a RedisCluster instance from a Redis connection, extracting connection details and setting appropriate cluster parameters.
  • falkordb/asyncio/falkordb.py
    • Imported the new cluster module.
    • Added cluster-specific parameters to the FalkorDB class constructor, including cluster_error_retry_attempts, startup_nodes, require_full_coverage, reinitialize_steps, read_from_replicas, and address_remap.
    • Modified the initialization logic to check if the connection is a cluster using Is_Cluster and, if so, create a RedisCluster connection using Cluster_Conn.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.


In realms of data, where clusters reside,
Async connections, a powerful stride.
FalkorDB awakens, with newfound might,
To weave through the nodes, day and night.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces asynchronous cluster support for FalkorDB, which is a valuable enhancement. The changes involve creating cluster connections from Redis connections and detecting if a connection is a cluster. Overall, the implementation seems reasonable, but there are a few areas that could be improved for clarity and robustness.

Summary of Findings

  • Error Handling in Is_Cluster: The Is_Cluster function does not handle potential exceptions that might occur when calling conn.info(). Adding error handling would make the function more robust.
  • Parameter Handling in Cluster_Conn: The Cluster_Conn function pops parameters from connection_kwargs without checking if they exist. This could lead to errors if the connection does not have these parameters. Consider adding checks or using get with default values.
  • Inconsistent Parameter Passing: In falkordb.py, the ssl parameter is passed directly to Cluster_Conn, but other parameters like retry are not. This inconsistency should be addressed for better code maintainability.

Merge Readiness

The pull request introduces important functionality, but there are a few issues that should be addressed before merging. Specifically, the error handling in Is_Cluster and parameter handling in Cluster_Conn should be improved. Additionally, the parameter passing in falkordb.py should be made consistent. I am unable to approve this pull request, and recommend that others review and approve this code before merging.

Comment on lines 6 to 8
async def Is_Cluster(conn):
info = await conn.info(section="server")
return "redis_mode" in info and info["redis_mode"] == "cluster"

Choose a reason for hiding this comment

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

medium

The Is_Cluster function does not handle potential exceptions that might occur when calling conn.info(). Consider adding a try-except block to catch and log any exceptions, or return a default value (e.g., False) if an error occurs. This will make the function more robust.

    try:
        info = await conn.info(section="server")
        return "redis_mode" in info and info["redis_mode"] == "cluster"
    except Exception:
        return False

Comment on lines +25 to +28
host = connection_kwargs.pop("host")
port = connection_kwargs.pop("port")
username = connection_kwargs.pop("username")
password = connection_kwargs.pop("password")

Choose a reason for hiding this comment

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

medium

The Cluster_Conn function pops parameters from connection_kwargs without checking if they exist. If the connection does not have these parameters, it will raise an exception. Consider using connection_kwargs.get('host') with a default value or checking if the key exists before popping.

    host = connection_kwargs.get("host")
    port = connection_kwargs.get("port")
    username = connection_kwargs.get("username")
    password = connection_kwargs.get("password")

Comment on lines +95 to +103
conn = Cluster_Conn(
conn,
ssl,
cluster_error_retry_attempts,
startup_nodes,
require_full_coverage,
reinitialize_steps,
read_from_replicas,
address_remap,

Choose a reason for hiding this comment

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

medium

The ssl parameter is passed directly to Cluster_Conn, but other parameters like retry are not. To maintain consistency and make the code more maintainable, consider passing all relevant parameters explicitly.

Suggested change
conn = Cluster_Conn(
conn,
ssl,
cluster_error_retry_attempts,
startup_nodes,
require_full_coverage,
reinitialize_steps,
read_from_replicas,
address_remap,
conn = Cluster_Conn(
conn,
ssl,
cluster_error_retry_attempts=cluster_error_retry_attempts,
startup_nodes=startup_nodes,
require_full_coverage=require_full_coverage,
reinitialize_steps=reinitialize_steps,
read_from_replicas=read_from_replicas,
address_remap=address_remap,
)

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

🔭 Outside diff range comments (1)
falkordb/asyncio/falkordb.py (1)

110-142: 🛠️ Refactor suggestion

Add cluster support to the from_url method

The from_url method creates a Redis connection but doesn't check if it's a cluster or handle it appropriately like the __init__ method does. This could lead to inconsistent behavior when connecting through URLs.

def from_url(cls, url: str, **kwargs) -> "FalkorDB":
    """
    Creates a new FalkorDB instance from a URL.

    Args:
        cls: The class itself.
        url (str): The URL.
        kwargs: Additional keyword arguments to pass to the ``DB.from_url`` function.

    Returns:
        DB: A new DB instance.

    Usage example::
    db = FalkorDB.from_url("falkor://[[username]:[password]]@localhost:6379")
    db = FalkorDB.from_url("falkors://[[username]:[password]]@localhost:6379")
    db = FalkorDB.from_url("unix://[username@]/path/to/socket.sock?db=0[&password=password]")
    """

    db = cls()

    # switch from redis:// to falkordb://
    if url.startswith('falkor://'):
        url = 'redis://' + url[len('falkor://'):]
    elif url.startswith('falkors://'):
        url = 'rediss://' + url[len('falkors://'):]

    conn = redis.from_url(url, **kwargs)
+   
+   # Check if the connection is a cluster and initialize it accordingly
+   if await Is_Cluster(conn):
+       ssl = url.startswith('rediss://') or url.startswith('falkors://')
+       conn = Cluster_Conn(
+           conn,
+           ssl,
+           **{k: v for k, v in kwargs.items() if k in [
+               'cluster_error_retry_attempts',
+               'startup_nodes',
+               'require_full_coverage',
+               'reinitialize_steps',
+               'read_from_replicas',
+               'address_remap'
+           ]}
+       )
+   
    db.connection      = conn
    db.flushdb         = conn.flushdb
    db.execute_command = conn.execute_command

    return db
🧹 Nitpick comments (4)
falkordb/asyncio/cluster.py (2)

5-8: Update function name and comment to follow Python conventions

The comment "detect if a connection is a sentinel" doesn't match the function's actual purpose (detecting cluster mode). Additionally, the function name uses PascalCase instead of snake_case, which is inconsistent with Python naming conventions (PEP 8).

- # detect if a connection is a sentinel
- async def Is_Cluster(conn):
+ # detect if a connection is in cluster mode
+ async def is_cluster(conn):
    info = await conn.info(section="server")
    return "redis_mode" in info and info["redis_mode"] == "cluster"

11-57: Improve function naming and remove commented out code

The function uses PascalCase instead of snake_case, which is inconsistent with Python conventions. There are also commented out parameters and code that should either be removed or implemented.

- def Cluster_Conn(
+ def cluster_conn(
    conn,
    ssl,
    cluster_error_retry_attempts=3,
    startup_nodes=None,
    require_full_coverage=False,
    reinitialize_steps=5,
    read_from_replicas=False,
-   # dynamic_startup_nodes=True,
-   # url=None,
    address_remap=None,
):
    connection_kwargs = conn.connection_pool.connection_kwargs
    host = connection_kwargs.pop("host")
    port = connection_kwargs.pop("port")
    username = connection_kwargs.pop("username")
    password = connection_kwargs.pop("password")

    retry = connection_kwargs.pop("retry", None)
-   # retry_on_timeout = connection_kwargs.pop("retry_on_timeout", None)
+   retry_on_timeout = connection_kwargs.pop("retry_on_timeout", None)
    retry_on_error = connection_kwargs.pop(
        "retry_on_error",

Additionally, consider whether this function should be async since it's part of an asyncio module, although the underlying RedisCluster constructor might not be async.

falkordb/asyncio/falkordb.py (2)

2-2: Avoid wildcard imports

Wildcard imports make it difficult to determine which names are present in the namespace and can lead to unexpected name conflicts. They're also discouraged by PEP 8.

- from .cluster import *
+ from .cluster import Is_Cluster, Cluster_Conn
🧰 Tools
🪛 Ruff (0.8.2)

2-2: from .cluster import * used; unable to detect undefined names

(F403)


11-27: Add documentation for cluster parameters

The class docstring doesn't include any information about the newly added cluster parameters. Update the documentation to include these parameters and their purpose.

class FalkorDB():
    """
    Asynchronous FalkorDB Class for interacting with a FalkorDB server.

    Usage example::
        from falkordb.asyncio import FalkorDB
        # connect to the database and select the 'social' graph
        db = FalkorDB()
        graph = db.select_graph("social")

        # get a single 'Person' node from the graph and print its name
        response = await graph.query("MATCH (n:Person) RETURN n LIMIT 1")
        result   = response.result_set
        person   = result[0][0]
        print(node.properties['name'])
+
+   Cluster Configuration:
+       For Redis Cluster support, the following parameters can be used:
+       - cluster_error_retry_attempts: Number of attempts to retry on cluster errors
+       - startup_nodes: List of nodes to initially connect to
+       - require_full_coverage: If True, requires full cluster coverage for operations
+       - reinitialize_steps: Number of steps to reinitialize the cluster
+       - read_from_replicas: If True, enables read from replica nodes
+       - address_remap: Dictionary of address remapping {old_addr: new_addr}
    """
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f26b45e and ccc3a93.

📒 Files selected for processing (2)
  • falkordb/asyncio/cluster.py (1 hunks)
  • falkordb/asyncio/falkordb.py (3 hunks)
🧰 Additional context used
🪛 Ruff (0.8.2)
falkordb/asyncio/falkordb.py

2-2: from .cluster import * used; unable to detect undefined names

(F403)


94-94: Is_Cluster may be undefined, or defined from star imports

(F405)


95-95: Cluster_Conn may be undefined, or defined from star imports

(F405)

Copy link

codecov bot commented Mar 12, 2025

Codecov Report

Attention: Patch coverage is 59.09091% with 9 lines in your changes missing coverage. Please review.

Project coverage is 91.98%. Comparing base (f26b45e) to head (9059529).
Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
falkordb/asyncio/cluster.py 57.89% 8 Missing ⚠️
falkordb/asyncio/falkordb.py 66.66% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #96      +/-   ##
==========================================
- Coverage   92.26%   91.98%   -0.28%     
==========================================
  Files          35       36       +1     
  Lines        2612     2634      +22     
==========================================
+ Hits         2410     2423      +13     
- Misses        202      211       +9     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@gkorland gkorland requested a review from AviAvni March 12, 2025 14:00
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

♻️ Duplicate comments (2)
falkordb/asyncio/cluster.py (2)

8-17: 🛠️ Refactor suggestion

Handle potential exceptions and resource management

The Is_Cluster function doesn't handle exceptions and doesn't properly close the Redis connection. This can lead to resource leaks and unexpected errors.

 def Is_Cluster(conn: redis.Redis):
 
     pool = conn.connection_pool
     kwargs = pool.connection_kwargs.copy()
 
-    # Create a synchronous Redis client with the same parameters
-    # as the connection pool just to keep Is_Cluster synchronous
-    info = sync_redis.Redis(**kwargs).info(section="server")
-
-    return "redis_mode" in info and info["redis_mode"] == "cluster"
+    # Create a synchronous Redis client with the same parameters
+    # as the connection pool just to keep Is_Cluster synchronous
+    sync_client = None
+    try:
+        sync_client = sync_redis.Redis(**kwargs)
+        info = sync_client.info(section="server")
+        return "redis_mode" in info and info["redis_mode"] == "cluster"
+    except Exception:
+        return False
+    finally:
+        if sync_client:
+            sync_client.close()

31-36: 🛠️ Refactor suggestion

Use get() instead of pop() for safer parameter extraction

The function pops parameters from connection_kwargs without checking if they exist. This could lead to exceptions if any of these keys are missing.

     connection_kwargs = conn.connection_pool.connection_kwargs
-    host = connection_kwargs.pop("host")
-    port = connection_kwargs.pop("port")
-    username = connection_kwargs.pop("username")
-    password = connection_kwargs.pop("password")
+    host = connection_kwargs.get("host")
+    port = connection_kwargs.get("port")
+    username = connection_kwargs.get("username")
+    password = connection_kwargs.get("password")
+    
+    # Remove used keys if they exist
+    for key in ["host", "port", "username", "password"]:
+        connection_kwargs.pop(key, None)
🧹 Nitpick comments (4)
falkordb/asyncio/cluster.py (4)

7-8: Fix misleading comment

The comment mentions "sentinel" but the function actually checks for cluster mode. Update the comment to accurately reflect the function's purpose.

-# detect if a connection is a sentinel
+# detect if a connection is in cluster mode
 def Is_Cluster(conn: redis.Redis):

20-31: Add docstring with parameter descriptions

The Cluster_Conn function lacks a docstring explaining its purpose and parameters. This makes it harder for other developers to understand how to use this function properly.

 # create a cluster connection from a Redis connection
 def Cluster_Conn(
     conn,
     ssl,
     cluster_error_retry_attempts=3,
     startup_nodes=None,
     require_full_coverage=False,
     reinitialize_steps=5,
     read_from_replicas=False,
     address_remap=None,
 ):
+    """
+    Create a Redis Cluster connection from a standard Redis connection.
+    
+    Args:
+        conn: The existing Redis connection
+        ssl: Whether to use SSL for the cluster connection
+        cluster_error_retry_attempts: Number of attempts to retry on cluster errors
+        startup_nodes: List of nodes to try to connect to initially
+        require_full_coverage: Whether to require all slots to be covered by the cluster
+        reinitialize_steps: Number of steps to try before reinitializing connection
+        read_from_replicas: Whether read commands can be sent to replicas
+        address_remap: Dictionary of remapped node addresses (for NAT environments)
+        
+    Returns:
+        A configured RedisCluster instance
+    """
     connection_kwargs = conn.connection_pool.connection_kwargs

37-47: Add validation for retry parameter

The code extracts retry and retry_on_error but doesn't validate if they're appropriate for the RedisCluster constructor. Consider adding validation or documentation about expected types.

-    retry = connection_kwargs.pop("retry", None)
+    # Extract retry configuration with validation
+    retry = connection_kwargs.pop("retry", None)
+    # Validate retry is compatible with RedisCluster if specified
+    if retry is not None and not hasattr(retry, 'retry'):
+        raise ValueError("retry must be a valid Retry object with retry method")
+        
     retry_on_error = connection_kwargs.pop(
         "retry_on_error",
         [

1-6: Consider organizing imports according to standard conventions

The imports are not organized according to common Python conventions. Consider organizing them by standard library, third-party, and local imports with alphabetical ordering within each group.

+import socket
+
 from redis.asyncio.cluster import RedisCluster
 import redis.exceptions as redis_exceptions
 import redis.asyncio as redis
 import redis as sync_redis
-import socket
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ccc3a93 and 757d9a7.

📒 Files selected for processing (2)
  • .gitignore (1 hunks)
  • falkordb/asyncio/cluster.py (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • .gitignore

Comment on lines +48 to +63
return RedisCluster(
host=host,
port=port,
username=username,
password=password,
decode_responses=True,
ssl=ssl,
retry=retry,
retry_on_error=retry_on_error,
require_full_coverage=require_full_coverage,
reinitialize_steps=reinitialize_steps,
read_from_replicas=read_from_replicas,
address_remap=address_remap,
startup_nodes=startup_nodes,
cluster_error_retry_attempts=cluster_error_retry_attempts,
)
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling for cluster connection creation

The function doesn't handle potential exceptions when creating the RedisCluster instance. This makes error diagnosis harder and doesn't provide a graceful fallback.

-    return RedisCluster(
-        host=host,
-        port=port,
-        username=username,
-        password=password,
-        decode_responses=True,
-        ssl=ssl,
-        retry=retry,
-        retry_on_error=retry_on_error,
-        require_full_coverage=require_full_coverage,
-        reinitialize_steps=reinitialize_steps,
-        read_from_replicas=read_from_replicas,
-        address_remap=address_remap,
-        startup_nodes=startup_nodes,
-        cluster_error_retry_attempts=cluster_error_retry_attempts,
-    )
+    try:
+        return RedisCluster(
+            host=host,
+            port=port,
+            username=username,
+            password=password,
+            decode_responses=True,
+            ssl=ssl,
+            retry=retry,
+            retry_on_error=retry_on_error,
+            require_full_coverage=require_full_coverage,
+            reinitialize_steps=reinitialize_steps,
+            read_from_replicas=read_from_replicas,
+            address_remap=address_remap,
+            startup_nodes=startup_nodes,
+            cluster_error_retry_attempts=cluster_error_retry_attempts,
+        )
+    except Exception as e:
+        # Provide more context for the error
+        raise redis_exceptions.ConnectionError(
+            f"Failed to initialize Redis cluster connection: {str(e)}"
+        ) from e
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return RedisCluster(
host=host,
port=port,
username=username,
password=password,
decode_responses=True,
ssl=ssl,
retry=retry,
retry_on_error=retry_on_error,
require_full_coverage=require_full_coverage,
reinitialize_steps=reinitialize_steps,
read_from_replicas=read_from_replicas,
address_remap=address_remap,
startup_nodes=startup_nodes,
cluster_error_retry_attempts=cluster_error_retry_attempts,
)
try:
return RedisCluster(
host=host,
port=port,
username=username,
password=password,
decode_responses=True,
ssl=ssl,
retry=retry,
retry_on_error=retry_on_error,
require_full_coverage=require_full_coverage,
reinitialize_steps=reinitialize_steps,
read_from_replicas=read_from_replicas,
address_remap=address_remap,
startup_nodes=startup_nodes,
cluster_error_retry_attempts=cluster_error_retry_attempts,
)
except Exception as e:
# Provide more context for the error
raise redis_exceptions.ConnectionError(
f"Failed to initialize Redis cluster connection: {str(e)}"
) from e

Copy link
Contributor

@swilly22 swilly22 left a comment

Choose a reason for hiding this comment

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

No tests ?

Comment on lines +40 to +46
[
ConnectionRefusedError,
ConnectionError,
TimeoutError,
socket.timeout,
redis_exceptions.ConnectionError,
],
Copy link
Contributor

Choose a reason for hiding this comment

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

What's this ?

startup_nodes=None,
require_full_coverage=False,
reinitialize_steps=5,
read_from_replicas=False,
Copy link
Contributor

Choose a reason for hiding this comment

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

Why False ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was following the none async configuration

@gkorland
Copy link
Contributor Author

No tests ?

There are no tests for cluster in general, I tested it manually.
We'll add another task to test the cluster

@gkorland gkorland requested a review from swilly22 March 12, 2025 22:10
@swilly22 swilly22 merged commit 15a9f5e into main Mar 13, 2025
7 of 9 checks passed
@swilly22 swilly22 deleted the cluster-async branch March 13, 2025 07:03
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.

Add support for Async Cluster
2 participants