diff --git a/redis/client.py b/redis/client.py index 4e4ccc69c2..b7e25a3ae3 100755 --- a/redis/client.py +++ b/redis/client.py @@ -2852,17 +2852,35 @@ def xrevrange(self, name, max='+', min='-', count=None): return self.execute_command('XREVRANGE', name, *pieces) - def xtrim(self, name, maxlen, approximate=True): + def xtrim(self, name, maxlen=None, approximate=True, minid=None, + limit=None): """ Trims old messages from a stream. name: name of the stream. maxlen: truncate old stream messages beyond this size approximate: actual stream length may be slightly more than maxlen + minin: the minimum id in the stream to query + limit: specifies the maximum number of entries to retrieve """ - pieces = [b'MAXLEN'] + pieces = [] + if maxlen is not None and minid is not None: + raise DataError("Only one of ```maxlen``` or ```minid```", + "may be specified") + + if maxlen is not None: + pieces.append(b'MAXLEN') + if minid is not None: + pieces.append(b'MINID') if approximate: pieces.append(b'~') - pieces.append(maxlen) + if maxlen is not None: + pieces.append(maxlen) + if minid is not None: + pieces.append(minid) + if limit is not None: + pieces.append(b"LIMIT") + pieces.append(limit) + return self.execute_command('XTRIM', name, *pieces) # SORTED SET COMMANDS diff --git a/tests/test_commands.py b/tests/test_commands.py index 9682603a9d..f4082593fa 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -2783,6 +2783,47 @@ def test_xtrim(self, r): # 1 message is trimmed assert r.xtrim(stream, 3, approximate=False) == 1 + @skip_if_server_version_lt('6.2.4') + def test_xtrim_minlen_and_length_args(self, r): + stream = 'stream' + + r.xadd(stream, {'foo': 'bar'}) + r.xadd(stream, {'foo': 'bar'}) + r.xadd(stream, {'foo': 'bar'}) + r.xadd(stream, {'foo': 'bar'}) + + # Future self: No limits without approximate, according to the api + with pytest.raises(redis.ResponseError): + assert r.xtrim(stream, 3, approximate=False, limit=2) + + # maxlen with a limit + assert r.xtrim(stream, 3, approximate=True, limit=2) == 0 + r.delete(stream) + + with pytest.raises(redis.DataError): + assert r.xtrim(stream, maxlen=3, minid="sometestvalue") + + # minid with a limit + m1 = r.xadd(stream, {'foo': 'bar'}) + r.xadd(stream, {'foo': 'bar'}) + r.xadd(stream, {'foo': 'bar'}) + r.xadd(stream, {'foo': 'bar'}) + assert r.xtrim(stream, None, approximate=True, minid=m1, limit=3) == 0 + + # pure minid + r.xadd(stream, {'foo': 'bar'}) + r.xadd(stream, {'foo': 'bar'}) + r.xadd(stream, {'foo': 'bar'}) + m4 = r.xadd(stream, {'foo': 'bar'}) + assert r.xtrim(stream, None, approximate=False, minid=m4) == 7 + + # minid approximate + r.xadd(stream, {'foo': 'bar'}) + r.xadd(stream, {'foo': 'bar'}) + m3 = r.xadd(stream, {'foo': 'bar'}) + r.xadd(stream, {'foo': 'bar'}) + assert r.xtrim(stream, None, approximate=True, minid=m3) == 0 + def test_bitfield_operations(self, r): # comments show affected bits bf = r.bitfield('a')