Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
e9dabdc
Refactored sync health check
vladvildanov Mar 6, 2026
79ec033
Refactored async multidb health check
vladvildanov Mar 9, 2026
1337270
Removed double exception handling
vladvildanov Mar 9, 2026
681af46
Update docs/geographic_failover.rst
vladvildanov Mar 9, 2026
5ba6794
Update tests/test_asyncio/test_multidb/test_healthcheck.py
vladvildanov Mar 9, 2026
37fa692
Update tests/test_multidb/test_healthcheck.py
vladvildanov Mar 9, 2026
514b71c
Refactored health checks to be completion-based
vladvildanov Mar 9, 2026
1b5485a
Merge branch 'vv-multidb-healthcheck-refactor' of github.com:redis/re…
vladvildanov Mar 9, 2026
5bb9534
Merge branch 'master' into vv-multidb-healthcheck-refactor
vladvildanov Mar 9, 2026
ad21d12
Codestlye fixes
vladvildanov Mar 9, 2026
aefa0cf
Merge branch 'vv-multidb-healthcheck-refactor' of github.com:redis/re…
vladvildanov Mar 9, 2026
bc96662
Fixed argument name
vladvildanov Mar 9, 2026
2706ea0
Fixed redundant timeout
vladvildanov Mar 10, 2026
0252736
Merge branch 'master' into vv-multidb-healthcheck-refactor
petyaslavova Mar 10, 2026
5227516
Refactored health check to be async-only
vladvildanov Mar 13, 2026
9b95404
Merge branch 'vv-multidb-healthcheck-refactor' of github.com:redis/re…
vladvildanov Mar 13, 2026
7bb8ba0
Refactored event loop execution in sync client
vladvildanov Mar 16, 2026
8c08bad
Fixed proper handling of failures and updated docs
vladvildanov Mar 16, 2026
c223e66
Fixed correct initial health check execution
vladvildanov Mar 16, 2026
7183fc2
Fixed event loop issue
vladvildanov Mar 16, 2026
137c403
Fixed flacky test
vladvildanov Mar 16, 2026
e3d8636
Fixed coroutine execution
vladvildanov Mar 16, 2026
5d6cac5
Fixed flacky test
vladvildanov Mar 16, 2026
534d144
Fixed correct connection cleanup
vladvildanov Mar 16, 2026
d08ea6f
Fixed 3.12 compatibility issue
vladvildanov Mar 16, 2026
7818603
Fixed race condition
vladvildanov Mar 16, 2026
c7548bf
Updated exception handling
vladvildanov Mar 16, 2026
3955c0a
Fix avoiding indefinite hangs
vladvildanov Mar 16, 2026
ebae44c
Refactor health checks to use clients instead of pools
vladvildanov Mar 17, 2026
8d82b1e
Removed unused if statement
vladvildanov Mar 17, 2026
0f7d7c3
Updated to broaded exception
vladvildanov Mar 17, 2026
ea521c7
Merge branch 'master' of github.com:redis/redis-py into vv-multidb-he…
vladvildanov Mar 17, 2026
29ea862
Fixed passing not supported arguments
vladvildanov Mar 18, 2026
acde146
Updated docs, added new properties to health check cluster client
vladvildanov Mar 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions docs/geographic_failover.rst
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ MultiDbConfig
health_check_interval: float = DEFAULT_HEALTH_CHECK_INTERVAL # seconds
health_check_probes: int = DEFAULT_HEALTH_CHECK_PROBES
health_check_delay: float = DEFAULT_HEALTH_CHECK_DELAY # seconds
health_check_timeout: float = DEFAULT_HEALTH_CHECK_TIMEOUT # seconds
health_check_policy: HealthCheckPolicies = DEFAULT_HEALTH_CHECK_POLICY,

# Failure detector
Expand Down Expand Up @@ -344,19 +345,23 @@ You can add custom health checks for specific requirements:
from redis.retry import Retry
from redis.utils import dummy_fail
Comment thread
vladvildanov marked this conversation as resolved.
Outdated
class PingHealthCheck(AbstractHealthCheck):
def __init__(self, retry: Retry):
super().__init__(retry=retry)
def check_health(self, database) -> bool:
return self._retry.call_with_retry(
lambda: self._returns_pong(database),
lambda _: dummy_fail()
def __init__(
self,
health_check_probes: int = 10,
health_check_delay: float = 0.1,
health_check_timeout: float = 2,
):
super().__init__(
health_check_probes=health_check_probes,
health_check_delay=health_check_delay,
health_check_timeout=health_check_timeout,
)
def _returns_pong(self, database) -> bool:

def check_health(self, database) -> bool:
expected_message = ["PONG", b"PONG"]
actual_message = database.client.execute_command("PING")
return actual_message in expected_message


Failure Detection (Reactive Monitoring)
-----------------

Expand Down
27 changes: 9 additions & 18 deletions redis/asyncio/multidb/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,9 @@ def __init__(self, config: MultiDbConfig):
if not config.health_checks
else config.health_checks
)

self._health_check_interval = config.health_check_interval
self._health_check_policy: HealthCheckPolicy = config.health_check_policy.value(
config.health_check_probes, config.health_check_delay
self._health_check_policy: HealthCheckPolicy = (
config.health_check_policy.value()
)
self._failure_detectors = (
config.default_failure_detectors()
Expand Down Expand Up @@ -326,23 +325,15 @@ async def _check_databases_health(self) -> dict[Database, bool]:
Runs health checks as a recurring task.
Runs health checks against all databases.
"""
try:
task_to_db: dict[asyncio.Task, Database] = {}
task_to_db: dict[asyncio.Task, Database] = {}

self._hc_tasks = []
for database, _ in self._databases:
task = asyncio.create_task(self._check_db_health(database))
task_to_db[task] = database
self._hc_tasks.append(task)
self._hc_tasks = []
for database, _ in self._databases:
task = asyncio.create_task(self._check_db_health(database))
task_to_db[task] = database
self._hc_tasks.append(task)

results = await asyncio.wait_for(
asyncio.gather(*self._hc_tasks, return_exceptions=True),
timeout=self._health_check_interval,
)
except asyncio.TimeoutError:
raise asyncio.TimeoutError(
"Health check execution exceeds health_check_interval"
)
results = await asyncio.gather(*self._hc_tasks, return_exceptions=True)
Comment thread
vladvildanov marked this conversation as resolved.

# Map end results to databases
db_results = {
Expand Down
10 changes: 9 additions & 1 deletion redis/asyncio/multidb/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
DEFAULT_HEALTH_CHECK_INTERVAL,
DEFAULT_HEALTH_CHECK_POLICY,
DEFAULT_HEALTH_CHECK_PROBES,
DEFAULT_HEALTH_CHECK_TIMEOUT,
HealthCheck,
HealthCheckPolicies,
PingHealthCheck,
Expand Down Expand Up @@ -110,6 +111,8 @@ class MultiDbConfig:
health_check_interval: Time interval for executing health checks.
health_check_probes: Number of attempts to evaluate the health of a database.
health_check_delay: Delay between health check attempts.
health_check_timeout: Timeout for the full health check operation (including all probes).
health_check_policy: Policy for determining database health based on health checks.
failover_strategy: Optional strategy for handling database failover scenarios.
failover_attempts: Number of retries allowed for failover operations.
failover_delay: Delay between failover attempts.
Expand Down Expand Up @@ -149,6 +152,7 @@ class MultiDbConfig:
health_check_interval: float = DEFAULT_HEALTH_CHECK_INTERVAL
health_check_probes: int = DEFAULT_HEALTH_CHECK_PROBES
health_check_delay: float = DEFAULT_HEALTH_CHECK_DELAY
health_check_timeout: float = DEFAULT_HEALTH_CHECK_TIMEOUT
health_check_policy: HealthCheckPolicies = DEFAULT_HEALTH_CHECK_POLICY
failover_strategy: Optional[AsyncFailoverStrategy] = None
failover_attempts: int = DEFAULT_FAILOVER_ATTEMPTS
Expand Down Expand Up @@ -213,7 +217,11 @@ def default_failure_detectors(self) -> List[AsyncFailureDetector]:

def default_health_checks(self) -> List[HealthCheck]:
return [
PingHealthCheck(),
PingHealthCheck(
health_check_probes=self.health_check_probes,
health_check_delay=self.health_check_delay,
health_check_timeout=self.health_check_timeout,
),
]

def default_failover_strategy(self) -> AsyncFailoverStrategy:
Expand Down
Loading
Loading