Skip to content

Add support for microseconds using TIME #526

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3303,6 +3303,15 @@ public Long time() {
return convertAndReturn(this.delegate.time(), identityConverter);
}

/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisServerCommands#microseconds()
*/
@Override
public Long microseconds() {
return convertAndReturn(this.delegate.microseconds(), identityConverter);
}

/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.StringRedisConnection#getClientList()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1394,6 +1394,13 @@ default Long time() {
return serverCommands().time();
}

/** @deprecated in favor of {@link RedisConnection#serverCommands()}. */
@Override
@Deprecated
default Long microseconds() {
return serverCommands().microseconds();
}

/** @deprecated in favor of {@link RedisConnection#serverCommands()}. */
@Override
@Deprecated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,16 @@ default void bgWriteAof() {
@Nullable
Long time();

/**
* Request server timestamp using {@code TIME} command.
*
* @return current server time in microseconds or {@literal null} when used in pipeline / transaction.
* @since 1.1
* @see <a href="https://redis.io/commands/time">Redis Documentation: TIME</a>
*/
@Nullable
Long microseconds();

/**
* Closes a given client connection identified by {@literal host:port}.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,9 +309,9 @@ public static List<Object> toObjects(Set<Tuple> tuples) {
* @param microseconds elapsed microseconds in current second
* @return
*/
public static Long toTimeMillis(String seconds, String microseconds) {
return NumberUtils.parseNumber(seconds, Long.class) * 1000L
+ NumberUtils.parseNumber(microseconds, Long.class) / 1000L;
public static Long toTimeMicros(String seconds, String microseconds) {
return NumberUtils.parseNumber(seconds, Long.class) * 1000 * 1000L
+ NumberUtils.parseNumber(microseconds, Long.class);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,17 @@ public Long time() {
.executeCommandOnArbitraryNode((JedisClusterCommandCallback<List<String>>) BinaryJedis::time).getValue());
}

/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisServerCommands#time()
*/
@Override
public Long microseconds() {

return convertListOfStringToMicros(connection.getClusterCommandExecutor()
.executeCommandOnArbitraryNode((JedisClusterCommandCallback<List<String>>) BinaryJedis::time).getValue());
}

/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisClusterServerCommands#time(org.springframework.data.redis.connection.RedisClusterNode)
Expand Down Expand Up @@ -518,11 +529,15 @@ public void migrate(byte[] key, RedisNode target, int dbIndex, @Nullable Migrate

private Long convertListOfStringToTime(List<String> serverTimeInformation) {

return convertListOfStringToMicros(serverTimeInformation) / 1000;
}

private Long convertListOfStringToMicros(List<String> serverTimeInformation) {
Assert.notEmpty(serverTimeInformation, "Received invalid result from server. Expected 2 items in collection.");
Assert.isTrue(serverTimeInformation.size() == 2,
"Received invalid number of arguments from redis server. Expected 2 received " + serverTimeInformation.size());

return Converters.toTimeMillis(serverTimeInformation.get(0), serverTimeInformation.get(1));
return Converters.toTimeMicros(serverTimeInformation.get(0), serverTimeInformation.get(1));
}

private <T> NodeResult<T> executeCommandOnSingleNode(JedisClusterCommandCallback<T> cmd, RedisClusterNode node) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ public byte[] convert(SetOption source) {
Assert.isTrue(source.size() == 2,
"Received invalid nr of arguments from redis server. Expected 2 received " + source.size());

return toTimeMillis(source.get(0), source.get(1));
return toTimeMicros(source.get(0), source.get(1));
};

GEO_COORDINATE_TO_POINT_CONVERTER = geoCoordinate -> geoCoordinate != null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,16 @@ public void resetConfigStats() {
*/
@Override
public Long time() {
Long time = microseconds();
return time == null ? null : time / 1000;
}

/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisServerCommands#time()
*/
@Override
public Long microseconds() {
try {
if (isPipelined()) {
pipeline(connection.newJedisResult(connection.getRequiredPipeline().time(), JedisConverters.toTimeConverter()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,16 @@ public void resetConfigStats(RedisClusterNode node) {
*/
@Override
public Long time() {
Long time = microseconds();
return time == null ? null : time / 1000;
}

/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.lettuce.LettuceServerCommands#time()
*/
@Override
public Long microseconds() {
return convertListOfStringToTime(connection.getClusterCommandExecutor()
.executeCommandOnArbitraryNode((LettuceClusterCommandCallback<List<byte[]>>) RedisServerCommands::time)
.getValue());
Expand Down Expand Up @@ -384,12 +393,15 @@ private <T> MultiNodeResult<T> executeCommandOnAllNodes(final LettuceClusterComm
}

private static Long convertListOfStringToTime(List<byte[]> serverTimeInformation) {
return convertListOfStringToMicros(serverTimeInformation) / 1000;
}

private static Long convertListOfStringToMicros(List<byte[]> serverTimeInformation) {
Assert.notEmpty(serverTimeInformation, "Received invalid result from server. Expected 2 items in collection.");
Assert.isTrue(serverTimeInformation.size() == 2,
"Received invalid number of arguments from redis server. Expected 2 received " + serverTimeInformation.size());

return Converters.toTimeMillis(LettuceConverters.toString(serverTimeInformation.get(0)),
return Converters.toTimeMicros(LettuceConverters.toString(serverTimeInformation.get(0)),
LettuceConverters.toString(serverTimeInformation.get(1)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ private Set<Flag> parseFlags(Set<NodeFlag> source) {
Assert.isTrue(source.size() == 2,
"Received invalid nr of arguments from redis server. Expected 2 received " + source.size());

return toTimeMillis(toString(source.get(0)), toString(source.get(1)));
return toTimeMicros(toString(source.get(0)), toString(source.get(1)));
};

GEO_COORDINATE_TO_POINT_CONVERTER = geoCoordinate -> geoCoordinate != null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,16 @@ public void resetConfigStats() {
*/
@Override
public Long time() {
Long time = microseconds();
return time == null ? null : time / 1000;
}

/*
* (non-Javadoc)
* @see org.springframework.data.redis.connection.RedisServerCommands#time()
*/
@Override
public Long microseconds() {
try {
if (isPipelined()) {
pipeline(connection.newLettuceResult(getAsyncConnection().time(), LettuceConverters.toTimeConverter()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2077,6 +2077,17 @@ public void testGetTimeShouldRequestServerTime() {
assertThat((Long) results.get(0) > 0).isTrue();
}

@Test
public void testGetMicrosecondsShouldRequestServerTime() {

actual.add(connection.microseconds());

List<Object> results = getResults();
assertThat(results).isNotEmpty();
assertThat(results.get(0)).isNotNull();
assertThat((Long) results.get(0) > 0).isTrue();
}

@Test // DATAREDIS-269
public void clientSetNameWorksCorrectly() {
connection.setClientName("foo".getBytes());
Expand Down