Skip to content

Commit 7f99734

Browse files
committed
Fixing check for correct parser when protocol is 3
1 parent 036cd3e commit 7f99734

File tree

2 files changed

+45
-1
lines changed

2 files changed

+45
-1
lines changed

redis/connection.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,13 @@ def _configure_maintenance_notifications(
386386
"To configure maintenance notifications, a parser must be provided!"
387387
)
388388

389+
if not isinstance(parser, _HiredisParser) and not isinstance(
390+
parser, _RESP3Parser
391+
):
392+
raise RedisError(
393+
"Maintenance notifications are only supported with hiredis and RESP3 parsers!"
394+
)
395+
389396
if maint_notifications_pool_handler:
390397
# Extract a reference to a new pool handler that copies all properties
391398
# of the original one and has a different connection reference
@@ -741,7 +748,12 @@ def __init__(
741748
raise ConnectionError("protocol must be either 2 or 3")
742749
# p = DEFAULT_RESP_VERSION
743750
self.protocol = p
744-
if self.protocol == 3 and parser_class == DefaultParser:
751+
if self.protocol == 3 and parser_class == _RESP2Parser:
752+
# If the protocol is 3 but the parser is RESP2, change it to RESP3
753+
# This is needed because the parser might be set before the protocol
754+
# or might be provided as a kwarg to the constructor
755+
# We need to react on discrepancy only for RESP2 and RESP3
756+
# as hiredis supports both
745757
parser_class = _RESP3Parser
746758
self.set_parser(parser_class)
747759

tests/test_maint_notifications_handling.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,38 @@ def recv(self, bufsize):
304304

305305
raise BlockingIOError(errno.EAGAIN, "Resource temporarily unavailable")
306306

307+
def recv_into(self, buffer, nbytes=0):
308+
"""
309+
Receive data from Redis and write it into the provided buffer.
310+
Returns the number of bytes written.
311+
312+
This method is used by the hiredis parser for efficient data reading.
313+
"""
314+
if self.closed:
315+
raise ConnectionError("Socket is closed")
316+
317+
# Use pending responses that were prepared when commands were sent
318+
if self.pending_responses:
319+
response = self.pending_responses.pop(0)
320+
if b"MOVING" in response:
321+
self.moving_sent = True
322+
323+
# Determine how many bytes to write
324+
if nbytes == 0:
325+
nbytes = len(buffer)
326+
327+
# Write data into the buffer (up to nbytes or response length)
328+
bytes_to_write = min(len(response), nbytes, len(buffer))
329+
buffer[:bytes_to_write] = response[:bytes_to_write]
330+
331+
return bytes_to_write
332+
else:
333+
# No data available - this should block or raise an exception
334+
# For can_read checks, we should indicate no data is available
335+
import errno
336+
337+
raise BlockingIOError(errno.EAGAIN, "Resource temporarily unavailable")
338+
307339
def fileno(self):
308340
"""Return a fake file descriptor for select/poll operations."""
309341
return 1 # Fake file descriptor

0 commit comments

Comments
 (0)