mirror of
https://github.com/open-webui/open-webui.git
synced 2026-07-12 13:29:37 +02:00
fix(redis): add opt-in health_check_interval for stale pooled connections (#23573)
Introduces REDIS_HEALTH_CHECK_INTERVAL and wires it through to every Redis client created by get_redis_connection (plain, cluster and sentinel paths, sync and async). When set, redis-py will PING any connection idle longer than the interval on checkout, so dead sockets are surfaced as reconnectable errors before a real command lands on them. Defaults to unset (empty string) so existing deployments see no behavioural change. Operators who want the protection should set it shorter than the Redis server `timeout` setting and any firewall/LB idle timeout on the path to Redis. Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -435,6 +435,20 @@ REDIS_SOCKET_KEEPALIVE = (
|
||||
os.environ.get('REDIS_SOCKET_KEEPALIVE', 'False').lower() == 'true'
|
||||
)
|
||||
|
||||
# How often (in seconds) redis-py should PING an idle pooled connection
|
||||
# before reusing it. Opt-in: defaults to unset (empty string) so behavior
|
||||
# is unchanged for existing deployments. When set, should be shorter than
|
||||
# the Redis server `timeout` setting and any firewall/LB idle timeout on
|
||||
# the path to Redis, so stale connections are detected before a real
|
||||
# command lands on them. Set to 0 or empty to disable.
|
||||
REDIS_HEALTH_CHECK_INTERVAL = os.environ.get('REDIS_HEALTH_CHECK_INTERVAL', '')
|
||||
try:
|
||||
REDIS_HEALTH_CHECK_INTERVAL = int(REDIS_HEALTH_CHECK_INTERVAL)
|
||||
if REDIS_HEALTH_CHECK_INTERVAL <= 0:
|
||||
REDIS_HEALTH_CHECK_INTERVAL = None
|
||||
except ValueError:
|
||||
REDIS_HEALTH_CHECK_INTERVAL = None
|
||||
|
||||
REDIS_RECONNECT_DELAY = os.environ.get('REDIS_RECONNECT_DELAY', '')
|
||||
|
||||
if REDIS_RECONNECT_DELAY == '':
|
||||
|
||||
@@ -9,6 +9,7 @@ import redis
|
||||
|
||||
from open_webui.env import (
|
||||
REDIS_CLUSTER,
|
||||
REDIS_HEALTH_CHECK_INTERVAL,
|
||||
REDIS_SOCKET_CONNECT_TIMEOUT,
|
||||
REDIS_SOCKET_KEEPALIVE,
|
||||
REDIS_SENTINEL_HOSTS,
|
||||
@@ -202,6 +203,12 @@ def get_redis_connection(
|
||||
{'socket_keepalive': True} if REDIS_SOCKET_KEEPALIVE else {}
|
||||
)
|
||||
|
||||
health_check_kwargs = (
|
||||
{'health_check_interval': REDIS_HEALTH_CHECK_INTERVAL}
|
||||
if REDIS_HEALTH_CHECK_INTERVAL
|
||||
else {}
|
||||
)
|
||||
|
||||
if async_mode:
|
||||
import redis.asyncio as redis
|
||||
|
||||
@@ -217,6 +224,7 @@ def get_redis_connection(
|
||||
decode_responses=decode_responses,
|
||||
socket_connect_timeout=REDIS_SOCKET_CONNECT_TIMEOUT,
|
||||
**keepalive_kwargs,
|
||||
**health_check_kwargs,
|
||||
)
|
||||
connection = SentinelRedisProxy(
|
||||
sentinel,
|
||||
@@ -231,6 +239,7 @@ def get_redis_connection(
|
||||
decode_responses=decode_responses,
|
||||
**connect_timeout_kwargs,
|
||||
**keepalive_kwargs,
|
||||
**health_check_kwargs,
|
||||
)
|
||||
elif redis_url:
|
||||
connection = redis.from_url(
|
||||
@@ -238,6 +247,7 @@ def get_redis_connection(
|
||||
decode_responses=decode_responses,
|
||||
**connect_timeout_kwargs,
|
||||
**keepalive_kwargs,
|
||||
**health_check_kwargs,
|
||||
)
|
||||
else:
|
||||
import redis
|
||||
@@ -253,6 +263,7 @@ def get_redis_connection(
|
||||
decode_responses=decode_responses,
|
||||
socket_connect_timeout=REDIS_SOCKET_CONNECT_TIMEOUT,
|
||||
**keepalive_kwargs,
|
||||
**health_check_kwargs,
|
||||
)
|
||||
connection = SentinelRedisProxy(
|
||||
sentinel,
|
||||
@@ -267,6 +278,7 @@ def get_redis_connection(
|
||||
decode_responses=decode_responses,
|
||||
**connect_timeout_kwargs,
|
||||
**keepalive_kwargs,
|
||||
**health_check_kwargs,
|
||||
)
|
||||
elif redis_url:
|
||||
connection = redis.Redis.from_url(
|
||||
@@ -274,6 +286,7 @@ def get_redis_connection(
|
||||
decode_responses=decode_responses,
|
||||
**connect_timeout_kwargs,
|
||||
**keepalive_kwargs,
|
||||
**health_check_kwargs,
|
||||
)
|
||||
|
||||
_CONNECTION_CACHE[cache_key] = connection
|
||||
|
||||
Reference in New Issue
Block a user