Skip to content

Commit 103636c

Browse files
authored
Add support for CLIENT TRACKINGINFO (#2862)
* Initial commit * Added the CLIENT TRACKINGINFO command * Implement the final version of the command, add parser utility * Add some more unit tests. Polishing. * Implemented dynamic parsing of the result returned from CLIENT TRACKINGINFO * Fixed conflixt issues * Addressed Ali's comment on calling the .getDynamicMap only once * Circle back to using domain objects * Missed several crucial files * Remove part of the license that is not needed
1 parent 53ba22b commit 103636c

23 files changed

+964
-24
lines changed

src/main/java/io/lettuce/core/AbstractRedisAsyncCommands.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,11 @@ public RedisFuture<String> clientTracking(TrackingArgs args) {
389389
return dispatch(commandBuilder.clientTracking(args));
390390
}
391391

392+
@Override
393+
public RedisFuture<TrackingInfo> clientTrackinginfo() {
394+
return dispatch(commandBuilder.clientTrackinginfo());
395+
}
396+
392397
@Override
393398
public RedisFuture<Long> clientUnblock(long id, UnblockType type) {
394399
return dispatch(commandBuilder.clientUnblock(id, type));

src/main/java/io/lettuce/core/AbstractRedisReactiveCommands.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,11 @@ public Mono<String> clientTracking(TrackingArgs args) {
407407
return createMono(() -> commandBuilder.clientTracking(args));
408408
}
409409

410+
@Override
411+
public Mono<TrackingInfo> clientTrackinginfo() {
412+
return createMono(commandBuilder::clientTrackinginfo);
413+
}
414+
410415
@Override
411416
public Mono<Long> clientUnblock(long id, UnblockType type) {
412417
return createMono(() -> commandBuilder.clientUnblock(id, type));

src/main/java/io/lettuce/core/RedisCommandBuilder.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,12 @@ Command<K, V, String> clientTracking(TrackingArgs trackingArgs) {
528528
return createCommand(CLIENT, new StatusOutput<>(codec), args);
529529
}
530530

531+
Command<K, V, TrackingInfo> clientTrackinginfo() {
532+
CommandArgs<K, V> args = new CommandArgs<>(codec).add(TRACKINGINFO);
533+
534+
return new Command<>(CLIENT, new ComplexOutput<>(codec, TrackingInfoParser.INSTANCE), args);
535+
}
536+
531537
Command<K, V, Long> clientUnblock(long id, UnblockType type) {
532538
LettuceAssert.notNull(type, "UnblockType " + MUST_NOT_BE_NULL);
533539

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
/*
2+
* Copyright 2024, Redis Ltd. and Contributors
3+
* All rights reserved.
4+
*
5+
* Licensed under the MIT License.
6+
*/
7+
8+
package io.lettuce.core;
9+
10+
import java.util.ArrayList;
11+
import java.util.Collections;
12+
import java.util.HashSet;
13+
import java.util.Objects;
14+
import java.util.Set;
15+
import java.util.List;
16+
17+
/**
18+
* Contains the output of a <a href="https://redis.io/docs/latest/commands/client-trackinginfo/">CLIENT TRACKINGINFO</a>
19+
* command.
20+
*
21+
* @author Tihomir Mateev
22+
* @since 6.5
23+
*/
24+
public class TrackingInfo {
25+
26+
private final Set<TrackingFlag> flags = new HashSet<>();
27+
28+
private final long redirect;
29+
30+
private final List<String> prefixes = new ArrayList<>();
31+
32+
/**
33+
* Constructor
34+
*
35+
* @param flags a {@link Set} of {@link TrackingFlag}s that the command returned
36+
* @param redirect the client ID used for notification redirection, -1 when none
37+
* @param prefixes a {@link List} of key prefixes for which notifications are sent to the client
38+
*
39+
* @see TrackingFlag
40+
*/
41+
public TrackingInfo(Set<TrackingFlag> flags, long redirect, List<String> prefixes) {
42+
this.flags.addAll(flags);
43+
this.redirect = redirect;
44+
this.prefixes.addAll(prefixes);
45+
}
46+
47+
/**
48+
* @return set of all the {@link TrackingFlag}s currently enabled on the client connection
49+
*/
50+
public Set<TrackingFlag> getFlags() {
51+
return Collections.unmodifiableSet(flags);
52+
}
53+
54+
/**
55+
* @return the client ID used for notification redirection, -1 when none
56+
*/
57+
public long getRedirect() {
58+
return redirect;
59+
}
60+
61+
/**
62+
* @return a {@link List} of key prefixes for which notifications are sent to the client
63+
*/
64+
public List<String> getPrefixes() {
65+
return Collections.unmodifiableList(prefixes);
66+
}
67+
68+
@Override
69+
public String toString() {
70+
return "TrackingInfo{" + "flags=" + flags + ", redirect=" + redirect + ", prefixes=" + prefixes + '}';
71+
}
72+
73+
@Override
74+
public boolean equals(Object o) {
75+
if (this == o)
76+
return true;
77+
if (o == null || getClass() != o.getClass())
78+
return false;
79+
TrackingInfo that = (TrackingInfo) o;
80+
return redirect == that.redirect && Objects.equals(flags, that.flags) && Objects.equals(prefixes, that.prefixes);
81+
}
82+
83+
@Override
84+
public int hashCode() {
85+
return Objects.hash(flags, redirect, prefixes);
86+
}
87+
88+
/**
89+
* CLIENT TRACKINGINFO flags
90+
*
91+
* @see <a href="https://redis.io/docs/latest/commands/client-trackinginfo/">CLIENT TRACKINGINFO</a>
92+
*/
93+
public enum TrackingFlag {
94+
95+
/**
96+
* The connection isn't using server assisted client side caching.
97+
*/
98+
OFF,
99+
/**
100+
* Server assisted client side caching is enabled for the connection.
101+
*/
102+
ON,
103+
/**
104+
* The client uses broadcasting mode.
105+
*/
106+
BCAST,
107+
/**
108+
* The client does not cache keys by default.
109+
*/
110+
OPTIN,
111+
/**
112+
* The client caches keys by default.
113+
*/
114+
OPTOUT,
115+
/**
116+
* The next command will cache keys (exists only together with optin).
117+
*/
118+
CACHING_YES,
119+
/**
120+
* The next command won't cache keys (exists only together with optout).
121+
*/
122+
CACHING_NO,
123+
/**
124+
* The client isn't notified about keys modified by itself.
125+
*/
126+
NOLOOP,
127+
/**
128+
* The client ID used for redirection isn't valid anymore.
129+
*/
130+
BROKEN_REDIRECT;
131+
132+
/**
133+
* Convert a given {@link String} flag to the corresponding {@link TrackingFlag}
134+
*
135+
* @param flag a {@link String} representation of the flag
136+
* @return the resulting {@link TrackingFlag} or {@link IllegalArgumentException} if unrecognized
137+
*/
138+
public static TrackingFlag from(String flag) {
139+
switch (flag.toLowerCase()) {
140+
case "off":
141+
return OFF;
142+
case "on":
143+
return ON;
144+
case "bcast":
145+
return BCAST;
146+
case "optin":
147+
return OPTIN;
148+
case "optout":
149+
return OPTOUT;
150+
case "caching-yes":
151+
return CACHING_YES;
152+
case "caching-no":
153+
return CACHING_NO;
154+
case "noloop":
155+
return NOLOOP;
156+
case "broken_redirect":
157+
return BROKEN_REDIRECT;
158+
default:
159+
throw new RuntimeException("Unsupported flag: " + flag);
160+
}
161+
}
162+
163+
}
164+
165+
}

src/main/java/io/lettuce/core/api/async/RedisServerAsyncCommands.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import io.lettuce.core.ShutdownArgs;
3131
import io.lettuce.core.TrackingArgs;
3232
import io.lettuce.core.UnblockType;
33+
import io.lettuce.core.TrackingInfo;
3334
import io.lettuce.core.protocol.CommandType;
3435

3536
/**
@@ -177,6 +178,14 @@ public interface RedisServerAsyncCommands<K, V> {
177178
*/
178179
RedisFuture<String> clientTracking(TrackingArgs args);
179180

181+
/**
182+
* Returns information about the current client connection's use of the server assisted client side caching feature.
183+
*
184+
* @return {@link TrackingInfo}, for more information check the documentation
185+
* @since 6.5
186+
*/
187+
RedisFuture<TrackingInfo> clientTrackinginfo();
188+
180189
/**
181190
* Unblock the specified blocked client.
182191
*

src/main/java/io/lettuce/core/api/reactive/RedisServerReactiveCommands.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import io.lettuce.core.ShutdownArgs;
2929
import io.lettuce.core.TrackingArgs;
3030
import io.lettuce.core.UnblockType;
31+
import io.lettuce.core.TrackingInfo;
3132
import io.lettuce.core.protocol.CommandType;
3233
import reactor.core.publisher.Flux;
3334
import reactor.core.publisher.Mono;
@@ -177,6 +178,14 @@ public interface RedisServerReactiveCommands<K, V> {
177178
*/
178179
Mono<String> clientTracking(TrackingArgs args);
179180

181+
/**
182+
* Returns information about the current client connection's use of the server assisted client side caching feature.
183+
*
184+
* @return {@link TrackingInfo}, for more information check the documentation
185+
* @since 6.5
186+
*/
187+
Mono<TrackingInfo> clientTrackinginfo();
188+
180189
/**
181190
* Unblock the specified blocked client.
182191
*

src/main/java/io/lettuce/core/api/sync/RedisServerCommands.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import io.lettuce.core.KillArgs;
2929
import io.lettuce.core.ShutdownArgs;
3030
import io.lettuce.core.TrackingArgs;
31+
import io.lettuce.core.TrackingInfo;
3132
import io.lettuce.core.UnblockType;
3233
import io.lettuce.core.protocol.CommandType;
3334

@@ -176,6 +177,14 @@ public interface RedisServerCommands<K, V> {
176177
*/
177178
String clientTracking(TrackingArgs args);
178179

180+
/**
181+
* Returns information about the current client connection's use of the server assisted client side caching feature.
182+
*
183+
* @return {@link TrackingInfo}, for more information check the documentation
184+
* @since 6.5
185+
*/
186+
TrackingInfo clientTrackinginfo();
187+
179188
/**
180189
* Unblock the specified blocked client.
181190
*

src/main/java/io/lettuce/core/cluster/api/async/NodeSelectionServerAsyncCommands.java

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@
1919
*/
2020
package io.lettuce.core.cluster.api.async;
2121

22-
import java.util.Date;
23-
import java.util.List;
2422
import java.util.Map;
25-
23+
import java.util.List;
24+
import java.util.Date;
2625
import io.lettuce.core.ClientListArgs;
2726
import io.lettuce.core.FlushMode;
2827
import io.lettuce.core.KillArgs;
2928
import io.lettuce.core.TrackingArgs;
3029
import io.lettuce.core.UnblockType;
30+
import io.lettuce.core.TrackingInfo;
3131
import io.lettuce.core.protocol.CommandType;
3232

3333
/**
@@ -175,6 +175,14 @@ public interface NodeSelectionServerAsyncCommands<K, V> {
175175
*/
176176
AsyncExecutions<String> clientTracking(TrackingArgs args);
177177

178+
/**
179+
* Returns information about the current client connection's use of the server assisted client side caching feature.
180+
*
181+
* @return {@link TrackingInfo}, for more information check the documentation
182+
* @since 6.5
183+
*/
184+
AsyncExecutions<TrackingInfo> clientTrackinginfo();
185+
178186
/**
179187
* Unblock the specified blocked client.
180188
*

src/main/java/io/lettuce/core/cluster/api/sync/NodeSelectionServerCommands.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import io.lettuce.core.KillArgs;
2929
import io.lettuce.core.TrackingArgs;
3030
import io.lettuce.core.UnblockType;
31+
import io.lettuce.core.TrackingInfo;
3132
import io.lettuce.core.protocol.CommandType;
3233

3334
/**
@@ -163,7 +164,7 @@ public interface NodeSelectionServerCommands<K, V> {
163164
* @return simple-string-reply {@code OK} if the connection name was successfully set.
164165
* @since 6.3
165166
*/
166-
Executions<String> clientSetinfo(String key, V value);
167+
Executions<String> clientSetinfo(String key, String value);
167168

168169
/**
169170
* Enables the tracking feature of the Redis server, that is used for server assisted client side caching. Tracking messages
@@ -175,6 +176,14 @@ public interface NodeSelectionServerCommands<K, V> {
175176
*/
176177
Executions<String> clientTracking(TrackingArgs args);
177178

179+
/**
180+
* Returns information about the current client connection's use of the server assisted client side caching feature.
181+
*
182+
* @return {@link TrackingInfo}, for more information check the documentation
183+
* @since 6.5
184+
*/
185+
Executions<TrackingInfo> clientTrackinginfo();
186+
178187
/**
179188
* Unblock the specified blocked client.
180189
*

0 commit comments

Comments
 (0)