From c0ac10d5db5f360feb9be456c6367cca59fcfc4d Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Sat, 11 Apr 2026 23:32:05 +0200 Subject: [PATCH] fix: honor REDIS_SOCKET_CONNECT_TIMEOUT on non-sentinel clients (#23572) * fix(redis): honor REDIS_SOCKET_CONNECT_TIMEOUT on non-sentinel clients Previously only the sentinel path passed REDIS_SOCKET_CONNECT_TIMEOUT through to the Redis client. Plain redis:// and cluster URLs fell back to redis-py's default (no explicit connect timeout), so a hung Redis or a black-holed network path could stall the whole worker until the kernel gave up. Forwarding the same env var to from_url()/RedisCluster keeps the behavior consistent across all deployment topologies. * fix(redis): gate socket_connect_timeout on is-not-None, not truthiness Addresses review feedback: the truthiness check on REDIS_SOCKET_CONNECT_TIMEOUT silently dropped an explicit 0 value and was inconsistent with the sentinel construction path, which forwards the value directly. Switch to `is not None` so any user-configured value (including 0) is passed through to from_url() and RedisCluster.from_url(). --------- Co-authored-by: Claude --- backend/open_webui/utils/redis.py | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/backend/open_webui/utils/redis.py b/backend/open_webui/utils/redis.py index 55d08147a9..c2e5da1fae 100644 --- a/backend/open_webui/utils/redis.py +++ b/backend/open_webui/utils/redis.py @@ -191,6 +191,12 @@ def get_redis_connection( connection = None + connect_timeout_kwargs = ( + {'socket_connect_timeout': REDIS_SOCKET_CONNECT_TIMEOUT} + if REDIS_SOCKET_CONNECT_TIMEOUT is not None + else {} + ) + if async_mode: import redis.asyncio as redis @@ -214,9 +220,17 @@ def get_redis_connection( elif redis_cluster: if not redis_url: raise ValueError('Redis URL must be provided for cluster mode.') - return redis.cluster.RedisCluster.from_url(redis_url, decode_responses=decode_responses) + return redis.cluster.RedisCluster.from_url( + redis_url, + decode_responses=decode_responses, + **connect_timeout_kwargs, + ) elif redis_url: - connection = redis.from_url(redis_url, decode_responses=decode_responses) + connection = redis.from_url( + redis_url, + decode_responses=decode_responses, + **connect_timeout_kwargs, + ) else: import redis @@ -239,9 +253,17 @@ def get_redis_connection( elif redis_cluster: if not redis_url: raise ValueError('Redis URL must be provided for cluster mode.') - return redis.cluster.RedisCluster.from_url(redis_url, decode_responses=decode_responses) + return redis.cluster.RedisCluster.from_url( + redis_url, + decode_responses=decode_responses, + **connect_timeout_kwargs, + ) elif redis_url: - connection = redis.Redis.from_url(redis_url, decode_responses=decode_responses) + connection = redis.Redis.from_url( + redis_url, + decode_responses=decode_responses, + **connect_timeout_kwargs, + ) _CONNECTION_CACHE[cache_key] = connection return connection