-
Notifications
You must be signed in to change notification settings - Fork 7
added get_replica_connections function #72
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: main
Are you sure you want to change the base?
Changes from 2 commits
e7beff6
6a717ab
0791c7e
c77580e
5ee68b7
c4dc33a
2c20a1e
99b6671
dd8a4ad
8eed87f
e646320
4a3d585
a1262e0
199a1e5
71622fe
9f261fc
9d21e95
6aad7bd
2a96be0
b693987
519b9dd
557f04f
222cfb4
a9f597e
ac8471e
cfd0864
65e41d0
d112322
ad7cedd
ac4cfa4
5a444db
4cc0b6a
51d4d90
cb8cd2e
1ad3162
4d4c1ac
263e8bf
af4f748
b1d6c41
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 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -3,7 +3,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from .sentinel import * | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from .graph import Graph | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from typing import List, Union | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import socket | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # config command | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| LIST_CMD = "GRAPH.LIST" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| CONFIG_CMD = "GRAPH.CONFIG" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -75,6 +75,7 @@ def __init__( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| dynamic_startup_nodes=True, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| url=None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| address_remap=None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| decode_responses=True | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| conn = redis.Redis( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -92,7 +93,7 @@ def __init__( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| encoding_errors=encoding_errors, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| charset=charset, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| errors=errors, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| decode_responses=True, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| decode_responses=decode_responses, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| retry_on_timeout=retry_on_timeout, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| retry_on_error=retry_on_error, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ssl=ssl, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -125,6 +126,7 @@ def __init__( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.sentinel, self.service_name = Sentinel_Conn(conn, ssl) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| conn = self.sentinel.master_for(self.service_name, ssl=ssl) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if Is_Cluster(conn): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| conn = Cluster_Conn( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| conn, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -138,6 +140,7 @@ def __init__( | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| url, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| address_remap, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.cluster_flag = True | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.connection = conn | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.flushdb = conn.flushdb | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -225,6 +228,22 @@ def config_get(self, name: str) -> Union[int, str]: | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return self.connection.execute_command(CONFIG_CMD, "GET", name)[1] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def get_replica_connections(self): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| #decide if its Sentinel or cluster | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| redis_mode= self.connection.execute_command("info")['redis_mode'] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if redis_mode == "standalone": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| replica_hostnames = self.sentinel.discover_slaves(service_name=self.service_name) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| result = [(host,port) for host, port in replica_hostnames] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return result | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| elif redis_mode == "cluster": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| data = self.connection.cluster_nodes() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # List comprehension to get a list of (ip, port, hostname) tuples | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| host_port_list = [(ip_port.split(':')[0], ip_port.split(':')[1], flag['hostname']) for ip_port, flag in data.items() if 'slave' in flag["flags"]] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| result = [tup for tup in host_port_list] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return result | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| redis_mode= self.connection.execute_command("info")['redis_mode'] | |
| if redis_mode == "standalone": | |
| replica_hostnames = self.sentinel.discover_slaves(service_name=self.service_name) | |
| result = [(host,port) for host, port in replica_hostnames] | |
| return result | |
| elif redis_mode == "cluster": | |
| data = self.connection.cluster_nodes() | |
| # List comprehension to get a list of (ip, port, hostname) tuples | |
| host_port_list = [(ip_port.split(':')[0], ip_port.split(':')[1], flag['hostname']) for ip_port, flag in data.items() if 'slave' in flag["flags"]] | |
| result = [tup for tup in host_port_list] | |
| return result | |
| redis_mode = self.connection.execute_command("info", section="server").get('redis_mode') | |
| if not redis_mode: | |
| raise ConnectionError("Unable to determine Redis mode") | |
| if redis_mode == "standalone": | |
| replica_hostnames = self.sentinel.discover_replicas(service_name=self.service_name) | |
| result = [(host,port) for host, port in replica_hostnames] | |
| return result | |
| elif redis_mode == "cluster": | |
| data = self.connection.cluster_nodes() | |
| result = [] | |
| for ip_port, flag in data.items(): | |
| if 'replica' in flag.get('flags', []): # Using 'replica' instead of 'slave' | |
| host, port = ip_port.split(':') | |
| result.append((host, int(port))) # Convert port to int for consistency | |
| return result | |
| else: | |
| raise ValueError(f"Unsupported Redis mode: {redis_mode}") |
🧰 Tools
🪛 GitHub Check: codecov/patch
[warning] 233-239: falkordb/falkordb.py#L233-L239
Added lines #L233 - L239 were not covered by tests
[warning] 241-243: falkordb/falkordb.py#L241-L243
Added lines #L241 - L243 were not covered by tests
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.
💡 Codebase verification
Missing test coverage for get_replica_connections method confirmed
The method requires test coverage for:
- Sentinel mode replica discovery
- Cluster mode replica discovery
- Error handling for connection failures
- Invalid mode handling
Example test structure in tests/test_db.py:
def test_get_replica_connections_sentinel():
# Test sentinel mode with mocked sentinel.discover_slaves
def test_get_replica_connections_cluster():
# Test cluster mode with mocked cluster_nodes
def test_get_replica_connections_errors():
# Test connection errors and invalid modes🔗 Analysis chain
Add test coverage for the new method
The new get_replica_connections method lacks test coverage for critical paths.
Would you like me to help create comprehensive test cases covering:
- Sentinel mode replica discovery
- Cluster mode replica discovery
- Error handling scenarios
- Invalid mode handling
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for existing tests of the new method
fd test_.+\.py$ | xargs rg "get_replica_connections"
Length of output: 53
Script:
#!/bin/bash
# Let's first check if there are any test files in the repository
fd "test.*\.py$"
# Then let's check the content of the falkordb.py file to understand the test requirements better
cat falkordb/falkordb.py
Length of output: 9548
Script:
#!/bin/bash
# Let's check test_db.py as it's likely to contain tests for FalkorDB class methods
cat tests/test_db.py
# Also check if there are any mock or fixture utilities for testing
fd "conftest\.py$"
Length of output: 1366
🧰 Tools
🪛 GitHub Check: codecov/patch
[warning] 248-251: falkordb/falkordb.py#L248-L251
Added lines #L248 - L251 were not covered by tests
[warning] 253-258: falkordb/falkordb.py#L253-L258
Added lines #L253 - L258 were not covered by tests
[warning] 260-260: falkordb/falkordb.py#L260
Added line #L260 was not covered by tests
🪛 Ruff
251-251: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
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.
🛠️ Refactor suggestion
Avoid wildcard imports to improve code clarity
Using wildcard imports can pollute the namespace and make it harder to track dependencies. Explicit imports enhance code readability and maintainability.
🧰 Tools
🪛 Ruff
Import
Is_SentinelandSentinel_Connexplicitly to avoid undefined namesThe functions
Is_SentinelandSentinel_Connmay be undefined if not imported properly. Wildcard imports (e.g.,from .sentinel import *) can lead to unclear code and potentialNameErrors.Apply this diff to fix the imports:
Similarly, update the cluster imports:
🧰 Tools
🪛 Ruff