Skip to content

Commit 0ee5ab0

Browse files
Yury-FridlyandacarbonettoSanHalacogluImproving
authored
Add CLIENT ID and CLIENT GETNAME commands. (valkey-io#1014)
* Add `CLIENT ID` and `CLIENT GETNAME` commands. (#98) Signed-off-by: Yury-Fridlyand <[email protected]> Co-authored-by: Andrew Carbonetto <[email protected]> Co-authored-by: SanHalacogluImproving <[email protected]>
1 parent fb93d1a commit 0ee5ab0

File tree

13 files changed

+407
-7
lines changed

13 files changed

+407
-7
lines changed

java/client/src/main/java/glide/api/BaseClient.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ public abstract class BaseClient
7979
HashCommands,
8080
ListBaseCommands,
8181
SetCommands {
82+
8283
/** Redis simple string response with "OK" */
8384
public static final String OK = ConstantResponse.OK.toString();
8485

@@ -214,7 +215,7 @@ protected Object[] handleArrayOrNullResponse(Response response) throws RedisExce
214215
/**
215216
* @param response A Protobuf response
216217
* @return A map of <code>String</code> to <code>V</code>
217-
* @param <V> Value type could be even map too
218+
* @param <V> Value type
218219
*/
219220
@SuppressWarnings("unchecked") // raw Map cast to Map<String, V>
220221
protected <V> Map<String, V> handleMapResponse(Response response) throws RedisException {

java/client/src/main/java/glide/api/RedisClient.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/** Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */
22
package glide.api;
33

4+
import static redis_request.RedisRequestOuterClass.RequestType.ClientGetName;
5+
import static redis_request.RedisRequestOuterClass.RequestType.ClientId;
46
import static redis_request.RedisRequestOuterClass.RequestType.CustomCommand;
57
import static redis_request.RedisRequestOuterClass.RequestType.Info;
68
import static redis_request.RedisRequestOuterClass.RequestType.Ping;
@@ -75,4 +77,15 @@ public CompletableFuture<String> select(long index) {
7577
return commandManager.submitNewCommand(
7678
Select, new String[] {Long.toString(index)}, this::handleStringResponse);
7779
}
80+
81+
@Override
82+
public CompletableFuture<Long> clientId() {
83+
return commandManager.submitNewCommand(ClientId, new String[0], this::handleLongResponse);
84+
}
85+
86+
@Override
87+
public CompletableFuture<String> clientGetName() {
88+
return commandManager.submitNewCommand(
89+
ClientGetName, new String[0], this::handleStringOrNullResponse);
90+
}
7891
}

java/client/src/main/java/glide/api/RedisClusterClient.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
/** Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */
22
package glide.api;
33

4+
import static redis_request.RedisRequestOuterClass.RequestType.ClientGetName;
5+
import static redis_request.RedisRequestOuterClass.RequestType.ClientId;
46
import static redis_request.RedisRequestOuterClass.RequestType.CustomCommand;
57
import static redis_request.RedisRequestOuterClass.RequestType.Info;
68
import static redis_request.RedisRequestOuterClass.RequestType.Ping;
@@ -144,4 +146,39 @@ public CompletableFuture<ClusterValue<String>> info(
144146
? ClusterValue.of(handleStringResponse(response))
145147
: ClusterValue.of(handleMapResponse(response)));
146148
}
149+
150+
@Override
151+
public CompletableFuture<Long> clientId() {
152+
return commandManager.submitNewCommand(ClientId, new String[0], this::handleLongResponse);
153+
}
154+
155+
@Override
156+
public CompletableFuture<ClusterValue<Long>> clientId(@NonNull Route route) {
157+
return commandManager.submitNewCommand(
158+
ClientId,
159+
new String[0],
160+
route,
161+
response ->
162+
route.isSingleNodeRoute()
163+
? ClusterValue.of(handleLongResponse(response))
164+
: ClusterValue.of(handleMapResponse(response)));
165+
}
166+
167+
@Override
168+
public CompletableFuture<String> clientGetName() {
169+
return commandManager.submitNewCommand(
170+
ClientGetName, new String[0], this::handleStringOrNullResponse);
171+
}
172+
173+
@Override
174+
public CompletableFuture<ClusterValue<String>> clientGetName(@NonNull Route route) {
175+
return commandManager.submitNewCommand(
176+
ClientGetName,
177+
new String[0],
178+
route,
179+
response ->
180+
route.isSingleNodeRoute()
181+
? ClusterValue.of(handleStringOrNullResponse(response))
182+
: ClusterValue.of(handleMapResponse(response)));
183+
}
147184
}

java/client/src/main/java/glide/api/commands/ConnectionManagementClusterCommands.java

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
/** Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */
22
package glide.api.commands;
33

4+
import glide.api.models.ClusterValue;
45
import glide.api.models.configuration.RequestRoutingConfiguration.Route;
56
import java.util.concurrent.CompletableFuture;
67

78
/**
8-
* Connection Management Commands interface.
9+
* Connection Management Commands interface for cluster client.
910
*
10-
* @see: <a href="https://redis.io/commands/?group=connection">Connection Management Commands</a>
11+
* @see <a href="https://redis.io/commands/?group=connection">Connection Management Commands</a>
1112
*/
1213
public interface ConnectionManagementClusterCommands {
1314

@@ -48,4 +49,74 @@ public interface ConnectionManagementClusterCommands {
4849
* @return <code>String</code> with a copy of the argument <code>message</code>.
4950
*/
5051
CompletableFuture<String> ping(String message, Route route);
52+
53+
/**
54+
* Gets the current connection id.<br>
55+
* The command will be routed to a random node.
56+
*
57+
* @see <a href="https://redis.io/commands/client-id/">redis.io</a> for details.
58+
* @return The id of the client.
59+
* @example
60+
* <pre>{@code
61+
* long id = client.clientId().get();
62+
* assert id > 0
63+
* }</pre>
64+
*/
65+
CompletableFuture<Long> clientId();
66+
67+
/**
68+
* Gets the current connection id.
69+
*
70+
* @see <a href="https://redis.io/commands/client-id/">redis.io</a> for details.
71+
* @param route Routing configuration for the command. Client will route the command to the nodes
72+
* defined.
73+
* @return A {@link ClusterValue} which holds a single value if single node route is used or a
74+
* dictionary where each address is the key and its corresponding node response is the value.
75+
* The value is the id of the client on that node.
76+
* @example
77+
* <pre>{@code
78+
* long id = client.clientId(new SlotIdRoute(...)).get().getSingleValue();
79+
* assert id > 0;
80+
*
81+
* Map<String, Long> idPerNode = client.clientId(ALL_NODES).get().getMultiValue();
82+
* assert idPerNode.get("<node 1 address>") > 0;
83+
* </pre>
84+
*/
85+
CompletableFuture<ClusterValue<Long>> clientId(Route route);
86+
87+
/**
88+
* Gets the name of the current connection.<br>
89+
* The command will be routed a random node.
90+
*
91+
* @see <a href="https://redis.io/commands/client-getname/">redis.io</a> for details.
92+
* @return The name of the client connection as a string if a name is set, or <code>null</code> if
93+
* no name is assigned.
94+
* @example
95+
* <pre>{@code
96+
* String clientName = client.clientGetName().get();
97+
* assert clientName != null;
98+
* }</pre>
99+
*/
100+
CompletableFuture<String> clientGetName();
101+
102+
/**
103+
* Gets the name of the current connection.
104+
*
105+
* @see <a href="https://redis.io/commands/client-getname/">redis.io</a> for details.
106+
* @param route Routing configuration for the command. Client will route the command to the nodes
107+
* defined.
108+
* @return A {@link ClusterValue} which holds a single value if single node route is used or a
109+
* dictionary where each address is the key and its corresponding node response is the value.
110+
* The value is the name of the client connection as a string if a name is set, or null if no
111+
* name is assigned.
112+
* @example
113+
* <pre>{@code
114+
* String clientName = client.clientGetName(new SlotIdRoute(...)).get().getSingleValue();
115+
* assert clientName != null;
116+
*
117+
* Map<String, String> clientNamePerNode = client.clientGetName(ALL_NODES).get().getMultiValue();
118+
* assert clientNamePerNode.get("<node 1 address>") != null
119+
* }</pre>
120+
*/
121+
CompletableFuture<ClusterValue<String>> clientGetName(Route route);
51122
}

java/client/src/main/java/glide/api/commands/ConnectionManagementCommands.java

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
import java.util.concurrent.CompletableFuture;
55

66
/**
7-
* Connection Management Commands interface.
7+
* Connection Management Commands interface for standalone client.
88
*
9-
* @see: <a href="https://redis.io/commands/?group=connection">Connection Management Commands</a>
9+
* @see <a href="https://redis.io/commands/?group=connection">Connection Management Commands</a>
1010
*/
1111
public interface ConnectionManagementCommands {
1212

@@ -26,4 +26,31 @@ public interface ConnectionManagementCommands {
2626
* @return <code>String</code> with a copy of the argument <code>message</code>.
2727
*/
2828
CompletableFuture<String> ping(String message);
29+
30+
/**
31+
* Gets the current connection id.
32+
*
33+
* @see <a href="https://redis.io/commands/client-id/">redis.io</a> for details.
34+
* @return The id of the client.
35+
* @example
36+
* <pre>{@code
37+
* Long id = client.clientId().get();
38+
* assert id > 0;
39+
* }</pre>
40+
*/
41+
CompletableFuture<Long> clientId();
42+
43+
/**
44+
* Gets the name of the current connection.
45+
*
46+
* @see <a href="https://redis.io/commands/client-getname/">redis.io</a> for details.
47+
* @return The name of the client connection as a string if a name is set, or <code>null</code> if
48+
* no name is assigned.
49+
* @example
50+
* <pre>{@code
51+
* String clientName = client.clientGetName().get();
52+
* assert clientName != null;
53+
* }</pre>
54+
*/
55+
CompletableFuture<String> clientGetName();
2956
}

java/client/src/main/java/glide/api/models/BaseTransaction.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
package glide.api.models;
33

44
import static glide.utils.ArrayTransformUtils.convertMapToArgArray;
5+
import static redis_request.RedisRequestOuterClass.RequestType.ClientGetName;
6+
import static redis_request.RedisRequestOuterClass.RequestType.ClientId;
57
import static redis_request.RedisRequestOuterClass.RequestType.CustomCommand;
68
import static redis_request.RedisRequestOuterClass.RequestType.Decr;
79
import static redis_request.RedisRequestOuterClass.RequestType.DecrBy;
@@ -966,6 +968,29 @@ public T ttl(@NonNull String key) {
966968
return getThis();
967969
}
968970

971+
/**
972+
* Get the current connection id.
973+
*
974+
* @see <a href="https://redis.io/commands/client-id/">redis.io</a> for details.
975+
* @return Command response - The id of the client.
976+
*/
977+
public T clientId() {
978+
protobufTransaction.addCommands(buildCommand(ClientId));
979+
return getThis();
980+
}
981+
982+
/**
983+
* Get the name of the current connection.
984+
*
985+
* @see <a href="https://redis.io/commands/client-getname/">redis.io</a> for details.
986+
* @return Command response - The name of the client connection as a string if a name is set, or
987+
* <code>null</code> if no name is assigned.
988+
*/
989+
public T clientGetName() {
990+
protobufTransaction.addCommands(buildCommand(ClientGetName));
991+
return getThis();
992+
}
993+
969994
/** Build protobuf {@link Command} object for given command and arguments. */
970995
protected Command buildCommand(RequestType requestType) {
971996
return buildCommand(requestType, buildArgs());

java/client/src/test/java/glide/api/RedisClientTest.java

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
import static org.mockito.ArgumentMatchers.eq;
1313
import static org.mockito.Mockito.mock;
1414
import static org.mockito.Mockito.when;
15+
import static redis_request.RedisRequestOuterClass.RequestType.ClientGetName;
16+
import static redis_request.RedisRequestOuterClass.RequestType.ClientId;
1517
import static redis_request.RedisRequestOuterClass.RequestType.CustomCommand;
1618
import static redis_request.RedisRequestOuterClass.RequestType.Decr;
1719
import static redis_request.RedisRequestOuterClass.RequestType.DecrBy;
@@ -1286,4 +1288,42 @@ public void scard_returns_success() {
12861288
assertEquals(testResponse, response);
12871289
assertEquals(value, payload);
12881290
}
1291+
1292+
@SneakyThrows
1293+
@Test
1294+
public void clientId_returns_success() {
1295+
// setup
1296+
CompletableFuture<Long> testResponse = mock(CompletableFuture.class);
1297+
when(testResponse.get()).thenReturn(42L);
1298+
1299+
// match on protobuf request
1300+
when(commandManager.<Long>submitNewCommand(eq(ClientId), eq(new String[0]), any()))
1301+
.thenReturn(testResponse);
1302+
1303+
// exercise
1304+
CompletableFuture<Long> response = service.clientId();
1305+
1306+
// verify
1307+
assertEquals(testResponse, response);
1308+
assertEquals(42L, response.get());
1309+
}
1310+
1311+
@SneakyThrows
1312+
@Test
1313+
public void clientGetName_returns_success() {
1314+
// setup
1315+
CompletableFuture<String> testResponse = mock(CompletableFuture.class);
1316+
when(testResponse.get()).thenReturn("TEST");
1317+
1318+
// match on protobuf request
1319+
when(commandManager.<String>submitNewCommand(eq(ClientGetName), eq(new String[0]), any()))
1320+
.thenReturn(testResponse);
1321+
1322+
// exercise
1323+
CompletableFuture<String> response = service.clientGetName();
1324+
1325+
// verify
1326+
assertEquals(testResponse, response);
1327+
assertEquals("TEST", response.get());
1328+
}
12891329
}

0 commit comments

Comments
 (0)