diff --git a/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java b/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java index 772b8920a9..d29da6d10e 100644 --- a/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java @@ -3841,7 +3841,16 @@ public List xRevRange(String key, org.springframework.data.domain. */ @Override public Long xTrim(String key, long count) { - return convertAndReturn(delegate.xTrim(serialize(key), count), identityConverter); + return xTrim(key, count, false); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.StringRedisConnection#xTrim(java.lang.String, long, boolean) + */ + @Override + public Long xTrim(String key, long count, boolean approximateTrimming) { + return convertAndReturn(delegate.xTrim(serialize(key), count, approximateTrimming), identityConverter); } /* @@ -4022,7 +4031,16 @@ public List xRevRange(byte[] key, org.springframework.data.domain.Ra */ @Override public Long xTrim(byte[] key, long count) { - return delegate.xTrim(key, count); + return xTrim(key, count, false); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisStreamCommands#xTrim(byte[], long, boolean) + */ + @Override + public Long xTrim(byte[] key, long count, boolean approximateTrimming) { + return delegate.xTrim(key, count, approximateTrimming); } /** diff --git a/src/main/java/org/springframework/data/redis/connection/DefaultedRedisConnection.java b/src/main/java/org/springframework/data/redis/connection/DefaultedRedisConnection.java index 684273ab80..b28b99eb36 100644 --- a/src/main/java/org/springframework/data/redis/connection/DefaultedRedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/DefaultedRedisConnection.java @@ -609,7 +609,13 @@ default List xRevRange(byte[] key, org.springframework.data.domain.R @Override @Deprecated default Long xTrim(byte[] key, long count) { - return streamCommands().xTrim(key, count); + return xTrim(key, count, false); + } + + @Override + @Deprecated + default Long xTrim(byte[] key, long count, boolean approximateTrimming) { + return streamCommands().xTrim(key, count, approximateTrimming); } // LIST COMMANDS diff --git a/src/main/java/org/springframework/data/redis/connection/ReactiveStreamCommands.java b/src/main/java/org/springframework/data/redis/connection/ReactiveStreamCommands.java index fd6869d6bc..2abf8ee140 100644 --- a/src/main/java/org/springframework/data/redis/connection/ReactiveStreamCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/ReactiveStreamCommands.java @@ -1376,11 +1376,12 @@ default Flux xRevRange(ByteBuffer key, Range range, Li class TrimCommand extends KeyCommand { private @Nullable Long count; + private boolean approximateTrimming; - private TrimCommand(ByteBuffer key, @Nullable Long count) { - + private TrimCommand(ByteBuffer key, @Nullable Long count, boolean approximateTrimming) { super(key); this.count = count; + this.approximateTrimming = approximateTrimming; } /** @@ -1393,7 +1394,7 @@ public static TrimCommand stream(ByteBuffer key) { Assert.notNull(key, "Key must not be null!"); - return new TrimCommand(key, null); + return new TrimCommand(key, null, false); } /** @@ -1401,10 +1402,11 @@ public static TrimCommand stream(ByteBuffer key) { * properties. * * @param count + * @param approximateTrimming * @return a new {@link TrimCommand} with {@literal count} applied. */ - public TrimCommand to(long count) { - return new TrimCommand(getKey(), count); + public TrimCommand to(long count, boolean approximateTrimming) { + return new TrimCommand(getKey(), count, approximateTrimming); } /** @@ -1414,6 +1416,10 @@ public TrimCommand to(long count) { public Long getCount() { return count; } + + public boolean isApproximateTrimming() { + return approximateTrimming; + } } /** @@ -1425,10 +1431,23 @@ public Long getCount() { * @see Redis Documentation: XTRIM */ default Mono xTrim(ByteBuffer key, long count) { + return xTrim(key, count, false); + } + + /** + * Trims the stream to {@code count} elements. + * + * @param key the stream key. + * @param count length of the stream. + * @param approximateTrimming the trimming must be performed in a approximated way in order to maximize performances. + * @return {@link Mono} emitting the number of removed entries. + * @see Redis Documentation: XTRIM + */ + default Mono xTrim(ByteBuffer key, long count, boolean approximateTrimming) { Assert.notNull(key, "Key must not be null!"); - return xTrim(Mono.just(TrimCommand.stream(key).to(count))).next().map(NumericResponse::getOutput); + return xTrim(Mono.just(TrimCommand.stream(key).to(count, approximateTrimming))).next().map(NumericResponse::getOutput); } /** diff --git a/src/main/java/org/springframework/data/redis/connection/RedisStreamCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisStreamCommands.java index 6376c663f8..f3d9270ada 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisStreamCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisStreamCommands.java @@ -873,4 +873,16 @@ default List xRevRange(byte[] key, Range range) { */ @Nullable Long xTrim(byte[] key, long count); + + /** + * Trims the stream to {@code count} elements. + * + * @param key the stream key. + * @param count length of the stream. + * @param approximateTrimming the trimming must be performed in a approximated way in order to maximize performances. + * @return number of removed entries. {@literal null} when used in pipeline / transaction. + * @see Redis Documentation: XTRIM + */ + @Nullable + Long xTrim(byte[] key, long count, boolean approximateTrimming); } diff --git a/src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java b/src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java index 8f8c444608..4854db0eb5 100644 --- a/src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java @@ -2428,4 +2428,17 @@ default List xRevRange(String key, org.springframework.data.domain */ @Nullable Long xTrim(String key, long count); + + /** + * Trims the stream to {@code count} elements. + * + * @param key the stream key. + * @param count length of the stream. + * @param approximateTrimming the trimming must be performed in a approximated way in order to maximize performances. + * @return number of removed entries. {@literal null} when used in pipeline / transaction. + * @since 2.2 + * @see Redis Documentation: XTRIM + */ + @Nullable + Long xTrim(String key, long count, boolean approximateTrimming); } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveStreamCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveStreamCommands.java index cf1baeb95a..b0d7f6b567 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveStreamCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceReactiveStreamCommands.java @@ -420,7 +420,7 @@ public Flux> xTrim(Publisher comm Assert.notNull(command.getKey(), "Key must not be null!"); Assert.notNull(command.getCount(), "Count must not be null!"); - return cmd.xtrim(command.getKey(), command.getCount()).map(value -> new NumericResponse<>(command, value)); + return cmd.xtrim(command.getKey(), command.isApproximateTrimming(), command.getCount()).map(value -> new NumericResponse<>(command, value)); })); } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceStreamCommands.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceStreamCommands.java index 0afc6b6ef6..62d07c0105 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceStreamCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceStreamCommands.java @@ -662,19 +662,27 @@ public List xRevRange(byte[] key, Range range, Limit limit) */ @Override public Long xTrim(byte[] key, long count) { + return xTrim(key, count, false); + } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisStreamCommands#xTrim(byte[], long, boolean) + */ + @Override + public Long xTrim(byte[] key, long count, boolean approximateTrimming) { Assert.notNull(key, "Key must not be null!"); try { if (isPipelined()) { - pipeline(connection.newLettuceResult(getAsyncConnection().xtrim(key, count))); + pipeline(connection.newLettuceResult(getAsyncConnection().xtrim(key, approximateTrimming, count))); return null; } if (isQueueing()) { - transaction(connection.newLettuceResult(getAsyncConnection().xtrim(key, count))); + transaction(connection.newLettuceResult(getAsyncConnection().xtrim(key, approximateTrimming, count))); return null; } - return getConnection().xtrim(key, count); + return getConnection().xtrim(key, approximateTrimming, count); } catch (Exception ex) { throw convertLettuceAccessException(ex); } diff --git a/src/main/java/org/springframework/data/redis/core/BoundStreamOperations.java b/src/main/java/org/springframework/data/redis/core/BoundStreamOperations.java index f311b99590..55f0d8353f 100644 --- a/src/main/java/org/springframework/data/redis/core/BoundStreamOperations.java +++ b/src/main/java/org/springframework/data/redis/core/BoundStreamOperations.java @@ -208,4 +208,15 @@ default List> reverseRange(Range range) { */ @Nullable Long trim(long count); + + /** + * Trims the stream to {@code count} elements. + * + * @param count length of the stream. + * @param approximateTrimming the trimming must be performed in a approximated way in order to maximize performances. + * @return number of removed entries. {@literal null} when used in pipeline / transaction. + * @see Redis Documentation: XTRIM + */ + @Nullable + Long trim(long count, boolean approximateTrimming); } diff --git a/src/main/java/org/springframework/data/redis/core/DefaultBoundStreamOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultBoundStreamOperations.java index bccb7e0ab3..52724c01fb 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultBoundStreamOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultBoundStreamOperations.java @@ -170,7 +170,17 @@ public List> reverseRange(Range range, Limit limit) @Nullable @Override public Long trim(long count) { - return ops.trim(getKey(), count); + return trim(count, false); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.core.BoundStreamOperations#trim(long,boolean) + */ + @Nullable + @Override + public Long trim(long count, boolean approximateTrimming) { + return ops.trim(getKey(), count, approximateTrimming); } /* diff --git a/src/main/java/org/springframework/data/redis/core/DefaultReactiveStreamOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultReactiveStreamOperations.java index f628f4a6e9..632c72299d 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultReactiveStreamOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultReactiveStreamOperations.java @@ -341,10 +341,18 @@ public Flux> reverseRange(K key, Range range, Limit */ @Override public Mono trim(K key, long count) { + return trim(key, count, false); + } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.core.ReactiveStreamOperations#trim(java.lang.Object, long, boolean) + */ + @Override + public Mono trim(K key, long count, boolean approximateTrimming) { Assert.notNull(key, "Key must not be null!"); - return createMono(connection -> connection.xTrim(rawKey(key), count)); + return createMono(connection -> connection.xTrim(rawKey(key), count, approximateTrimming)); } @Override diff --git a/src/main/java/org/springframework/data/redis/core/DefaultStreamOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultStreamOperations.java index 21e3a401fd..e59cf85c73 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultStreamOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultStreamOperations.java @@ -336,6 +336,12 @@ public Long trim(K key, long count) { return execute(connection -> connection.xTrim(rawKey, count), true); } + @Override + public Long trim(K key, long count, boolean approximateTrimming) { + byte[] rawKey = rawKey(key); + return execute(connection -> connection.xTrim(rawKey, count, approximateTrimming), true); + } + @Override public HashMapper getHashMapper(Class targetType) { return objectMapper.getHashMapper(targetType); diff --git a/src/main/java/org/springframework/data/redis/core/ReactiveStreamOperations.java b/src/main/java/org/springframework/data/redis/core/ReactiveStreamOperations.java index 63bc4ba504..aa4280edb6 100644 --- a/src/main/java/org/springframework/data/redis/core/ReactiveStreamOperations.java +++ b/src/main/java/org/springframework/data/redis/core/ReactiveStreamOperations.java @@ -544,6 +544,17 @@ default Flux> reverseRange(Class targetType, K key, Ra */ Mono trim(K key, long count); + /** + * Trims the stream to {@code count} elements. + * + * @param key the stream key. + * @param count length of the stream. + * @param approximateTrimming the trimming must be performed in a approximated way in order to maximize performances. + * @return number of removed entries. + * @see Redis Documentation: XTRIM + */ + Mono trim(K key, long count, boolean approximateTrimming); + /** * Get the {@link HashMapper} for a specific type. * diff --git a/src/main/java/org/springframework/data/redis/core/StreamOperations.java b/src/main/java/org/springframework/data/redis/core/StreamOperations.java index 003c5a4567..9bff7be82f 100644 --- a/src/main/java/org/springframework/data/redis/core/StreamOperations.java +++ b/src/main/java/org/springframework/data/redis/core/StreamOperations.java @@ -525,6 +525,18 @@ default List> reverseRange(Class targetType, K key, Ra @Nullable Long trim(K key, long count); + /** + * Trims the stream to {@code count} elements. + * + * @param key the stream key. + * @param count length of the stream. + * @param approximateTrimming the trimming must be performed in a approximated way in order to maximize performances. + * @return number of removed entries. {@literal null} when used in pipeline / transaction. + * @see Redis Documentation: XTRIM + */ + @Nullable + Long trim(K key, long count, boolean approximateTrimming); + /** * Get the {@link HashMapper} for a specific type. * diff --git a/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionPipelineTests.java b/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionPipelineTests.java index a395b31489..7ca20aa823 100644 --- a/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionPipelineTests.java +++ b/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionPipelineTests.java @@ -1726,6 +1726,13 @@ public void xTrimShouldDelegateAndConvertCorrectly() { super.xTrimShouldDelegateAndConvertCorrectly(); } + @Test + public void xTrimApproximateShouldDelegateAndConvertCorrectly() { + + doReturn(Arrays.asList(1L)).when(nativeConnection).closePipeline(); + super.xTrimApproximateShouldDelegateAndConvertCorrectly(); + } + protected List getResults() { return connection.closePipeline(); } diff --git a/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionPipelineTxTests.java b/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionPipelineTxTests.java index 587176c913..e4c382a37e 100644 --- a/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionPipelineTxTests.java +++ b/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionPipelineTxTests.java @@ -1846,6 +1846,13 @@ public void xTrimShouldDelegateAndConvertCorrectly() { super.xTrimShouldDelegateAndConvertCorrectly(); } + @Test + public void xTrimApproximateShouldDelegateAndConvertCorrectly() { + + doReturn(Arrays.asList(Arrays.asList(1L))).when(nativeConnection).closePipeline(); + super.xTrimApproximateShouldDelegateAndConvertCorrectly(); + } + @SuppressWarnings("unchecked") protected List getResults() { connection.exec(); diff --git a/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTests.java b/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTests.java index 3447756419..4075d70d6a 100644 --- a/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTests.java +++ b/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTests.java @@ -2169,6 +2169,15 @@ public void xTrimShouldDelegateAndConvertCorrectly() { Assertions.assertThat(getResults()).containsExactly(1L); } + @Test + public void xTrimApproximateShouldDelegateAndConvertCorrectly() { + + doReturn(1L).when(nativeConnection).xTrim(any(), anyLong(), anyBoolean()); + + actual.add(connection.xTrim("key", 2L, true)); + Assertions.assertThat(getResults()).containsExactly(1L); + } + protected List getResults() { return actual; } diff --git a/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTxTests.java b/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTxTests.java index ee8121f0e6..2d31ee0e78 100644 --- a/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTxTests.java +++ b/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTxTests.java @@ -1733,6 +1733,13 @@ public void xTrimShouldDelegateAndConvertCorrectly() { super.xTrimShouldDelegateAndConvertCorrectly(); } + @Test + public void xTrimApproximateShouldDelegateAndConvertCorrectly() { + + doReturn(Arrays.asList(1L)).when(nativeConnection).exec(); + super.xTrimApproximateShouldDelegateAndConvertCorrectly(); + } + protected List getResults() { return connection.exec(); }