DATAREDIS-815 - Polishing.
Update Javadoc, add tests and missing methods for BoundValueOperations. Original Pull Request: #334
This commit is contained in:
@@ -15,9 +15,11 @@
|
||||
*/
|
||||
package org.springframework.data.redis.core;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Value (or String in Redis terminology) operations bound to a certain key.
|
||||
@@ -47,6 +49,26 @@ public interface BoundValueOperations<K, V> extends BoundKeyOperations<K> {
|
||||
*/
|
||||
void set(V value, long timeout, TimeUnit unit);
|
||||
|
||||
/**
|
||||
* Set the {@code value} and expiration {@code timeout} for the bound key.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @param timeout must not be {@literal null}.
|
||||
* @throws IllegalArgumentException if either {@code value} or {@code timeout} is not present.
|
||||
* @see <a href="http://redis.io/commands/setex">Redis Documentation: SETEX</a>
|
||||
* @since 2.1
|
||||
*/
|
||||
default void set(V value, Duration timeout) {
|
||||
|
||||
Assert.notNull(timeout, "Timeout must not be null!");
|
||||
|
||||
if (TimeoutUtils.hasMillis(timeout)) {
|
||||
set(value, timeout.toMillis(), TimeUnit.MILLISECONDS);
|
||||
} else {
|
||||
set(value, timeout.getSeconds(), TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bound key to hold the string {@code value} if the bound key is absent.
|
||||
*
|
||||
@@ -70,6 +92,28 @@ public interface BoundValueOperations<K, V> extends BoundKeyOperations<K> {
|
||||
@Nullable
|
||||
Boolean setIfAbsent(V value, long timeout, TimeUnit unit);
|
||||
|
||||
/**
|
||||
* Set bound key to hold the string {@code value} and expiration {@code timeout} if {@code key} is absent.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @param timeout must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @throws IllegalArgumentException if either {@code value} or {@code timeout} is not present.
|
||||
* @see <a href="http://redis.io/commands/set">Redis Documentation: SET</a>
|
||||
* @since 2.1
|
||||
*/
|
||||
@Nullable
|
||||
default Boolean setIfAbsent(V value, Duration timeout) {
|
||||
|
||||
Assert.notNull(timeout, "Timeout must not be null!");
|
||||
|
||||
if (TimeoutUtils.hasMillis(timeout)) {
|
||||
return setIfAbsent(value, timeout.toMillis(), TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
return setIfAbsent(value, timeout.getSeconds(), TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bound key to hold the string {@code value} if {@code key} is present.
|
||||
*
|
||||
@@ -96,6 +140,28 @@ public interface BoundValueOperations<K, V> extends BoundKeyOperations<K> {
|
||||
@Nullable
|
||||
Boolean setIfPresent(V value, long timeout, TimeUnit unit);
|
||||
|
||||
/**
|
||||
* Set the bound key to hold the string {@code value} and expiration {@code timeout} if {@code key} is present.
|
||||
*
|
||||
* @param value must not be {@literal null}.
|
||||
* @param timeout must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @throws IllegalArgumentException if either {@code value} or {@code timeout} is not present.
|
||||
* @see <a href="http://redis.io/commands/set">Redis Documentation: SET</a>
|
||||
* @since 2.1
|
||||
*/
|
||||
@Nullable
|
||||
default Boolean setIfPresent(V value, Duration timeout) {
|
||||
|
||||
Assert.notNull(timeout, "Timeout must not be null!");
|
||||
|
||||
if (TimeoutUtils.hasMillis(timeout)) {
|
||||
return setIfPresent(value, timeout.toMillis(), TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
return setIfPresent(value, timeout.getSeconds(), TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the bound key.
|
||||
*
|
||||
|
||||
@@ -23,15 +23,18 @@ import java.util.concurrent.TimeUnit;
|
||||
*
|
||||
* @author Jennifer Hickey
|
||||
* @author Mark Paluch
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
abstract public class TimeoutUtils {
|
||||
|
||||
/**
|
||||
* @param duration the actual {@link Duration} to inspect.
|
||||
* Check if a given Duration can be represented in {@code sec} or requires {@code msec} representation.
|
||||
*
|
||||
* @param duration the actual {@link Duration} to inspect. Never {@literal null}.
|
||||
* @return {@literal true} if the {@link Duration} contains millisecond information.
|
||||
* @since 2.1
|
||||
*/
|
||||
static boolean hasMillis(Duration duration) {
|
||||
public static boolean hasMillis(Duration duration) {
|
||||
return duration.toMillis() % 1000 != 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -58,10 +58,11 @@ public interface ValueOperations<K, V> {
|
||||
* Set the {@code value} and expiration {@code timeout} for {@code key}.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param value
|
||||
* @param value must not be {@literal null}.
|
||||
* @param timeout must not be {@literal null}.
|
||||
* @since 2.1
|
||||
* @throws IllegalArgumentException if either {@code key}, {@code value} or {@code timeout} is not present.
|
||||
* @see <a href="http://redis.io/commands/setex">Redis Documentation: SETEX</a>
|
||||
* @since 2.1
|
||||
*/
|
||||
default void set(K key, V value, Duration timeout) {
|
||||
|
||||
@@ -103,11 +104,12 @@ public interface ValueOperations<K, V> {
|
||||
* Set {@code key} to hold the string {@code value} and expiration {@code timeout} if {@code key} is absent.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param value
|
||||
* @param value must not be {@literal null}.
|
||||
* @param timeout must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @throws IllegalArgumentException if either {@code key}, {@code value} or {@code timeout} is not present.
|
||||
* @see <a href="http://redis.io/commands/set">Redis Documentation: SET</a>
|
||||
* @since 2.1
|
||||
* @see <a href="http://redis.io/commands/setex">Redis Documentation: SETEX</a>
|
||||
*/
|
||||
@Nullable
|
||||
default Boolean setIfAbsent(K key, V value, Duration timeout) {
|
||||
@@ -153,11 +155,12 @@ public interface ValueOperations<K, V> {
|
||||
* Set {@code key} to hold the string {@code value} and expiration {@code timeout} if {@code key} is present.
|
||||
*
|
||||
* @param key must not be {@literal null}.
|
||||
* @param value
|
||||
* @param value must not be {@literal null}.
|
||||
* @param timeout must not be {@literal null}.
|
||||
* @return {@literal null} when used in pipeline / transaction.
|
||||
* @throws IllegalArgumentException if either {@code key}, {@code value} or {@code timeout} is not present.
|
||||
* @see <a href="http://redis.io/commands/set">Redis Documentation: SET</a>
|
||||
* @since 2.1
|
||||
* @see <a href="http://redis.io/commands/setex">Redis Documentation: SETEX</a>
|
||||
*/
|
||||
@Nullable
|
||||
default Boolean setIfPresent(K key, V value, Duration timeout) {
|
||||
|
||||
@@ -17,6 +17,7 @@ package org.springframework.data.redis.core;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -64,4 +65,52 @@ public class DefaultBoundValueOperationsUnitTests {
|
||||
|
||||
verify(valueOps).setIfPresent(eq(KEY), eq(VALUE), eq(10L), eq(TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-815
|
||||
public void setWithDurationOfSecondsShouldDelegateCorrectly() {
|
||||
|
||||
boundValueOps.set(VALUE, Duration.ofSeconds(1));
|
||||
|
||||
verify(valueOps).set(eq(KEY), eq(VALUE), eq(1L), eq(TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-815
|
||||
public void setWithDurationOfMillisShouldDelegateCorrectly() {
|
||||
|
||||
boundValueOps.set(VALUE, Duration.ofMillis(250));
|
||||
|
||||
verify(valueOps).set(eq(KEY), eq(VALUE), eq(250L), eq(TimeUnit.MILLISECONDS));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-815
|
||||
public void setIfAbsentWithDurationOfSecondsShouldDelegateCorrectly() {
|
||||
|
||||
boundValueOps.setIfAbsent(VALUE, Duration.ofSeconds(1));
|
||||
|
||||
verify(valueOps).setIfAbsent(eq(KEY), eq(VALUE), eq(1L), eq(TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-815
|
||||
public void setIfAbsentWithDurationOfMillisShouldDelegateCorrectly() {
|
||||
|
||||
boundValueOps.setIfAbsent(VALUE, Duration.ofMillis(250));
|
||||
|
||||
verify(valueOps).setIfAbsent(eq(KEY), eq(VALUE), eq(250L), eq(TimeUnit.MILLISECONDS));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-815
|
||||
public void setIfPresentWithDurationOfSecondsShouldDelegateCorrectly() {
|
||||
|
||||
boundValueOps.setIfPresent(VALUE, Duration.ofSeconds(1));
|
||||
|
||||
verify(valueOps).setIfPresent(eq(KEY), eq(VALUE), eq(1L), eq(TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-815
|
||||
public void setIfPresentWithDurationOfMillisShouldDelegateCorrectly() {
|
||||
|
||||
boundValueOps.setIfPresent(VALUE, Duration.ofMillis(250));
|
||||
|
||||
verify(valueOps).setIfPresent(eq(KEY), eq(VALUE), eq(250L), eq(TimeUnit.MILLISECONDS));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,78 +15,95 @@
|
||||
*/
|
||||
package org.springframework.data.redis.core;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Unit test of {@link TimeoutUtils}
|
||||
*
|
||||
* @author Jennifer Hickey
|
||||
* @author Christoph Strobl
|
||||
*/
|
||||
public class TimeoutUtilsTests {
|
||||
|
||||
@Test
|
||||
public void testConvertMoreThanOneSecond() {
|
||||
assertEquals(2, TimeoutUtils.toSeconds(2010, TimeUnit.MILLISECONDS));
|
||||
assertThat(TimeoutUtils.toSeconds(2010, TimeUnit.MILLISECONDS)).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertLessThanOneSecond() {
|
||||
assertEquals(1, TimeoutUtils.toSeconds(999, TimeUnit.NANOSECONDS));
|
||||
assertThat(TimeoutUtils.toSeconds(999, TimeUnit.NANOSECONDS)).isOne();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertZeroSeconds() {
|
||||
assertEquals(0, TimeoutUtils.toSeconds(0, TimeUnit.MINUTES));
|
||||
assertThat(TimeoutUtils.toSeconds(0, TimeUnit.MINUTES)).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertNegativeSecondsGreaterThanNegativeOne() {
|
||||
// Ensure we convert this to 0 as before, though ideally we wouldn't accept negative values
|
||||
assertEquals(0, TimeoutUtils.toSeconds(-123, TimeUnit.MILLISECONDS));
|
||||
assertThat(TimeoutUtils.toSeconds(-123, TimeUnit.MILLISECONDS)).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertNegativeSecondsEqualNegativeOne() {
|
||||
assertEquals(-1, TimeoutUtils.toSeconds(-1111, TimeUnit.MILLISECONDS));
|
||||
assertThat(TimeoutUtils.toSeconds(-1111, TimeUnit.MILLISECONDS)).isEqualTo(-1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertNegativeSecondsLessThanNegativeOne() {
|
||||
assertEquals(-2, TimeoutUtils.toSeconds(-2344, TimeUnit.MILLISECONDS));
|
||||
assertThat(TimeoutUtils.toSeconds(-2344, TimeUnit.MILLISECONDS)).isEqualTo(-2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertMoreThanOneMilli() {
|
||||
assertEquals(2, TimeoutUtils.toMillis(2010, TimeUnit.MICROSECONDS));
|
||||
assertThat(TimeoutUtils.toMillis(2010, TimeUnit.MICROSECONDS)).isEqualTo(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertLessThanOneMilli() {
|
||||
assertEquals(1, TimeoutUtils.toMillis(999, TimeUnit.NANOSECONDS));
|
||||
assertThat(TimeoutUtils.toMillis(999, TimeUnit.NANOSECONDS)).isOne();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertZeroMillis() {
|
||||
assertEquals(0, TimeoutUtils.toMillis(0, TimeUnit.SECONDS));
|
||||
assertThat(TimeoutUtils.toMillis(0, TimeUnit.SECONDS)).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertNegativeMillisGreaterThanNegativeOne() {
|
||||
// Ensure we convert this to 0 as before, though ideally we wouldn't accept negative values
|
||||
assertEquals(0, TimeoutUtils.toMillis(-123, TimeUnit.MICROSECONDS));
|
||||
assertThat(TimeoutUtils.toMillis(-123, TimeUnit.MICROSECONDS)).isZero();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertNegativeMillisEqualNegativeOne() {
|
||||
assertEquals(-1, TimeoutUtils.toMillis(-1111, TimeUnit.MICROSECONDS));
|
||||
assertThat(TimeoutUtils.toMillis(-1111, TimeUnit.MICROSECONDS)).isEqualTo(-1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertNegativeMillisLessThanNegativeOne() {
|
||||
assertEquals(-2, TimeoutUtils.toMillis(-2344, TimeUnit.MICROSECONDS));
|
||||
assertThat(TimeoutUtils.toMillis(-2344, TimeUnit.MICROSECONDS)).isEqualTo(-2);
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-815
|
||||
public void hasMillisReturnsFalseForTimeoutOfExactSeconds() {
|
||||
assertThat(TimeoutUtils.hasMillis(Duration.ofSeconds(1))).isFalse();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-815
|
||||
public void hasMillisReturnsTrueForTimeoutWithMsec() {
|
||||
assertThat(TimeoutUtils.hasMillis(Duration.ofMillis(1500))).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-815
|
||||
public void hasMillisReturnsTrueForTimeoutLessThanOneSecond() {
|
||||
assertThat(TimeoutUtils.hasMillis(Duration.ofMillis(500))).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user