diff --git a/docs/src/content/docs/valkey/drivers.md b/docs/src/content/docs/valkey/drivers.md
index b5aa29ef..c4db4d2f 100644
--- a/docs/src/content/docs/valkey/drivers.md
+++ b/docs/src/content/docs/valkey/drivers.md
@@ -73,7 +73,7 @@ The following overview explains features that are supported by the individual Va
io.valkey
valkey-glide
- 2.4.0
+ ${version}
```
@@ -136,7 +136,7 @@ For more detailed client configuration options, see `io.valkey.springframework.d
io.lettuce
lettuce-core
- 6.3.2.RELEASE
+ ${version}
@@ -212,7 +212,7 @@ Netty currently supports the epoll (Linux) and kqueue (BSD/macOS) interfaces for
valkey.clients
jedis
- 5.1.2
+ ${version}
diff --git a/pom.xml b/pom.xml
index f099cf44..ebc6e885 100644
--- a/pom.xml
+++ b/pom.xml
@@ -30,7 +30,7 @@
4.1.0
- 2.4.2
+ 2.5.2
7.5.2.RELEASE
7.4.1
2.12.0
diff --git a/spring-data-valkey/src/main/java/io/valkey/springframework/data/valkey/connection/valkeyglide/ClusterGlideClientAdapter.java b/spring-data-valkey/src/main/java/io/valkey/springframework/data/valkey/connection/valkeyglide/ClusterGlideClientAdapter.java
index 223be4d1..cbc24a2a 100644
--- a/spring-data-valkey/src/main/java/io/valkey/springframework/data/valkey/connection/valkeyglide/ClusterGlideClientAdapter.java
+++ b/spring-data-valkey/src/main/java/io/valkey/springframework/data/valkey/connection/valkeyglide/ClusterGlideClientAdapter.java
@@ -175,8 +175,8 @@ else if (!password.equals(ValkeyPassword.none())) {
subConfigBuilder.callback((msg, context) -> this.listener.onMessage(msg, context));
configBuilder.subscriptionConfiguration(subConfigBuilder.build());
- // Set library name for server-side client identification
- configBuilder.libName("GlideSpringDataValkey");
+ // Report as GlideJava(SpringDataValkey), preserving the underlying driver identity.
+ configBuilder.clientInfoTag(CLIENT_INFO_TAG);
// Build and create cluster client
GlideClusterClientConfiguration config = configBuilder.build();
@@ -415,8 +415,11 @@ public Object customCommand(GlideString[] args) throws InterruptedException, Exe
ClusterValue> clusterValue = nextCommandRoute == null ? glideClusterClient.customCommand(args).get()
: glideClusterClient.customCommand(args, nextCommandRoute).get();
- // Case 1: Explicit multi-node route - return multiValue for aggregation
- if (needToAggregateResult(nextCommandRoute)) {
+ // Case 1: Explicit multi-node route - return multiValue for aggregation.
+ // Guard with hasMultiData(): some commands routed to all primaries (e.g. SAVE)
+ // return a single value rather than a per-node map, in which case we fall
+ // through to single-value handling instead of failing.
+ if (needToAggregateResult(nextCommandRoute) && clusterValue.hasMultiData()) {
return clusterValue.getMultiValue();
}
diff --git a/spring-data-valkey/src/main/java/io/valkey/springframework/data/valkey/connection/valkeyglide/StandaloneGlideClientAdapter.java b/spring-data-valkey/src/main/java/io/valkey/springframework/data/valkey/connection/valkeyglide/StandaloneGlideClientAdapter.java
index 37bb5928..78a54e2c 100644
--- a/spring-data-valkey/src/main/java/io/valkey/springframework/data/valkey/connection/valkeyglide/StandaloneGlideClientAdapter.java
+++ b/spring-data-valkey/src/main/java/io/valkey/springframework/data/valkey/connection/valkeyglide/StandaloneGlideClientAdapter.java
@@ -163,8 +163,8 @@ else if (!password.equals(ValkeyPassword.none())) {
subConfigBuilder.callback((msg, context) -> this.listener.onMessage(msg, context));
configBuilder.subscriptionConfiguration(subConfigBuilder.build());
- // Set library name for server-side client identification
- configBuilder.libName("GlideSpringDataValkey");
+ // Report as GlideJava(SpringDataValkey), preserving the underlying driver identity.
+ configBuilder.clientInfoTag(CLIENT_INFO_TAG);
// Build and create client
GlideClientConfiguration config = configBuilder.build();
diff --git a/spring-data-valkey/src/main/java/io/valkey/springframework/data/valkey/connection/valkeyglide/UnifiedGlideClient.java b/spring-data-valkey/src/main/java/io/valkey/springframework/data/valkey/connection/valkeyglide/UnifiedGlideClient.java
index 58e73f28..50661f18 100644
--- a/spring-data-valkey/src/main/java/io/valkey/springframework/data/valkey/connection/valkeyglide/UnifiedGlideClient.java
+++ b/spring-data-valkey/src/main/java/io/valkey/springframework/data/valkey/connection/valkeyglide/UnifiedGlideClient.java
@@ -29,6 +29,12 @@
*/
interface UnifiedGlideClient extends AutoCloseable {
+ /**
+ * Client information tag reported to the server via GLIDE's {@code clientInfoTag}, producing a
+ * lib-name of {@code GlideJava(SpringDataValkey)} for server-side identification.
+ */
+ String CLIENT_INFO_TAG = "SpringDataValkey";
+
public enum BatchStatus {
None, Pipeline, Transaction,
diff --git a/spring-data-valkey/src/main/java/io/valkey/springframework/data/valkey/connection/valkeyglide/ValkeyGlideClusterServerCommands.java b/spring-data-valkey/src/main/java/io/valkey/springframework/data/valkey/connection/valkeyglide/ValkeyGlideClusterServerCommands.java
index 53f9c1c7..fa366138 100644
--- a/spring-data-valkey/src/main/java/io/valkey/springframework/data/valkey/connection/valkeyglide/ValkeyGlideClusterServerCommands.java
+++ b/spring-data-valkey/src/main/java/io/valkey/springframework/data/valkey/connection/valkeyglide/ValkeyGlideClusterServerCommands.java
@@ -76,9 +76,12 @@ public Long lastSave() {
(Map rawResult) -> rawResult.isEmpty() ? null : Collections.max(rawResult.values()));
}
+ @Override
public void save() {
- // valkey-glide default route is "random", so we specify ALL_PRIMARIES
- connection.execute(SimpleMultiNodeRoute.ALL_PRIMARIES, "SAVE", (Map rawResult) -> null);
+ // valkey-glide default route is "random", so we specify ALL_PRIMARIES.
+ // GLIDE 2.5.x aggregates SAVE to a single value (rather than a per-node map);
+ // the response is discarded, so accept Object.
+ connection.execute(SimpleMultiNodeRoute.ALL_PRIMARIES, "SAVE", (Object rawResult) -> null);
}
@Override
diff --git a/spring-data-valkey/src/test/java/io/valkey/springframework/data/valkey/connection/valkeyglide/ValkeyGlideConnectionClusterServerCommandsIntegrationTests.java b/spring-data-valkey/src/test/java/io/valkey/springframework/data/valkey/connection/valkeyglide/ValkeyGlideConnectionClusterServerCommandsIntegrationTests.java
index 77a9e375..f805a608 100644
--- a/spring-data-valkey/src/test/java/io/valkey/springframework/data/valkey/connection/valkeyglide/ValkeyGlideConnectionClusterServerCommandsIntegrationTests.java
+++ b/spring-data-valkey/src/test/java/io/valkey/springframework/data/valkey/connection/valkeyglide/ValkeyGlideConnectionClusterServerCommandsIntegrationTests.java
@@ -478,7 +478,8 @@ void testGetClientListOnSpecificNode() {
@EnabledOnValkeyVersion("7.2")
void testClientLibNameReported() {
List clientList = clusterConnection.serverCommands().getClientList();
- assertThat(clientList).anyMatch(client -> "GlideSpringDataValkey".equals(client.get("lib-name")));
+ assertThat(clientList).anyMatch(
+ client -> client.get("lib-name") != null && client.get("lib-name").contains("(SpringDataValkey)"));
}
// ==================== Cluster-Wide Routing and Aggregation Verification
diff --git a/spring-data-valkey/src/test/java/io/valkey/springframework/data/valkey/connection/valkeyglide/ValkeyGlideConnectionServerCommandsIntegrationTests.java b/spring-data-valkey/src/test/java/io/valkey/springframework/data/valkey/connection/valkeyglide/ValkeyGlideConnectionServerCommandsIntegrationTests.java
index 26693718..6de5cb91 100644
--- a/spring-data-valkey/src/test/java/io/valkey/springframework/data/valkey/connection/valkeyglide/ValkeyGlideConnectionServerCommandsIntegrationTests.java
+++ b/spring-data-valkey/src/test/java/io/valkey/springframework/data/valkey/connection/valkeyglide/ValkeyGlideConnectionServerCommandsIntegrationTests.java
@@ -481,7 +481,8 @@ void testGetClientList() {
@EnabledOnValkeyVersion("7.2")
void testClientLibNameReported() {
List clientList = connection.serverCommands().getClientList();
- assertThat(clientList).anyMatch(client -> "GlideSpringDataValkey".equals(client.get("lib-name")));
+ assertThat(clientList).anyMatch(
+ client -> client.get("lib-name") != null && client.get("lib-name").contains("(SpringDataValkey)"));
}
@Test