Skip to content

Commit f98dcce

Browse files
authored
Merge pull request #749 from JackiLin/read-write-separation
Fix sentinel mode read-write separation
2 parents 196544b + f23b06d commit f98dcce

File tree

3 files changed

+21
-7
lines changed

3 files changed

+21
-7
lines changed

changelog.d/749.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix is_master parsing error for write separation in sentinel mode

django_redis/pool.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from typing import Dict
2-
from urllib.parse import parse_qs, urlparse
2+
from urllib.parse import parse_qs, urlencode, urlparse, urlunparse
33

44
from django.conf import settings
55
from django.core.exceptions import ImproperlyConfigured
@@ -163,16 +163,27 @@ def get_connection_pool(self, params):
163163
# explicitly set service_name and sentinel_manager for the
164164
# SentinelConnectionPool constructor since will be called by from_url
165165
cp_params = dict(params)
166-
cp_params.update(service_name=url.hostname, sentinel_manager=self._sentinel)
167-
pool = super().get_connection_pool(cp_params)
168-
169166
# convert "is_master" to a boolean if set on the URL, otherwise if not
170167
# provided it defaults to True.
171-
is_master = parse_qs(url.query).get("is_master")
168+
query_params = parse_qs(url.query)
169+
is_master = query_params.get("is_master")
172170
if is_master:
173-
pool.is_master = to_bool(is_master[0])
171+
cp_params["is_master"] = to_bool(is_master[0])
172+
# then remove the "is_master" query string from the URL
173+
# so it doesn't interfere with the SentinelConnectionPool constructor
174+
if "is_master" in query_params:
175+
del query_params["is_master"]
176+
new_query = urlencode(query_params, doseq=True)
177+
178+
new_url = urlunparse(
179+
(url.scheme, url.netloc, url.path, url.params, new_query, url.fragment)
180+
)
174181

175-
return pool
182+
cp_params.update(
183+
service_name=url.hostname, sentinel_manager=self._sentinel, url=new_url
184+
)
185+
186+
return super().get_connection_pool(cp_params)
176187

177188

178189
def get_connection_factory(path=None, options=None):

tests/test_connection_string.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
[
99
"unix://tmp/foo.bar?db=1",
1010
"redis://localhost/2",
11+
"redis://redis-master/0?is_master=0",
12+
"redis://redis-master/2?is_master=False",
1113
"rediss://localhost:3333?db=2",
1214
],
1315
)

0 commit comments

Comments
 (0)