Skip to content

Commit e8cd9b2

Browse files
Expose method to add upstream driver libraries to CLIENT SETINFO payload (#4373)
* Expose method to add upstream driver libraries to CLIENT SETINFO payload * Apply formatting * Address PR feedback * enforce formating * Remove licensing header as per PR feedback --------- Co-authored-by: ggivo <[email protected]>
1 parent ff20d72 commit e8cd9b2

File tree

7 files changed

+646
-80
lines changed

7 files changed

+646
-80
lines changed

pom.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,9 @@
547547
<include>**/*CompareCondition*.java</include>
548548
<include>**/*MSetExParams*.java</include>
549549
<include>**/*UnitTest.java</include>
550+
<include>**/DriverInfo.java</include>
551+
<include>**/ClientSetInfo*.java</include>
552+
<include>**/ClientCommandsTest*.java</include>
550553
</includes>
551554
</configuration>
552555
<executions>

src/main/java/redis/clients/jedis/ClientSetInfoConfig.java

Lines changed: 96 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,132 @@
11
package redis.clients.jedis;
22

3-
import java.util.Arrays;
4-
import java.util.HashSet;
53
import redis.clients.jedis.exceptions.JedisValidationException;
64

5+
/**
6+
* Configuration for CLIENT SETINFO command behaviour.
7+
* <p>
8+
* This class supports two modes of operation:
9+
* <ul>
10+
* <li>Advanced mode: Using {@link #withLibNameSuffix(String)} for advanced suffix customization,
11+
* where the provided string is already preformatted according to the rules of the `CLIENT SETINFO`
12+
* command</li>
13+
* <li>Simple mode: Using {@link #ClientSetInfoConfig(DriverInfo)} used when the command parameter
14+
* will be built by the driver based on the {@link DriverInfo} provided</li>
15+
* </ul>
16+
* <p>
17+
* For backward compatibility, {@link #getUpstreamDrivers()} returns the upstream drivers string
18+
* when using driver info mode.
19+
* @see DriverInfo
20+
* @see <a href="https://redis.io/docs/latest/commands/client-setinfo/">CLIENT SETINFO</a>
21+
*/
722
public final class ClientSetInfoConfig {
823

924
private final boolean disabled;
1025

11-
private final String libNameSuffix;
26+
private final DriverInfo driverInfo;
1227

28+
/**
29+
* Creates a new ClientSetInfoConfig with default settings.
30+
* <p>
31+
* The default configuration uses the "jedis" library name without any upstream drivers.
32+
*/
1333
public ClientSetInfoConfig() {
14-
this(false, null);
34+
this(false);
1535
}
1636

37+
/**
38+
* Creates a new ClientSetInfoConfig with the specified disabled state.
39+
* <p>
40+
* When disabled, the CLIENT SETINFO command will not be sent to Redis.
41+
* @param disabled {@code true} to disable CLIENT SETINFO, {@code false} otherwise
42+
*/
1743
public ClientSetInfoConfig(boolean disabled) {
18-
this(disabled, null);
44+
this.disabled = disabled;
45+
this.driverInfo = DriverInfo.builder().build();
1946
}
2047

2148
/**
22-
* @param libNameSuffix must not have braces ({@code ()[]{}}) and spaces will be replaced with hyphens
49+
* Creates a new ClientSetInfoConfig with a library name suffix.
50+
* <p>
51+
* This constructor is for legacy compatibility. The suffix will be appended to "jedis" in
52+
* parentheses, resulting in a format like: {@code jedis(suffix)}.
53+
* <p>
54+
* For adding upstream driver information, use {@link #ClientSetInfoConfig(DriverInfo)} with a
55+
* {@link DriverInfo} that has upstream drivers.
56+
* @param libNameSuffix the suffix to append to "jedis" (will be placed in parentheses)
57+
* @throws JedisValidationException if libNameSuffix contains braces
2358
*/
2459
public ClientSetInfoConfig(String libNameSuffix) {
25-
this(false, libNameSuffix);
60+
this.disabled = false;
61+
this.driverInfo = DriverInfo.builder().addUpstreamDriver(libNameSuffix).build();
2662
}
2763

28-
private ClientSetInfoConfig(boolean disabled, String libNameSuffix) {
29-
this.disabled = disabled;
30-
this.libNameSuffix = validateLibNameSuffix(libNameSuffix);
31-
}
32-
33-
private static final HashSet<Character> BRACES = new HashSet<>(Arrays.asList('(', ')', '[', ']', '{', '}'));
34-
35-
private static String validateLibNameSuffix(String suffix) {
36-
if (suffix == null || suffix.trim().isEmpty()) {
37-
return null;
38-
}
39-
40-
for (int i = 0; i < suffix.length(); i++) {
41-
char c = suffix.charAt(i);
42-
if (c < ' ' || c > '~' || BRACES.contains(c)) {
43-
throw new JedisValidationException("lib-name suffix cannot contain braces, newlines or "
44-
+ "special characters.");
45-
}
64+
/**
65+
* Creates a new ClientSetInfoConfig with the specified driver information.
66+
* <p>
67+
* This is the recommended constructor for setting up driver information with upstream drivers.
68+
* The driver information can optionally override the library name completely.
69+
* @param driverInfo the driver information, must not be {@code null}
70+
* @throws JedisValidationException if driverInfo is {@code null}
71+
*/
72+
public ClientSetInfoConfig(DriverInfo driverInfo) {
73+
if (driverInfo == null) {
74+
throw new JedisValidationException("DriverInfo must not be null");
4675
}
47-
48-
return suffix.replaceAll("\\s", "-");
76+
this.disabled = false;
77+
this.driverInfo = driverInfo;
4978
}
5079

51-
public final boolean isDisabled() {
80+
/**
81+
* @return {@code true} if CLIENT SETINFO is disabled, {@code false} otherwise
82+
*/
83+
public boolean isDisabled() {
5284
return disabled;
5385
}
5486

55-
public final String getLibNameSuffix() {
56-
return libNameSuffix;
87+
/**
88+
* @return the driver information
89+
*/
90+
public DriverInfo getDriverInfo() {
91+
return driverInfo;
5792
}
5893

94+
/**
95+
* Returns the formatted upstream drivers string.
96+
* <p>
97+
* Multiple drivers are separated by semicolons, with the most recently added driver appearing
98+
* first.
99+
* <p>
100+
* Examples:
101+
* <ul>
102+
* <li>{@code "spring-data-redis_v3.2.0"} - single upstream driver</li>
103+
* <li>{@code "lettuce-core_v6.4.1;spring-data-redis_v3.2.0"} - multiple upstream drivers</li>
104+
* </ul>
105+
* @return the formatted upstream drivers string, or {@code null} if no upstream drivers are set
106+
*/
107+
public String getUpstreamDrivers() {
108+
return driverInfo.getUpstreamDrivers();
109+
}
110+
111+
/**
112+
* Default configuration that uses the Jedis library name without any upstream drivers.
113+
*/
59114
public static final ClientSetInfoConfig DEFAULT = new ClientSetInfoConfig();
60115

116+
/**
117+
* Configuration that disables CLIENT SETINFO command.
118+
*/
61119
public static final ClientSetInfoConfig DISABLED = new ClientSetInfoConfig(true);
62120

63121
/**
64-
* @param suffix must not have braces ({@code ()[]{}}) and spaces will be replaced with hyphens
65-
* @return config
122+
* Creates a new ClientSetInfoConfig with a library name suffix.
123+
* <p>
124+
* This is the legacy method for simple name customization. The provided suffix will be appended
125+
* to "jedis" in parentheses, resulting in a format like: {@code jedis(suffix)}. For adding
126+
* upstream driver information, use {@link #ClientSetInfoConfig(DriverInfo)} with a *
127+
* {@link DriverInfo} that has upstream drivers.
128+
* @param suffix the suffix to append to "jedis" (will be placed in parentheses)
129+
* @return a new ClientSetInfoConfig with the library name suffix
66130
*/
67131
public static ClientSetInfoConfig withLibNameSuffix(String suffix) {
68132
return new ClientSetInfoConfig(suffix);

src/main/java/redis/clients/jedis/Connection.java

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -542,20 +542,15 @@ protected void initializeFromClientConfig(final JedisClientConfig config) {
542542
}
543543

544544
if (!setInfoConfig.isDisabled()) {
545-
String libName = JedisMetaInfo.getArtifactId();
546-
if (libName != null && validateClientInfo(libName)) {
547-
String libNameSuffix = setInfoConfig.getLibNameSuffix();
548-
if (libNameSuffix != null) { // validation is moved into ClientSetInfoConfig constructor
549-
libName = libName + '(' + libNameSuffix + ')';
550-
}
551-
fireAndForgetMsg.add(new CommandArguments(Command.CLIENT).add(Keyword.SETINFO)
552-
.add(ClientAttributeOption.LIB_NAME.getRaw()).add(libName));
553-
}
545+
fireAndForgetMsg.add(
546+
new CommandArguments(Command.CLIENT).add(Keyword.SETINFO).add(ClientAttributeOption.LIB_NAME.getRaw())
547+
.add(setInfoConfig.getDriverInfo().getFormattedName()));
554548

555549
String libVersion = JedisMetaInfo.getVersion();
556550
if (libVersion != null && validateClientInfo(libVersion)) {
557-
fireAndForgetMsg.add(new CommandArguments(Command.CLIENT).add(Keyword.SETINFO)
558-
.add(ClientAttributeOption.LIB_VER.getRaw()).add(libVersion));
551+
fireAndForgetMsg.add(
552+
new CommandArguments(Command.CLIENT).add(Keyword.SETINFO).add(ClientAttributeOption.LIB_VER.getRaw())
553+
.add(libVersion));
559554
}
560555
}
561556

0 commit comments

Comments
 (0)