Skip to content

Commit d0a95fa

Browse files
committed
Added a health check response counter
1 parent 27ed485 commit d0a95fa

File tree

2 files changed

+30
-35
lines changed

2 files changed

+30
-35
lines changed

redis/client.py

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,15 +1282,11 @@ def __init__(
12821282
self.encoder = encoder
12831283
if self.encoder is None:
12841284
self.encoder = self.connection_pool.get_encoder()
1285-
self.health_check_response_b = self.encoder.encode(
1286-
self.HEALTH_CHECK_MESSAGE)
1285+
self.health_check_response_b = self.encoder.encode(self.HEALTH_CHECK_MESSAGE)
12871286
if self.encoder.decode_responses:
12881287
self.health_check_response = ["pong", self.HEALTH_CHECK_MESSAGE]
12891288
else:
1290-
self.health_check_response = [
1291-
b"pong",
1292-
self.health_check_response_b
1293-
]
1289+
self.health_check_response = [b"pong", self.health_check_response_b]
12941290
self.reset()
12951291

12961292
def __enter__(self):
@@ -1315,6 +1311,7 @@ def reset(self):
13151311
self.connection_pool.release(self.connection)
13161312
self.connection = None
13171313
self.channels = {}
1314+
self.health_check_response_counter = 0
13181315
self.pending_unsubscribe_channels = set()
13191316
self.patterns = {}
13201317
self.pending_unsubscribe_patterns = set()
@@ -1370,12 +1367,19 @@ def clean_health_check_responses(self):
13701367
"""
13711368
If any health check responses are present, clean them
13721369
"""
1370+
ttl = 10
13731371
conn = self.connection
1374-
while self._execute(conn, conn.can_read, timeout=0):
1375-
response = self._execute(conn, conn.read_response)
1376-
if not self.is_health_check_response(response):
1377-
raise PubSubError('A non health check response was cleaned by '
1378-
'execute_command: {0}'.format(response))
1372+
while self.health_check_response_counter > 0 and ttl > 0:
1373+
if self._execute(conn, conn.can_read, timeout=1):
1374+
response = self._execute(conn, conn.read_response)
1375+
if self.is_health_check_response(response):
1376+
self.health_check_response_counter -= 1
1377+
else:
1378+
raise PubSubError(
1379+
"A non health check response was cleaned by "
1380+
"execute_command: {0}".format(response)
1381+
)
1382+
ttl -= 1
13791383

13801384
def _disconnect_raise_connect(self, conn, error):
13811385
"""
@@ -1418,6 +1422,7 @@ def parse_response(self, block=True, timeout=0):
14181422

14191423
if self.is_health_check_response(response):
14201424
# ignore the health check message as user might not expect it
1425+
self.health_check_response_counter -= 1
14211426
return None
14221427
return response
14231428

@@ -1428,9 +1433,9 @@ def is_health_check_response(self, response):
14281433
bulk response, instead of a multi-bulk with "pong" and the response.
14291434
"""
14301435
return response in [
1431-
self.health_check_response, # If there was a subscription
1432-
self.health_check_response_b # If there wasn't
1433-
]
1436+
self.health_check_response, # If there was a subscription
1437+
self.health_check_response_b, # If there wasn't
1438+
]
14341439

14351440
def check_health(self):
14361441
conn = self.connection
@@ -1442,6 +1447,7 @@ def check_health(self):
14421447

14431448
if conn.health_check_interval and time.time() > conn.next_health_check:
14441449
conn.send_command("PING", self.HEALTH_CHECK_MESSAGE, check_health=False)
1450+
self.health_check_response_counter += 1
14451451

14461452
def _normalize_keys(self, data):
14471453
"""

tests/test_pubsub.py

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,23 @@
22
import threading
33
import time
44
from unittest import mock
5+
from unittest.mock import patch
56

67
import pytest
78

89
import redis
910
from redis.exceptions import ConnectionError
1011

11-
from .conftest import (
12-
_get_client,
13-
skip_if_redis_enterprise,
14-
skip_if_server_version_lt
15-
)
12+
from .conftest import _get_client, skip_if_redis_enterprise, skip_if_server_version_lt
1613

1714

1815
def wait_for_message(pubsub, timeout=0.1, ignore_subscribe_messages=False):
1916
now = time.time()
2017
timeout = now + timeout
2118
while now < timeout:
2219
message = pubsub.get_message(
23-
ignore_subscribe_messages=ignore_subscribe_messages)
20+
ignore_subscribe_messages=ignore_subscribe_messages
21+
)
2422
if message is not None:
2523
return message
2624
time.sleep(0.01)
@@ -351,15 +349,6 @@ def test_unicode_pattern_message_handler(self, r):
351349
"pmessage", channel, "test message", pattern=pattern
352350
)
353351

354-
def test_get_message_without_subscribe(self, r):
355-
p = r.pubsub()
356-
with pytest.raises(RuntimeError) as info:
357-
p.get_message()
358-
expect = (
359-
"connection not set: " "did you forget to call subscribe() or psubscribe()?"
360-
)
361-
assert expect in info.exconly()
362-
363352

364353
class TestPubSubAutoDecoding:
365354
"These tests only validate that we get unicode values back"
@@ -557,7 +546,7 @@ def test_get_message_not_subscribed_return_none(self, r):
557546
assert p.subscribed is False
558547
assert p.get_message() is None
559548
assert p.get_message(timeout=0.1) is None
560-
with patch.object(threading.Event, 'wait') as mock:
549+
with patch.object(threading.Event, "wait") as mock:
561550
mock.return_value = False
562551
assert p.get_message(timeout=0.01) is None
563552
assert mock.called
@@ -570,19 +559,19 @@ def poll(ps, expected_res):
570559
message = ps.get_message(timeout=1)
571560
assert message == expected_res
572561

573-
subscribe_response = make_message('subscribe', 'foo', 1)
562+
subscribe_response = make_message("subscribe", "foo", 1)
574563
poller = threading.Thread(target=poll, args=(p, subscribe_response))
575564
poller.start()
576565
time.sleep(0.2)
577-
p.subscribe('foo')
566+
p.subscribe("foo")
578567
poller.join()
579568

580569
def test_get_message_wait_for_subscription_not_being_called(self, r):
581570
p = r.pubsub()
582-
p.subscribe('foo')
583-
with patch.object(threading.Event, 'wait') as mock:
571+
p.subscribe("foo")
572+
with patch.object(threading.Event, "wait") as mock:
584573
assert p.subscribed is True
585-
assert wait_for_message(p) == make_message('subscribe', 'foo', 1)
574+
assert wait_for_message(p) == make_message("subscribe", "foo", 1)
586575
assert mock.called is False
587576

588577

0 commit comments

Comments
 (0)