Skip to content

Commit 1614416

Browse files
kajinamitzzzeek
authored andcommitted
redis: Support a few more socket_* options
Added support for additional Redis client parameters :paramref:`.RedisBackend.socket_connect_timeout`, :paramref:`.RedisBackend.socket_keepalive` and :paramref:`.RedisBackend.socket_keepalive_options`. Pull request courtesy Takashi Kajinami. Closes: #252 Pull-request: #252 Pull-request-sha: adf7a8a Change-Id: Iad0a8960d6f5450035296de8563a7d885a675968
1 parent 7fda91f commit 1614416

File tree

4 files changed

+114
-5
lines changed

4 files changed

+114
-5
lines changed

docs/build/unreleased/250.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
.. change::
2-
:tags: feature, redis
2+
:tags: usecase, redis
33
:tickets: 250
44

55
Added a new backend :class:`.RedisClusterBackend`, allowing support for
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.. change::
2+
:tags: usecase, redis
3+
:tickets: 252
4+
5+
Added support for additional Redis client parameters
6+
:paramref:`.RedisBackend.socket_connect_timeout`,
7+
:paramref:`.RedisBackend.socket_keepalive` and
8+
:paramref:`.RedisBackend.socket_keepalive_options`. Pull request courtesy
9+
Takashi Kajinami.

dogpile/cache/backends/redis.py

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ class RedisBackend(BytesBackend):
5252
5353
:param username: string, default is no username.
5454
55+
.. versionadded:: 1.3.1
56+
5557
:param password: string, default is no password.
5658
5759
:param port: integer, default is ``6379``.
@@ -74,6 +76,21 @@ class RedisBackend(BytesBackend):
7476
:param socket_timeout: float, seconds for socket timeout.
7577
Default is None (no timeout).
7678
79+
:param socket_connect_timeout: float, seconds for socket connection
80+
timeout. Default is None (no timeout).
81+
82+
.. versionadded:: 1.3.2
83+
84+
:param socket_keepalive: boolean, when True, socket keepalive is enabled.
85+
Default is False.
86+
87+
.. versionadded:: 1.3.2
88+
89+
:param socket_keepalive_options: dict, socket keepalive options.
90+
Default is None (no options).
91+
92+
.. versionadded:: 1.3.2
93+
7794
:param lock_sleep: integer, number of seconds to sleep when failed to
7895
acquire a lock. This argument is only valid when
7996
``distributed_lock`` is ``True``.
@@ -95,9 +112,10 @@ class RedisBackend(BytesBackend):
95112
directly, including parameters like ``ssl``, ``ssl_certfile``,
96113
``charset``, etc.
97114
98-
.. versionadded:: 1.1.6 Added ``connection_kwargs`` parameter.
115+
.. versionadded:: 1.1.6
116+
117+
99118
100-
.. versionadded:: 1.3.1 Added ``username`` parameter.
101119
102120
"""
103121

@@ -112,6 +130,13 @@ def __init__(self, arguments):
112130
self.db = arguments.pop("db", 0)
113131
self.distributed_lock = arguments.pop("distributed_lock", False)
114132
self.socket_timeout = arguments.pop("socket_timeout", None)
133+
self.socket_connect_timeout = arguments.pop(
134+
"socket_connect_timeout", None
135+
)
136+
self.socket_keepalive = arguments.pop("socket_keepalive", False)
137+
self.socket_keepalive_options = arguments.pop(
138+
"socket_keepalive_options", None
139+
)
115140
self.lock_timeout = arguments.pop("lock_timeout", None)
116141
self.lock_sleep = arguments.pop("lock_sleep", 0.1)
117142
self.thread_local_lock = arguments.pop("thread_local_lock", True)
@@ -144,8 +169,16 @@ def _create_client(self):
144169
else:
145170
args = {}
146171
args.update(self.connection_kwargs)
147-
if self.socket_timeout:
172+
if self.socket_timeout is not None:
148173
args["socket_timeout"] = self.socket_timeout
174+
if self.socket_connect_timeout is not None:
175+
args["socket_connect_timeout"] = self.socket_connect_timeout
176+
if self.socket_keepalive:
177+
args["socket_keepalive"] = True
178+
if self.socket_keepalive_options is not None:
179+
args[
180+
"socket_keepalive_options"
181+
] = self.socket_keepalive_options
149182

150183
if self.url is not None:
151184
args.update(url=self.url)
@@ -256,6 +289,8 @@ class RedisSentinelBackend(RedisBackend):
256289
257290
:param username: string, default is no username.
258291
292+
.. versionadded:: 1.3.1
293+
259294
:param password: string, default is no password.
260295
261296
:param db: integer, default is ``0``.
@@ -276,6 +311,21 @@ class RedisSentinelBackend(RedisBackend):
276311
:param socket_timeout: float, seconds for socket timeout.
277312
Default is None (no timeout).
278313
314+
.. versionadded:: 1.3.2
315+
316+
:param socket_connect_timeout: float, seconds for socket connection
317+
timeout. Default is None (no timeout).
318+
319+
.. versionadded:: 1.3.2
320+
321+
:param socket_keepalive: boolean, when True, socket keepalive is enabled
322+
Default is False.
323+
324+
.. versionadded:: 1.3.2
325+
326+
:param socket_keepalive_options: dict, socket keepalive options.
327+
Default is {} (no options).
328+
279329
:param sentinels: is a list of sentinel nodes. Each node is represented by
280330
a pair (hostname, port).
281331
Default is None (not in sentinel mode).
@@ -303,7 +353,6 @@ class RedisSentinelBackend(RedisBackend):
303353
asynchronous runners, as they run in a different thread than the one
304354
used to create the lock.
305355
306-
.. versionadded:: 1.3.1 Added ``username`` parameter.
307356
308357
"""
309358

@@ -343,6 +392,16 @@ def _create_client(self):
343392
sentinel_kwargs.setdefault("db", self.db)
344393
if self.socket_timeout is not None:
345394
connection_kwargs.setdefault("socket_timeout", self.socket_timeout)
395+
if self.socket_connect_timeout is not None:
396+
connection_kwargs.setdefault(
397+
"socket_connect_timeout", self.socket_connect_timeout
398+
)
399+
if self.socket_keepalive:
400+
connection_kwargs.setdefault("socket_keepalive", True)
401+
if self.socket_keepalive_options is not None:
402+
connection_kwargs.setdefault(
403+
"socket_keepalive_options", self.socket_keepalive_options
404+
)
346405

347406
sentinel = redis.sentinel.Sentinel(
348407
self.sentinels,
@@ -463,6 +522,12 @@ class RedisClusterBackend(RedisBackend):
463522
:param socket_timeout: float, seconds for socket timeout.
464523
Default is None (no timeout).
465524
525+
:param socket_connect_timeout: float, seconds for socket connection
526+
timeout. Default is None (no timeout).
527+
528+
:param socket_keepalive: boolean, when True, socket keepalive is enabled
529+
Default is False.
530+
466531
:param lock_sleep: integer, number of seconds to sleep when failed to
467532
acquire a lock. This argument is only valid when
468533
``distributed_lock`` is ``True``.

tests/cache/test_redis_backend.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,41 @@ def test_connect_with_socket_timeout(self, MockStrictRedis):
202202
expected.update({"username": None, "password": None})
203203
self._test_helper(MockStrictRedis, expected, arguments)
204204

205+
def test_connect_with_socket_connect_timeout(self, MockStrictRedis):
206+
arguments = {
207+
"host": "127.0.0.1",
208+
"port": 6379,
209+
"socket_timeout": 1.0,
210+
"db": 0,
211+
}
212+
expected = arguments.copy()
213+
expected.update({"username": None, "password": None})
214+
self._test_helper(MockStrictRedis, expected, arguments)
215+
216+
def test_connect_with_socket_keepalive(self, MockStrictRedis):
217+
arguments = {
218+
"host": "127.0.0.1",
219+
"port": 6379,
220+
"socket_keepalive": True,
221+
"db": 0,
222+
}
223+
expected = arguments.copy()
224+
expected.update({"username": None, "password": None})
225+
self._test_helper(MockStrictRedis, expected, arguments)
226+
227+
def test_connect_with_socket_keepalive_options(self, MockStrictRedis):
228+
arguments = {
229+
"host": "127.0.0.1",
230+
"port": 6379,
231+
"socket_keepalive": True,
232+
# 4 = socket.TCP_KEEPIDLE
233+
"socket_keepalive_options": {4, 10.0},
234+
"db": 0,
235+
}
236+
expected = arguments.copy()
237+
expected.update({"username": None, "password": None})
238+
self._test_helper(MockStrictRedis, expected, arguments)
239+
205240
def test_connect_with_connection_pool(self, MockStrictRedis):
206241
pool = Mock()
207242
arguments = {"connection_pool": pool, "socket_timeout": 0.5}

0 commit comments

Comments
 (0)