diff --git a/.github/workflows/ort.yml b/.github/workflows/ort.yml
index 3270b2052f..014db6da9b 100644
--- a/.github/workflows/ort.yml
+++ b/.github/workflows/ort.yml
@@ -28,6 +28,7 @@ jobs:
PYTHON_ATTRIBUTIONS: "python/THIRD_PARTY_LICENSES_PYTHON"
NODE_ATTRIBUTIONS: "node/THIRD_PARTY_LICENSES_NODE"
RUST_ATTRIBUTIONS: "glide-core/THIRD_PARTY_LICENSES_RUST"
+ JAVA_ATTRIBUTIONS: "java/THIRD_PARTY_LICENSES_JAVA"
steps:
- name: Set the release version
shell: bash
@@ -158,6 +159,19 @@ jobs:
with:
folder_path: "${{ github.workspace }}/glide-core"
+ ### Java ###
+
+ - name: Set up JDK 11
+ uses: actions/setup-java@v4
+ with:
+ distribution: "temurin"
+ java-version: 11
+
+ - name: Run ORT tools for Java
+ uses: ./.github/workflows/run-ort-tools
+ with:
+ folder_path: "${{ github.workspace }}/java"
+
### Process results ###
- name: Check for diff
@@ -165,7 +179,8 @@ jobs:
cp python/ort_results/NOTICE_DEFAULT $PYTHON_ATTRIBUTIONS
cp node/ort_results/NOTICE_DEFAULT $NODE_ATTRIBUTIONS
cp glide-core/ort_results/NOTICE_DEFAULT $RUST_ATTRIBUTIONS
- GIT_DIFF=`git diff $PYTHON_ATTRIBUTIONS $NODE_ATTRIBUTIONS $RUST_ATTRIBUTIONS`
+ cp java/ort_results/NOTICE_DEFAULT $JAVA_ATTRIBUTIONS
+ GIT_DIFF=`git diff $PYTHON_ATTRIBUTIONS $NODE_ATTRIBUTIONS $RUST_ATTRIBUTIONS $JAVA_ATTRIBUTIONS`
if [ -n "$GIT_DIFF" ]; then
echo "FOUND_DIFF=true" >> $GITHUB_ENV
else
@@ -191,7 +206,7 @@ jobs:
git config --global user.email "glide-for-redis@amazon.com"
git config --global user.name "ort-bot"
git checkout -b ${BRANCH_NAME}
- git add $PYTHON_ATTRIBUTIONS $NODE_ATTRIBUTIONS $RUST_ATTRIBUTIONS
+ git add $PYTHON_ATTRIBUTIONS $NODE_ATTRIBUTIONS $RUST_ATTRIBUTIONS $JAVA_ATTRIBUTIONS
git commit -m "Updated attribution files"
git push --set-upstream origin ${BRANCH_NAME} -f
title="Updated attribution files for ${BRANCH_NAME}"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 995cc0f59f..f1f8511d97 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,7 @@
* Python: Added OBJECT FREQ command ([#1472](https://github.com/aws/glide-for-redis/pull/1472))
* Python: Added OBJECT IDLETIME command ([#1474](https://github.com/aws/glide-for-redis/pull/1474))
* Python: Added GEOSEARCH command ([#1482](https://github.com/aws/glide-for-redis/pull/1482))
+* Python: Added GEOSEARCHSTORE command ([#1581](https://github.com/aws/glide-for-redis/pull/1581))
* Node: Added RENAMENX command ([#1483](https://github.com/aws/glide-for-redis/pull/1483))
* Python: Added OBJECT REFCOUNT command ([#1485](https://github.com/aws/glide-for-redis/pull/1485))
* Python: Added RENAMENX command ([#1492](https://github.com/aws/glide-for-redis/pull/1492))
@@ -13,27 +14,56 @@
* Python: Added XLEN command ([#1503](https://github.com/aws/glide-for-redis/pull/1503))
* Python: Added LASTSAVE command ([#1509](https://github.com/aws/glide-for-redis/pull/1509))
* Python: Added GETDEL command ([#1514](https://github.com/aws/glide-for-redis/pull/1514))
+* Python: Added GETRANGE command ([#1585](https://github.com/aws/glide-for-redis/pull/1585))
* Python: Added ZINTER, ZUNION commands ([#1478](https://github.com/aws/glide-for-redis/pull/1478))
* Python: Added SINTERCARD command ([#1511](https://github.com/aws/glide-for-redis/pull/1511))
* Python: Added SORT command ([#1439](https://github.com/aws/glide-for-redis/pull/1439))
* Node: Added OBJECT ENCODING command ([#1518](https://github.com/aws/glide-for-redis/pull/1518), [#1559](https://github.com/aws/glide-for-redis/pull/1559))
* Python: Added LMOVE and BLMOVE commands ([#1536](https://github.com/aws/glide-for-redis/pull/1536))
* Node: Added SUNIONSTORE command ([#1549](https://github.com/aws/glide-for-redis/pull/1549))
+* Python: Added SUNION command ([#1583](https://github.com/aws/glide-for-redis/pull/1583))
* Node: Added PFCOUNT command ([#1545](https://github.com/aws/glide-for-redis/pull/1545))
* Node: Added OBJECT FREQ command ([#1542](https://github.com/aws/glide-for-redis/pull/1542), [#1559](https://github.com/aws/glide-for-redis/pull/1559))
* Node: Added LINSERT command ([#1544](https://github.com/aws/glide-for-redis/pull/1544))
* Node: Added XLEN command ([#1555](https://github.com/aws/glide-for-redis/pull/1555))
* Node: Added ZINTERCARD command ([#1553](https://github.com/aws/glide-for-redis/pull/1553))
+* Python: Added ZINCBY command ([#1586](https://github.com/aws/glide-for-redis/pull/1586))
* Python: Added LMPOP and BLMPOP commands ([#1547](https://github.com/aws/glide-for-redis/pull/1547))
+* Python: Added HSTRLEN command ([#1564](https://github.com/aws/glide-for-redis/pull/1564))
* Python: Added MSETNX command ([#1565](https://github.com/aws/glide-for-redis/pull/1565))
* Python: Added MOVE command ([#1566](https://github.com/aws/glide-for-redis/pull/1566))
+* Python: Added EXPIRETIME, PEXPIRETIME commands ([#1587](https://github.com/aws/glide-for-redis/pull/1587))
+* Python: Added LSET command ([#1584](https://github.com/aws/glide-for-redis/pull/1584))
* Node: Added OBJECT IDLETIME command ([#1567](https://github.com/aws/glide-for-redis/pull/1567))
* Node: Added OBJECT REFCOUNT command ([#1568](https://github.com/aws/glide-for-redis/pull/1568))
* Python: Added SETBIT command ([#1571](https://github.com/aws/glide-for-redis/pull/1571))
+* Python: Added SRandMember command ([#1578](https://github.com/aws/glide-for-redis/pull/1578))
+* Python: Added GETBIT command ([#1575](https://github.com/aws/glide-for-redis/pull/1575))
+* Python: Added BITCOUNT command ([#1592](https://github.com/aws/glide-for-redis/pull/1592))
+* Python: Added FLUSHALL command ([#1579](https://github.com/aws/glide-for-redis/pull/1579))
+* Python: Added TOUCH command ([#1582](https://github.com/aws/glide-for-redis/pull/1582))
+* Python: Added BITOP command ([#1596](https://github.com/aws/glide-for-redis/pull/1596))
+* Python: Added BITPOS command ([#1604](https://github.com/aws/glide-for-redis/pull/1604))
+* Python: Added GETEX command ([#1612](https://github.com/aws/glide-for-redis/pull/1612))
+* Python: Added BITFIELD and BITFIELD_RO commands ([#1615](https://github.com/aws/glide-for-redis/pull/1615))
+* Python: Added ZREVRANK command ([#1614](https://github.com/aws/glide-for-redis/pull/1614))
+* Python: Added XDEL command ([#1619](https://github.com/aws/glide-for-redis/pull/1619))
+* Python: Added XRANGE command ([#1624](https://github.com/aws/glide-for-redis/pull/1624))
+* Python: Added COPY command ([#1626](https://github.com/aws/glide-for-redis/pull/1626))
+* Python: Added XREVRANGE command ([#1625](https://github.com/aws/glide-for-redis/pull/1625))
+* Python: Added XREAD command ([#1644](https://github.com/aws/glide-for-redis/pull/1644))
+* Python: Added XGROUP CREATE and XGROUP DESTROY commands ([#1646](https://github.com/aws/glide-for-redis/pull/1646))
+* Python: Added XGROUP CREATECONSUMER and XGROUP DELCONSUMER commands ([#1658](https://github.com/aws/glide-for-redis/pull/1658))
+* Python: Added LOLWUT command ([#1657](https://github.com/aws/glide-for-redis/pull/1657))
+* Python: Added XREADGROUP command ([#1679](https://github.com/aws/glide-for-redis/pull/1679))
+* Python: Added XACK command ([#1681](https://github.com/aws/glide-for-redis/pull/1681))
+* Python: Added FLUSHDB command ([#1680](https://github.com/aws/glide-for-redis/pull/1680))
* Python: Added FUNCTION LOAD command ([#1699](https://github.com/aws/glide-for-redis/pull/1699))
### Breaking Changes
* Node: Update XREAD to return a Map of Map ([#1494](https://github.com/aws/glide-for-redis/pull/1494))
+* Node: Rename RedisClient to GlideClient and RedisClusterClient to GlideClusterClient ([#1670](https://github.com/aws/glide-for-redis/pull/1670))
+* Python: Rename RedisClient to GlideClient, RedisClusterClient to GlideClusterClient and BaseRedisClient to BaseClient([#1669](https://github.com/aws/glide-for-redis/pull/1669))
## 0.4.1 (2024-02-06)
diff --git a/benchmarks/csharp/Program.cs b/benchmarks/csharp/Program.cs
index 84a785aac5..3a3e8a6f08 100644
--- a/benchmarks/csharp/Program.cs
+++ b/benchmarks/csharp/Program.cs
@@ -1,4 +1,4 @@
-// Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+// Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
using System.Collections.Concurrent;
using System.Diagnostics;
diff --git a/benchmarks/node/node_benchmark.ts b/benchmarks/node/node_benchmark.ts
index ce044cb770..1f5b70703f 100644
--- a/benchmarks/node/node_benchmark.ts
+++ b/benchmarks/node/node_benchmark.ts
@@ -1,9 +1,9 @@
/**
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
import { writeFileSync } from "fs";
-import { Logger, RedisClient, RedisClusterClient } from "glide-for-redis";
+import { GlideClient, GlideClusterClient, Logger } from "glide-for-redis";
import { Cluster, Redis } from "ioredis";
import { parse } from "path";
import percentile from "percentile";
@@ -216,8 +216,8 @@ async function main(
if (clientsToRun == "all" || clientsToRun == "glide") {
const clientClass = clusterModeEnabled
- ? RedisClusterClient
- : RedisClient;
+ ? GlideClusterClient
+ : GlideClient;
const clients = await createClients(clientCount, () =>
clientClass.createClient({
addresses: [{ host, port }],
@@ -232,7 +232,7 @@ async function main(
dataSize,
data,
(client) => {
- (client as RedisClient).close();
+ (client as GlideClient).close();
},
clusterModeEnabled,
);
@@ -240,11 +240,11 @@ async function main(
}
if (clientsToRun == "all") {
- const nodeRedisClients = await createClients(clientCount, async () => {
+ const nodeGlideClients = await createClients(clientCount, async () => {
const node = {
url: getAddress(host, useTLS, port),
};
- const nodeRedisClient = clusterModeEnabled
+ const nodeGlideClient = clusterModeEnabled
? createCluster({
rootNodes: [{ socket: { host, port, tls: useTLS } }],
defaults: {
@@ -255,11 +255,11 @@ async function main(
useReplicas: true,
})
: createClient(node);
- await nodeRedisClient.connect();
- return nodeRedisClient;
+ await nodeGlideClient.connect();
+ return nodeGlideClient;
});
await runClients(
- nodeRedisClients,
+ nodeGlideClients,
"node_redis",
totalCommands,
numOfConcurrentTasks,
diff --git a/benchmarks/python/python_benchmark.py b/benchmarks/python/python_benchmark.py
index 29262764eb..1da52f9941 100644
--- a/benchmarks/python/python_benchmark.py
+++ b/benchmarks/python/python_benchmark.py
@@ -1,4 +1,4 @@
-# Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+# Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
import argparse
import asyncio
@@ -17,11 +17,11 @@
import redis.asyncio as redispy # type: ignore
from glide import (
BaseClientConfiguration,
+ GlideClient,
+ GlideClusterClient,
Logger,
LogLevel,
NodeAddress,
- RedisClient,
- RedisClusterClient,
)
@@ -288,7 +288,7 @@ async def main(
if clients_to_run == "all" or clients_to_run == "glide":
# Glide Socket
- client_class = RedisClusterClient if is_cluster else RedisClient
+ client_class = GlideClusterClient if is_cluster else GlideClient
config = BaseClientConfiguration(
[NodeAddress(host=host, port=port)], use_tls=use_tls
)
diff --git a/benchmarks/rust/src/main.rs b/benchmarks/rust/src/main.rs
index 8503375195..edace91a30 100644
--- a/benchmarks/rust/src/main.rs
+++ b/benchmarks/rust/src/main.rs
@@ -1,5 +1,5 @@
/**
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
#[cfg(not(target_env = "msvc"))]
@@ -236,7 +236,7 @@ async fn get_connection(args: &Args) -> Client {
..Default::default()
};
- glide_core::client::Client::new(connection_request)
+ glide_core::client::Client::new(connection_request, None)
.await
.unwrap()
}
diff --git a/benchmarks/utilities/csv_exporter.py b/benchmarks/utilities/csv_exporter.py
index 080aa22e4f..2841e867f6 100755
--- a/benchmarks/utilities/csv_exporter.py
+++ b/benchmarks/utilities/csv_exporter.py
@@ -1,6 +1,6 @@
#!/bin/python3
-# Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+# Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
import csv
import json
diff --git a/benchmarks/utilities/fill_db.ts b/benchmarks/utilities/fill_db.ts
index 45c1412e02..01bd29884f 100644
--- a/benchmarks/utilities/fill_db.ts
+++ b/benchmarks/utilities/fill_db.ts
@@ -1,5 +1,5 @@
/**
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
import {
diff --git a/benchmarks/utilities/flush_db.ts b/benchmarks/utilities/flush_db.ts
index b5a59cc0f2..00d2af086f 100644
--- a/benchmarks/utilities/flush_db.ts
+++ b/benchmarks/utilities/flush_db.ts
@@ -1,5 +1,5 @@
/**
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
import { RedisClientType, RedisClusterType } from "redis";
diff --git a/benchmarks/utilities/utils.ts b/benchmarks/utilities/utils.ts
index 140dd4fadd..3e1c2e8014 100644
--- a/benchmarks/utilities/utils.ts
+++ b/benchmarks/utilities/utils.ts
@@ -1,5 +1,5 @@
/**
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
import commandLineArgs from "command-line-args";
diff --git a/csharp/.editorconfig b/csharp/.editorconfig
index 4a0f9f3bb6..d05fdf9728 100644
--- a/csharp/.editorconfig
+++ b/csharp/.editorconfig
@@ -7,7 +7,7 @@ indent_size = 2
[*.cs]
# License header
-file_header_template = Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+file_header_template = Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
# Organize usings
dotnet_separate_import_directive_groups = true
diff --git a/csharp/lib/AsyncClient.cs b/csharp/lib/AsyncClient.cs
index db28bd7194..3e6aab1ba8 100644
--- a/csharp/lib/AsyncClient.cs
+++ b/csharp/lib/AsyncClient.cs
@@ -1,4 +1,4 @@
-// Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+// Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
using System.Buffers;
using System.Runtime.InteropServices;
diff --git a/csharp/lib/Logger.cs b/csharp/lib/Logger.cs
index fc30584323..814737e649 100644
--- a/csharp/lib/Logger.cs
+++ b/csharp/lib/Logger.cs
@@ -1,4 +1,4 @@
-// Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+// Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
using System.Runtime.InteropServices;
diff --git a/csharp/lib/Message.cs b/csharp/lib/Message.cs
index fd6d9090f7..9e3cdd4d2e 100644
--- a/csharp/lib/Message.cs
+++ b/csharp/lib/Message.cs
@@ -1,4 +1,4 @@
-// Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+// Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
using System.Diagnostics;
using System.Runtime.CompilerServices;
diff --git a/csharp/lib/MessageContainer.cs b/csharp/lib/MessageContainer.cs
index 18073a62d2..d2baf6e2cb 100644
--- a/csharp/lib/MessageContainer.cs
+++ b/csharp/lib/MessageContainer.cs
@@ -1,4 +1,4 @@
-// Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+// Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
using System.Collections.Concurrent;
diff --git a/csharp/lib/Properties/AssemblyInfo.cs b/csharp/lib/Properties/AssemblyInfo.cs
index e7e05eb672..9ddad510f9 100644
--- a/csharp/lib/Properties/AssemblyInfo.cs
+++ b/csharp/lib/Properties/AssemblyInfo.cs
@@ -1,4 +1,4 @@
-// Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+// Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
using System.Runtime.CompilerServices;
diff --git a/csharp/lib/src/lib.rs b/csharp/lib/src/lib.rs
index fce015a376..73a4be8681 100644
--- a/csharp/lib/src/lib.rs
+++ b/csharp/lib/src/lib.rs
@@ -1,5 +1,5 @@
/**
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
use glide_core::client;
use glide_core::client::Client as GlideClient;
@@ -59,7 +59,7 @@ fn create_client_internal(
.thread_name("GLIDE for Redis C# thread")
.build()?;
let _runtime_handle = runtime.enter();
- let client = runtime.block_on(GlideClient::new(request)).unwrap(); // TODO - handle errors.
+ let client = runtime.block_on(GlideClient::new(request, None)).unwrap(); // TODO - handle errors.
Ok(Client {
client,
success_callback,
diff --git a/csharp/tests/Integration/GetAndSet.cs b/csharp/tests/Integration/GetAndSet.cs
index 78c6a74180..792741cf44 100644
--- a/csharp/tests/Integration/GetAndSet.cs
+++ b/csharp/tests/Integration/GetAndSet.cs
@@ -1,4 +1,4 @@
-// Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+// Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
using System.Runtime.InteropServices;
diff --git a/csharp/tests/Integration/IntegrationTestBase.cs b/csharp/tests/Integration/IntegrationTestBase.cs
index 2f507e0473..8e909af17e 100644
--- a/csharp/tests/Integration/IntegrationTestBase.cs
+++ b/csharp/tests/Integration/IntegrationTestBase.cs
@@ -1,4 +1,4 @@
-// Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+// Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
using System.Diagnostics;
diff --git a/csharp/tests/Usings.cs b/csharp/tests/Usings.cs
index 7bb49c0d1f..a14d42be1a 100644
--- a/csharp/tests/Usings.cs
+++ b/csharp/tests/Usings.cs
@@ -1,3 +1,3 @@
-// Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+// Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
global using Xunit;
diff --git a/examples/node/index.ts b/examples/node/index.ts
index ec4d5c9d51..ec7533f547 100644
--- a/examples/node/index.ts
+++ b/examples/node/index.ts
@@ -1,8 +1,8 @@
/**
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
-import { Logger, RedisClient, RedisClusterClient } from "@aws/glide-for-redis";
+import { GlideClient, GlideClusterClient, Logger } from "@aws/glide-for-redis";
async function sendPingToNode() {
// When in Redis is in standalone mode, add address of the primary node, and any replicas you'd like to be able to read from.
@@ -12,8 +12,8 @@ async function sendPingToNode() {
port: 6379,
},
];
- // Check `RedisClientConfiguration/ClusterClientConfiguration` for additional options.
- const client = await RedisClient.createClient({
+ // Check `GlideClientConfiguration/ClusterClientConfiguration` for additional options.
+ const client = await GlideClient.createClient({
addresses: addresses,
// if the server uses TLS, you'll need to enable it. Otherwise the connection attempt will time out silently.
// useTLS: true,
@@ -26,7 +26,7 @@ async function sendPingToNode() {
client.close();
}
-async function send_set_and_get(client: RedisClient | RedisClusterClient) {
+async function send_set_and_get(client: GlideClient | GlideClusterClient) {
const set_response = await client.set("foo", "bar");
console.log(`Set response is = ${set_response}`);
const get_response = await client.get("foo");
@@ -41,8 +41,8 @@ async function sendPingToRandomNodeInCluster() {
port: 6380,
},
];
- // Check `RedisClientConfiguration/ClusterClientConfiguration` for additional options.
- const client = await RedisClusterClient.createClient({
+ // Check `GlideClientConfiguration/ClusterClientConfiguration` for additional options.
+ const client = await GlideClusterClient.createClient({
addresses: addresses,
// if the cluster nodes use TLS, you'll need to enable it. Otherwise the connection attempt will time out silently.
// useTLS: true,
diff --git a/examples/python/client_example.py b/examples/python/client_example.py
index 7620348a5b..3d5941f4ff 100755
--- a/examples/python/client_example.py
+++ b/examples/python/client_example.py
@@ -1,4 +1,4 @@
-# Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+# Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
import asyncio
from typing import Optional, Union
@@ -6,11 +6,11 @@
from glide import (
AllNodes,
BaseClientConfiguration,
+ GlideClient,
+ GlideClusterClient,
Logger,
LogLevel,
NodeAddress,
- RedisClient,
- RedisClusterClient,
)
@@ -28,7 +28,7 @@ def set_file_logger(level: LogLevel = LogLevel.WARN, file: Optional[str] = None)
Logger.set_logger_config(level, file)
-async def send_set_and_get(client: Union[RedisClient, RedisClusterClient]):
+async def send_set_and_get(client: Union[GlideClient, GlideClusterClient]):
set_response = await client.set("foo", "bar")
print(f"Set response is = {set_response}")
get_response = await client.get("foo")
@@ -39,14 +39,14 @@ async def test_standalone_client(host: str = "localhost", port: int = 6379):
# When in Redis is in standalone mode, add address of the primary node,
# and any replicas you'd like to be able to read from.
addresses = [NodeAddress(host, port)]
- # Check `RedisClientConfiguration/ClusterClientConfiguration` for additional options.
+ # Check `GlideClientConfiguration/ClusterClientConfiguration` for additional options.
config = BaseClientConfiguration(
addresses=addresses,
- client_name="test_standalone_client"
+ client_name="test_standalone_client",
# if the server use TLS, you'll need to enable it. Otherwise the connection attempt will time out silently.
# use_tls=True
)
- client = await RedisClient.create(config)
+ client = await GlideClient.create(config)
# Send SET and GET
await send_set_and_get(client)
@@ -58,14 +58,14 @@ async def test_standalone_client(host: str = "localhost", port: int = 6379):
async def test_cluster_client(host: str = "localhost", port: int = 6379):
# When in Redis is cluster mode, add address of any nodes, and the client will find all nodes in the cluster.
addresses = [NodeAddress(host, port)]
- # Check `RedisClientConfiguration/ClusterClientConfiguration` for additional options.
+ # Check `GlideClientConfiguration/ClusterClientConfiguration` for additional options.
config = BaseClientConfiguration(
addresses=addresses,
- client_name="test_cluster_client"
+ client_name="test_cluster_client",
# if the cluster nodes use TLS, you'll need to enable it. Otherwise the connection attempt will time out silently.
# use_tls=True
)
- client = await RedisClusterClient.create(config)
+ client = await GlideClusterClient.create(config)
# Send SET and GET
await send_set_and_get(client)
diff --git a/glide-core/Cargo.toml b/glide-core/Cargo.toml
index dc623c6714..1d934fabc3 100644
--- a/glide-core/Cargo.toml
+++ b/glide-core/Cargo.toml
@@ -20,7 +20,7 @@ tokio-retry = "0.3.0"
protobuf = { version= "3", features = ["bytes", "with-bytes"], optional = true }
integer-encoding = { version = "4.0.0", optional = true }
thiserror = "1"
-rand = { version = "0.8.5", optional = true }
+rand = { version = "0.8.5" }
futures-intrusive = "0.5.0"
directories = { version = "4.0", optional = true }
once_cell = "1.18.0"
@@ -28,7 +28,7 @@ arcstr = "1.1.5"
sha1_smol = "1.0.0"
[features]
-socket-layer = ["directories", "integer-encoding", "num_cpus", "protobuf", "tokio-util", "bytes", "rand"]
+socket-layer = ["directories", "integer-encoding", "num_cpus", "protobuf", "tokio-util", "bytes"]
[dev-dependencies]
rsevents = "0.3.1"
diff --git a/glide-core/THIRD_PARTY_LICENSES_RUST b/glide-core/THIRD_PARTY_LICENSES_RUST
index e22b97f8f7..ddacaea254 100644
--- a/glide-core/THIRD_PARTY_LICENSES_RUST
+++ b/glide-core/THIRD_PARTY_LICENSES_RUST
@@ -2993,7 +2993,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
----
-Package: bitflags:2.5.0
+Package: bitflags:2.6.0
The following copyrights and licenses were found in the source code of this package:
@@ -11851,7 +11851,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
----
-Package: lazy_static:1.4.0
+Package: lazy_static:1.5.0
The following copyrights and licenses were found in the source code of this package:
@@ -13000,7 +13000,7 @@ The following copyrights and licenses were found in the source code of this pack
----
-Package: memchr:2.7.2
+Package: memchr:2.7.4
The following copyrights and licenses were found in the source code of this package:
@@ -13052,7 +13052,7 @@ For more information, please refer to
----
-Package: miniz_oxide:0.7.3
+Package: miniz_oxide:0.7.4
The following copyrights and licenses were found in the source code of this package:
@@ -17727,7 +17727,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
----
-Package: proc-macro2:1.0.85
+Package: proc-macro2:1.0.86
The following copyrights and licenses were found in the source code of this package:
@@ -18953,7 +18953,7 @@ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----
-Package: redox_syscall:0.5.1
+Package: redox_syscall:0.5.2
The following copyrights and licenses were found in the source code of this package:
@@ -22176,7 +22176,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
----
-Package: subtle:2.5.0
+Package: subtle:2.6.1
The following copyrights and licenses were found in the source code of this package:
@@ -22436,7 +22436,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
----
-Package: syn:2.0.66
+Package: syn:2.0.68
The following copyrights and licenses were found in the source code of this package:
@@ -24039,7 +24039,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
----
-Package: tinyvec:1.6.0
+Package: tinyvec:1.6.1
The following copyrights and licenses were found in the source code of this package:
diff --git a/glide-core/benches/connections_benchmark.rs b/glide-core/benches/connections_benchmark.rs
index fc98933de8..f52a91d3ca 100644
--- a/glide-core/benches/connections_benchmark.rs
+++ b/glide-core/benches/connections_benchmark.rs
@@ -1,5 +1,5 @@
/**
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
use criterion::{criterion_group, criterion_main, Criterion};
use futures::future::join_all;
@@ -83,7 +83,7 @@ fn get_connection_info(address: ConnectionAddr) -> redis::ConnectionInfo {
fn multiplexer_benchmark(c: &mut Criterion, address: ConnectionAddr, group: &str) {
benchmark(c, address, "multiplexer", group, |address, runtime| {
let client = redis::Client::open(get_connection_info(address)).unwrap();
- runtime.block_on(async { client.get_multiplexed_tokio_connection().await.unwrap() })
+ runtime.block_on(async { client.get_multiplexed_tokio_connection(None).await.unwrap() })
});
}
@@ -120,7 +120,7 @@ fn cluster_connection_benchmark(
builder = builder.read_from_replicas();
}
let client = builder.build().unwrap();
- client.get_async_connection().await
+ client.get_async_connection(None).await
})
.unwrap()
});
diff --git a/glide-core/benches/memory_benchmark.rs b/glide-core/benches/memory_benchmark.rs
index c6e307bae2..1948d9a2cd 100644
--- a/glide-core/benches/memory_benchmark.rs
+++ b/glide-core/benches/memory_benchmark.rs
@@ -1,5 +1,5 @@
/**
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
use glide_core::{
client::Client,
@@ -26,7 +26,7 @@ where
{
let runtime = Builder::new_current_thread().enable_all().build().unwrap();
runtime.block_on(async {
- let client = Client::new(create_connection_request().into())
+ let client = Client::new(create_connection_request().into(), None)
.await
.unwrap();
f(client).await;
diff --git a/glide-core/benches/rotating_buffer_benchmark.rs b/glide-core/benches/rotating_buffer_benchmark.rs
index 30f52f702f..581a278453 100644
--- a/glide-core/benches/rotating_buffer_benchmark.rs
+++ b/glide-core/benches/rotating_buffer_benchmark.rs
@@ -1,5 +1,5 @@
/**
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
use std::io::Write;
diff --git a/glide-core/build.rs b/glide-core/build.rs
index 9d41cd2491..a20b5dadea 100644
--- a/glide-core/build.rs
+++ b/glide-core/build.rs
@@ -1,5 +1,5 @@
/**
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
#[cfg(feature = "socket-layer")]
diff --git a/glide-core/src/client/mod.rs b/glide-core/src/client/mod.rs
index 3197c82a23..9961e3cf1c 100644
--- a/glide-core/src/client/mod.rs
+++ b/glide-core/src/client/mod.rs
@@ -1,5 +1,5 @@
/**
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
mod types;
@@ -9,7 +9,7 @@ use logger_core::log_info;
use redis::aio::ConnectionLike;
use redis::cluster_async::ClusterConnection;
use redis::cluster_routing::{Routable, RoutingInfo, SingleNodeRoutingInfo};
-use redis::{Cmd, ErrorKind, Value};
+use redis::{Cmd, ErrorKind, PushInfo, Value};
use redis::{RedisError, RedisResult};
pub use standalone_client::StandaloneClient;
use std::io;
@@ -21,6 +21,7 @@ use self::value_conversion::{convert_to_expected_type, expected_type_for_cmd, ge
mod reconnecting_connection;
mod standalone_client;
mod value_conversion;
+use tokio::sync::mpsc;
pub const HEARTBEAT_SLEEP_DURATION: Duration = Duration::from_secs(1);
@@ -44,6 +45,7 @@ pub(super) fn get_redis_connection_info(
let protocol = connection_request.protocol.unwrap_or_default();
let db = connection_request.database_id;
let client_name = connection_request.client_name.clone();
+ let pubsub_subscriptions = connection_request.pubsub_subscriptions.clone();
match &connection_request.authentication_info {
Some(info) => redis::RedisConnectionInfo {
db,
@@ -51,11 +53,13 @@ pub(super) fn get_redis_connection_info(
password: info.password.clone(),
protocol,
client_name,
+ pubsub_subscriptions,
},
None => redis::RedisConnectionInfo {
db,
protocol,
client_name,
+ pubsub_subscriptions,
..Default::default()
},
}
@@ -373,6 +377,7 @@ fn to_duration(time_in_millis: Option, default: Duration) -> Duration {
async fn create_cluster_client(
request: ConnectionRequest,
+ push_sender: Option>,
) -> RedisResult {
// TODO - implement timeout for each connection attempt
let tls_mode = request.tls_mode.unwrap_or_default();
@@ -410,8 +415,11 @@ async fn create_cluster_client(
};
builder = builder.tls(tls);
}
+ if let Some(pubsub_subscriptions) = redis_connection_info.pubsub_subscriptions {
+ builder = builder.pubsub_subscriptions(pubsub_subscriptions);
+ }
let client = builder.build()?;
- client.get_async_connection().await
+ client.get_async_connection(push_sender).await
}
#[derive(thiserror::Error)]
@@ -520,13 +528,22 @@ fn sanitized_request_string(request: &ConnectionRequest) -> String {
String::new()
};
+ let pubsub_subscriptions = request
+ .pubsub_subscriptions
+ .as_ref()
+ .map(|pubsub_subscriptions| format!("\nPubsub subscriptions: {pubsub_subscriptions:?}"))
+ .unwrap_or_default();
+
format!(
- "\nAddresses: {addresses}{tls_mode}{cluster_mode}{request_timeout}{rfr_strategy}{connection_retry_strategy}{database_id}{protocol}{client_name}{periodic_checks}",
+ "\nAddresses: {addresses}{tls_mode}{cluster_mode}{request_timeout}{rfr_strategy}{connection_retry_strategy}{database_id}{protocol}{client_name}{periodic_checks}{pubsub_subscriptions}",
)
}
impl Client {
- pub async fn new(request: ConnectionRequest) -> Result {
+ pub async fn new(
+ request: ConnectionRequest,
+ push_sender: Option>,
+ ) -> Result {
const DEFAULT_CLIENT_CREATION_TIMEOUT: Duration = Duration::from_secs(10);
log_info(
@@ -536,13 +553,13 @@ impl Client {
let request_timeout = to_duration(request.request_timeout, DEFAULT_RESPONSE_TIMEOUT);
tokio::time::timeout(DEFAULT_CLIENT_CREATION_TIMEOUT, async move {
let internal_client = if request.cluster_mode_enabled {
- let client = create_cluster_client(request)
+ let client = create_cluster_client(request, push_sender)
.await
.map_err(ConnectionError::Cluster)?;
ClientWrapper::Cluster { client }
} else {
ClientWrapper::Standalone(
- StandaloneClient::create_client(request)
+ StandaloneClient::create_client(request, push_sender)
.await
.map_err(ConnectionError::Standalone)?,
)
diff --git a/glide-core/src/client/reconnecting_connection.rs b/glide-core/src/client/reconnecting_connection.rs
index ac33f6c005..c76da9cf42 100644
--- a/glide-core/src/client/reconnecting_connection.rs
+++ b/glide-core/src/client/reconnecting_connection.rs
@@ -1,17 +1,18 @@
/**
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
use super::{NodeAddress, TlsMode};
use crate::retry_strategies::RetryStrategy;
use futures_intrusive::sync::ManualResetEvent;
use logger_core::{log_debug, log_trace, log_warn};
use redis::aio::MultiplexedConnection;
-use redis::{RedisConnectionInfo, RedisError, RedisResult};
+use redis::{PushInfo, RedisConnectionInfo, RedisError, RedisResult};
use std::fmt;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::sync::Mutex;
use std::time::Duration;
+use tokio::sync::mpsc;
use tokio::task;
use tokio_retry::Retry;
@@ -45,6 +46,7 @@ struct InnerReconnectingConnection {
#[derive(Clone)]
pub(super) struct ReconnectingConnection {
inner: Arc,
+ push_sender: Option>,
}
impl fmt::Debug for ReconnectingConnection {
@@ -53,10 +55,13 @@ impl fmt::Debug for ReconnectingConnection {
}
}
-async fn get_multiplexed_connection(client: &redis::Client) -> RedisResult {
+async fn get_multiplexed_connection(
+ client: &redis::Client,
+ push_sender: Option>,
+) -> RedisResult {
run_with_timeout(
Some(DEFAULT_CONNECTION_ATTEMPT_TIMEOUT),
- client.get_multiplexed_async_connection(),
+ client.get_multiplexed_async_connection(push_sender),
)
.await
}
@@ -64,9 +69,10 @@ async fn get_multiplexed_connection(client: &redis::Client) -> RedisResult>,
) -> Result {
let client = &connection_backend.connection_info;
- let action = || get_multiplexed_connection(client);
+ let action = || get_multiplexed_connection(client, push_sender.clone());
match Retry::spawn(retry_strategy.get_iterator(), action).await {
Ok(connection) => {
@@ -85,6 +91,7 @@ async fn create_connection(
state: Mutex::new(ConnectionState::Connected(connection)),
backend: connection_backend,
}),
+ push_sender,
})
}
Err(err) => {
@@ -103,6 +110,7 @@ async fn create_connection(
state: Mutex::new(ConnectionState::InitializedDisconnected),
backend: connection_backend,
}),
+ push_sender,
};
connection.reconnect();
Err((connection, err))
@@ -141,6 +149,7 @@ impl ReconnectingConnection {
connection_retry_strategy: RetryStrategy,
redis_connection_info: RedisConnectionInfo,
tls_mode: TlsMode,
+ push_sender: Option>,
) -> Result {
log_debug(
"connection creation",
@@ -153,7 +162,7 @@ impl ReconnectingConnection {
connection_available_signal: ManualResetEvent::new(true),
client_dropped_flagged: AtomicBool::new(false),
};
- create_connection(backend, connection_retry_strategy).await
+ create_connection(backend, connection_retry_strategy, push_sender).await
}
fn node_address(&self) -> String {
@@ -211,6 +220,7 @@ impl ReconnectingConnection {
log_debug("reconnect", "starting");
let connection_clone = self.clone();
+ let push_sender = self.push_sender.clone();
// The reconnect task is spawned instead of awaited here, so that the reconnect attempt will continue in the
// background, regardless of whether the calling task is dropped or not.
task::spawn(async move {
@@ -224,7 +234,7 @@ impl ReconnectingConnection {
// Client was dropped, reconnection attempts can stop
return;
}
- match get_multiplexed_connection(client).await {
+ match get_multiplexed_connection(client, push_sender.clone()).await {
Ok(mut connection) => {
if connection
.send_packed_command(&redis::cmd("PING"))
diff --git a/glide-core/src/client/standalone_client.rs b/glide-core/src/client/standalone_client.rs
index 736155bbf0..f59e18eac8 100644
--- a/glide-core/src/client/standalone_client.rs
+++ b/glide-core/src/client/standalone_client.rs
@@ -1,5 +1,5 @@
/**
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
use super::get_redis_connection_info;
use super::reconnecting_connection::ReconnectingConnection;
@@ -9,10 +9,12 @@ use futures::{future, stream, StreamExt};
#[cfg(standalone_heartbeat)]
use logger_core::log_debug;
use logger_core::log_warn;
+use rand::Rng;
use redis::cluster_routing::{self, is_readonly_cmd, ResponsePolicy, Routable, RoutingInfo};
-use redis::{RedisError, RedisResult, Value};
+use redis::{PushInfo, RedisError, RedisResult, Value};
use std::sync::atomic::AtomicUsize;
use std::sync::Arc;
+use tokio::sync::mpsc;
#[cfg(standalone_heartbeat)]
use tokio::task;
@@ -96,22 +98,33 @@ impl std::fmt::Debug for StandaloneClientConnectionError {
impl StandaloneClient {
pub async fn create_client(
connection_request: ConnectionRequest,
+ push_sender: Option>,
) -> Result {
if connection_request.addresses.is_empty() {
return Err(StandaloneClientConnectionError::NoAddressesProvided);
}
- let redis_connection_info = get_redis_connection_info(&connection_request);
+ let mut redis_connection_info = get_redis_connection_info(&connection_request);
+ let pubsub_connection_info = redis_connection_info.clone();
+ redis_connection_info.pubsub_subscriptions = None;
let retry_strategy = RetryStrategy::new(connection_request.connection_retry_strategy);
let tls_mode = connection_request.tls_mode;
let node_count = connection_request.addresses.len();
+ // randomize pubsub nodes, maybe a batter option is to always use the primary
+ let pubsub_node_index = rand::thread_rng().gen_range(0..node_count);
+ let pubsub_addr = &connection_request.addresses[pubsub_node_index];
let mut stream = stream::iter(connection_request.addresses.iter())
.map(|address| async {
get_connection_and_replication_info(
address,
&retry_strategy,
- &redis_connection_info,
+ if address.to_string() != pubsub_addr.to_string() {
+ &redis_connection_info
+ } else {
+ &pubsub_connection_info
+ },
tls_mode.unwrap_or(TlsMode::NoTls),
+ &push_sender,
)
.await
.map_err(|err| (format!("{}:{}", address.host, address.port), err))
@@ -392,12 +405,14 @@ async fn get_connection_and_replication_info(
retry_strategy: &RetryStrategy,
connection_info: &redis::RedisConnectionInfo,
tls_mode: TlsMode,
+ push_sender: &Option>,
) -> Result<(ReconnectingConnection, Value), (ReconnectingConnection, RedisError)> {
let result = ReconnectingConnection::new(
address,
retry_strategy.clone(),
connection_info.clone(),
tls_mode,
+ push_sender.clone(),
)
.await;
let reconnecting_connection = match result {
diff --git a/glide-core/src/client/types.rs b/glide-core/src/client/types.rs
index f942f64174..c26cdfb93f 100644
--- a/glide-core/src/client/types.rs
+++ b/glide-core/src/client/types.rs
@@ -1,7 +1,9 @@
/*
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
+use logger_core::log_warn;
+use std::collections::HashSet;
use std::time::Duration;
#[cfg(feature = "socket-layer")]
@@ -20,6 +22,7 @@ pub struct ConnectionRequest {
pub request_timeout: Option,
pub connection_retry_strategy: Option,
pub periodic_checks: Option,
+ pub pubsub_subscriptions: Option,
}
pub struct AuthenticationInfo {
@@ -150,6 +153,39 @@ impl From for ConnectionRequest {
PeriodicCheck::Disabled
}
});
+ let mut pubsub_subscriptions: Option = None;
+ if let Some(protobuf_pubsub) = value.pubsub_subscriptions.0 {
+ let mut redis_pubsub = redis::PubSubSubscriptionInfo::new();
+ for (pubsub_type, channels_patterns) in
+ protobuf_pubsub.channels_or_patterns_by_type.iter()
+ {
+ let kind = match *pubsub_type {
+ 0 => redis::PubSubSubscriptionKind::Exact,
+ 1 => redis::PubSubSubscriptionKind::Pattern,
+ 2 => redis::PubSubSubscriptionKind::Sharded,
+ 3_u32..=u32::MAX => {
+ log_warn(
+ "client creation",
+ format!(
+ "Omitting pubsub subscription on an unknown type: {:?}",
+ *pubsub_type
+ ),
+ );
+ continue;
+ }
+ };
+
+ for channel_pattern in channels_patterns.channels_or_patterns.iter() {
+ redis_pubsub
+ .entry(kind)
+ .and_modify(|channels_patterns| {
+ channels_patterns.insert(channel_pattern.to_vec());
+ })
+ .or_insert(HashSet::from([channel_pattern.to_vec()]));
+ }
+ }
+ pubsub_subscriptions = Some(redis_pubsub);
+ }
ConnectionRequest {
read_from,
@@ -163,6 +199,7 @@ impl From for ConnectionRequest {
request_timeout,
connection_retry_strategy,
periodic_checks,
+ pubsub_subscriptions,
}
}
}
diff --git a/glide-core/src/client/value_conversion.rs b/glide-core/src/client/value_conversion.rs
index f5b8fc04d2..dff852e839 100644
--- a/glide-core/src/client/value_conversion.rs
+++ b/glide-core/src/client/value_conversion.rs
@@ -1,5 +1,5 @@
/**
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
use redis::{
cluster_routing::Routable, from_owned_redis_value, Cmd, ErrorKind, RedisResult, Value,
@@ -33,6 +33,7 @@ pub(crate) enum ExpectedReturnType<'a> {
KeyWithMemberAndScore,
FunctionStatsReturnType,
GeoSearchReturnType,
+ SimpleString,
}
pub(crate) fn convert_to_expected_type(
@@ -141,6 +142,9 @@ pub(crate) fn convert_to_expected_type(
ExpectedReturnType::BulkString => Ok(Value::BulkString(
from_owned_redis_value::(value)?.into(),
)),
+ ExpectedReturnType::SimpleString => Ok(Value::SimpleString(
+ from_owned_redis_value::(value)?,
+ )),
ExpectedReturnType::JsonToggleReturnType => match value {
Value::Array(array) => {
let converted_array: RedisResult> = array
@@ -791,6 +795,7 @@ fn convert_to_array_of_pairs(
value_expected_return_type: Option,
) -> RedisResult {
match response {
+ Value::Nil => Ok(response),
Value::Array(ref array) if array.is_empty() || matches!(array[0], Value::Array(_)) => {
// The server response is an empty array or a RESP3 array of pairs. In RESP3, the values in the pairs are
// already of the correct type, so we do not need to convert them and `response` is in the correct format.
@@ -852,20 +857,35 @@ pub(crate) fn expected_type_for_cmd(cmd: &Cmd) -> Option {
key_type: &Some(ExpectedReturnType::BulkString),
value_type: &Some(ExpectedReturnType::ArrayOfPairs),
}),
- b"XREAD" => Some(ExpectedReturnType::Map {
+ b"XREAD" | b"XREADGROUP" => Some(ExpectedReturnType::Map {
key_type: &Some(ExpectedReturnType::BulkString),
value_type: &Some(ExpectedReturnType::Map {
key_type: &Some(ExpectedReturnType::BulkString),
value_type: &Some(ExpectedReturnType::ArrayOfPairs),
}),
}),
+ b"LCS" => cmd.position(b"IDX").map(|_| ExpectedReturnType::Map {
+ key_type: &Some(ExpectedReturnType::SimpleString),
+ value_type: &None,
+ }),
b"INCRBYFLOAT" | b"HINCRBYFLOAT" | b"ZINCRBY" => Some(ExpectedReturnType::Double),
- b"HEXISTS" | b"HSETNX" | b"EXPIRE" | b"EXPIREAT" | b"PEXPIRE" | b"PEXPIREAT"
- | b"SISMEMBER" | b"PERSIST" | b"SMOVE" | b"RENAMENX" | b"MOVE" | b"COPY" | b"MSETNX" => {
- Some(ExpectedReturnType::Boolean)
- }
+ b"HEXISTS"
+ | b"HSETNX"
+ | b"EXPIRE"
+ | b"EXPIREAT"
+ | b"PEXPIRE"
+ | b"PEXPIREAT"
+ | b"SISMEMBER"
+ | b"PERSIST"
+ | b"SMOVE"
+ | b"RENAMENX"
+ | b"MOVE"
+ | b"COPY"
+ | b"MSETNX"
+ | b"XGROUP DESTROY"
+ | b"XGROUP CREATECONSUMER" => Some(ExpectedReturnType::Boolean),
b"SMISMEMBER" => Some(ExpectedReturnType::ArrayOfBools),
- b"SMEMBERS" | b"SINTER" | b"SDIFF" => Some(ExpectedReturnType::Set),
+ b"SMEMBERS" | b"SINTER" | b"SDIFF" | b"SUNION" => Some(ExpectedReturnType::Set),
b"ZSCORE" | b"GEODIST" => Some(ExpectedReturnType::DoubleOrNull),
b"ZMSCORE" => Some(ExpectedReturnType::ArrayOfDoubleOrNull),
b"ZPOPMIN" | b"ZPOPMAX" => Some(ExpectedReturnType::MapOfStringToDouble),
@@ -1194,6 +1214,28 @@ mod tests {
));
}
+ #[test]
+ fn convert_xreadgroup() {
+ assert!(matches!(
+ expected_type_for_cmd(
+ redis::cmd("XREADGROUP")
+ .arg("GROUP")
+ .arg("group")
+ .arg("consumer")
+ .arg("streams")
+ .arg("key")
+ .arg("id")
+ ),
+ Some(ExpectedReturnType::Map {
+ key_type: &Some(ExpectedReturnType::BulkString),
+ value_type: &Some(ExpectedReturnType::Map {
+ key_type: &Some(ExpectedReturnType::BulkString),
+ value_type: &Some(ExpectedReturnType::ArrayOfPairs),
+ }),
+ })
+ ));
+ }
+
#[test]
fn test_convert_empty_array_to_map_is_nil() {
let mut cmd = redis::cmd("XREAD");
@@ -2341,4 +2383,14 @@ mod tests {
assert!(expected_type_for_cmd(redis::cmd("GEOSEARCH").arg("key")).is_none());
}
+ #[test]
+ fn convert_lcs_idx() {
+ assert!(matches!(
+ expected_type_for_cmd(redis::cmd("LCS").arg("key1").arg("key2").arg("IDX")),
+ Some(ExpectedReturnType::Map {
+ key_type: &Some(ExpectedReturnType::SimpleString),
+ value_type: &None,
+ })
+ ));
+ }
}
diff --git a/glide-core/src/errors.rs b/glide-core/src/errors.rs
index 1c05aad84b..b5f9b1af9e 100644
--- a/glide-core/src/errors.rs
+++ b/glide-core/src/errors.rs
@@ -1,5 +1,5 @@
/*
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
use redis::RedisError;
diff --git a/glide-core/src/lib.rs b/glide-core/src/lib.rs
index f904928be1..5bbc431e82 100644
--- a/glide-core/src/lib.rs
+++ b/glide-core/src/lib.rs
@@ -1,5 +1,5 @@
/*
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
#[cfg(feature = "socket-layer")]
diff --git a/glide-core/src/protobuf/connection_request.proto b/glide-core/src/protobuf/connection_request.proto
index ecdeeae1b2..a186a1f41f 100644
--- a/glide-core/src/protobuf/connection_request.proto
+++ b/glide-core/src/protobuf/connection_request.proto
@@ -36,6 +36,22 @@ message PeriodicChecksManualInterval {
message PeriodicChecksDisabled {
}
+enum PubSubChannelType {
+ Exact = 0;
+ Pattern = 1;
+ Sharded = 2;
+}
+
+message PubSubChannelsOrPatterns
+{
+ repeated bytes channels_or_patterns = 1;
+}
+
+message PubSubSubscriptions
+{
+ map channels_or_patterns_by_type = 1;
+}
+
// IMPORTANT - if you add fields here, you probably need to add them also in client/mod.rs:`sanitized_request_string`.
message ConnectionRequest {
repeated NodeAddress addresses = 1;
@@ -52,6 +68,7 @@ message ConnectionRequest {
PeriodicChecksManualInterval periodic_checks_manual_interval = 11;
PeriodicChecksDisabled periodic_checks_disabled = 12;
}
+ PubSubSubscriptions pubsub_subscriptions = 13;
}
message ConnectionRetryStrategy {
diff --git a/glide-core/src/protobuf/redis_request.proto b/glide-core/src/protobuf/redis_request.proto
index 8056bf308e..e3d2b01b2c 100644
--- a/glide-core/src/protobuf/redis_request.proto
+++ b/glide-core/src/protobuf/redis_request.proto
@@ -202,6 +202,8 @@ enum RequestType {
Sort = 160;
FunctionKill = 161;
FunctionStats = 162;
+ FCallReadOnly = 163;
+ FlushDB = 164;
LSet = 165;
XDel = 166;
XRange = 167;
@@ -219,6 +221,22 @@ enum RequestType {
LPos = 180;
LCS = 181;
GeoSearch = 182;
+ Watch = 183;
+ UnWatch = 184;
+ GeoSearchStore = 185;
+ SUnion = 186;
+ Publish = 187;
+ SPublish = 188;
+ XGroupCreateConsumer = 189;
+ XGroupDelConsumer = 190;
+ RandomKey = 191;
+ GetEx = 192;
+ Dump = 193;
+ Restore = 194;
+ SortReadOnly = 195;
+ FunctionDump = 196;
+ FunctionRestore = 197;
+ XPending = 198;
}
message Command {
diff --git a/glide-core/src/protobuf/response.proto b/glide-core/src/protobuf/response.proto
index 33591112ba..871d38e476 100644
--- a/glide-core/src/protobuf/response.proto
+++ b/glide-core/src/protobuf/response.proto
@@ -21,6 +21,7 @@ message Response {
RequestError request_error = 4;
string closing_error = 5;
}
+ bool is_push = 6;
}
enum ConstantResponse {
diff --git a/glide-core/src/request_type.rs b/glide-core/src/request_type.rs
index 8e417b91f4..805db2dc91 100644
--- a/glide-core/src/request_type.rs
+++ b/glide-core/src/request_type.rs
@@ -1,5 +1,5 @@
/**
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
use redis::{cmd, Cmd};
@@ -172,6 +172,8 @@ pub enum RequestType {
Sort = 160,
FunctionKill = 161,
FunctionStats = 162,
+ FCallReadOnly = 163,
+ FlushDB = 164,
LSet = 165,
XDel = 166,
XRange = 167,
@@ -189,6 +191,22 @@ pub enum RequestType {
LPos = 180,
LCS = 181,
GeoSearch = 182,
+ Watch = 183,
+ UnWatch = 184,
+ GeoSearchStore = 185,
+ SUnion = 186,
+ Publish = 187,
+ SPublish = 188,
+ XGroupCreateConsumer = 189,
+ XGroupDelConsumer = 190,
+ RandomKey = 191,
+ GetEx = 192,
+ Dump = 193,
+ Restore = 194,
+ SortReadOnly = 195,
+ FunctionDump = 196,
+ FunctionRestore = 197,
+ XPending = 198,
}
fn get_two_word_command(first: &str, second: &str) -> Cmd {
@@ -363,6 +381,8 @@ impl From<::protobuf::EnumOrUnknown> for RequestType {
ProtobufRequestType::XLen => RequestType::XLen,
ProtobufRequestType::FunctionKill => RequestType::FunctionKill,
ProtobufRequestType::FunctionStats => RequestType::FunctionStats,
+ ProtobufRequestType::FCallReadOnly => RequestType::FCallReadOnly,
+ ProtobufRequestType::FlushDB => RequestType::FlushDB,
ProtobufRequestType::LSet => RequestType::LSet,
ProtobufRequestType::XDel => RequestType::XDel,
ProtobufRequestType::XRange => RequestType::XRange,
@@ -381,6 +401,22 @@ impl From<::protobuf::EnumOrUnknown> for RequestType {
ProtobufRequestType::LPos => RequestType::LPos,
ProtobufRequestType::LCS => RequestType::LCS,
ProtobufRequestType::GeoSearch => RequestType::GeoSearch,
+ ProtobufRequestType::SUnion => RequestType::SUnion,
+ ProtobufRequestType::Watch => RequestType::Watch,
+ ProtobufRequestType::UnWatch => RequestType::UnWatch,
+ ProtobufRequestType::GeoSearchStore => RequestType::GeoSearchStore,
+ ProtobufRequestType::Publish => RequestType::Publish,
+ ProtobufRequestType::SPublish => RequestType::SPublish,
+ ProtobufRequestType::XGroupCreateConsumer => RequestType::XGroupCreateConsumer,
+ ProtobufRequestType::XGroupDelConsumer => RequestType::XGroupDelConsumer,
+ ProtobufRequestType::RandomKey => RequestType::RandomKey,
+ ProtobufRequestType::GetEx => RequestType::GetEx,
+ ProtobufRequestType::Dump => RequestType::Dump,
+ ProtobufRequestType::Restore => RequestType::Restore,
+ ProtobufRequestType::SortReadOnly => RequestType::SortReadOnly,
+ ProtobufRequestType::FunctionDump => RequestType::FunctionDump,
+ ProtobufRequestType::FunctionRestore => RequestType::FunctionRestore,
+ ProtobufRequestType::XPending => RequestType::XPending,
}
}
}
@@ -551,6 +587,8 @@ impl RequestType {
RequestType::XLen => Some(cmd("XLEN")),
RequestType::FunctionKill => Some(get_two_word_command("FUNCTION", "KILL")),
RequestType::FunctionStats => Some(get_two_word_command("FUNCTION", "STATS")),
+ RequestType::FCallReadOnly => Some(cmd("FCALL_RO")),
+ RequestType::FlushDB => Some(cmd("FLUSHDB")),
RequestType::LSet => Some(cmd("LSET")),
RequestType::XDel => Some(cmd("XDEL")),
RequestType::XRange => Some(cmd("XRANGE")),
@@ -569,6 +607,24 @@ impl RequestType {
RequestType::LPos => Some(cmd("LPOS")),
RequestType::LCS => Some(cmd("LCS")),
RequestType::GeoSearch => Some(cmd("GEOSEARCH")),
+ RequestType::SUnion => Some(cmd("SUNION")),
+ RequestType::Watch => Some(cmd("WATCH")),
+ RequestType::UnWatch => Some(cmd("UNWATCH")),
+ RequestType::GeoSearchStore => Some(cmd("GEOSEARCHSTORE")),
+ RequestType::Publish => Some(cmd("PUBLISH")),
+ RequestType::SPublish => Some(cmd("SPUBLISH")),
+ RequestType::XGroupCreateConsumer => {
+ Some(get_two_word_command("XGROUP", "CREATECONSUMER"))
+ }
+ RequestType::XGroupDelConsumer => Some(get_two_word_command("XGROUP", "DELCONSUMER")),
+ RequestType::RandomKey => Some(cmd("RANDOMKEY")),
+ RequestType::GetEx => Some(cmd("GETEX")),
+ RequestType::Dump => Some(cmd("DUMP")),
+ RequestType::Restore => Some(cmd("RESTORE")),
+ RequestType::SortReadOnly => Some(cmd("SORT_RO")),
+ RequestType::FunctionDump => Some(get_two_word_command("FUNCTION", "DUMP")),
+ RequestType::FunctionRestore => Some(get_two_word_command("FUNCTION", "RESTORE")),
+ RequestType::XPending => Some(cmd("XPENDING")),
}
}
}
diff --git a/glide-core/src/retry_strategies.rs b/glide-core/src/retry_strategies.rs
index 4dd5d7edb7..dbe5683347 100644
--- a/glide-core/src/retry_strategies.rs
+++ b/glide-core/src/retry_strategies.rs
@@ -1,5 +1,5 @@
/**
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
use crate::client::ConnectionRetryStrategy;
use std::time::Duration;
diff --git a/glide-core/src/rotating_buffer.rs b/glide-core/src/rotating_buffer.rs
index 5178b587e7..cbd32313ed 100644
--- a/glide-core/src/rotating_buffer.rs
+++ b/glide-core/src/rotating_buffer.rs
@@ -1,5 +1,5 @@
/**
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
#[allow(unused_imports)]
use bytes::{Bytes, BytesMut};
diff --git a/glide-core/src/scripts_container.rs b/glide-core/src/scripts_container.rs
index 251a69e5c3..129e6592c4 100644
--- a/glide-core/src/scripts_container.rs
+++ b/glide-core/src/scripts_container.rs
@@ -1,5 +1,5 @@
/**
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
use arcstr::ArcStr;
use logger_core::log_info;
diff --git a/glide-core/src/socket_listener.rs b/glide-core/src/socket_listener.rs
index 82b8df6a69..a2a333f103 100644
--- a/glide-core/src/socket_listener.rs
+++ b/glide-core/src/socket_listener.rs
@@ -1,5 +1,5 @@
/**
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
use super::rotating_buffer::RotatingBuffer;
use crate::client::Client;
@@ -21,7 +21,7 @@ use redis::cluster_routing::{
};
use redis::cluster_routing::{ResponsePolicy, Routable};
use redis::RedisError;
-use redis::{Cmd, Value};
+use redis::{Cmd, PushInfo, Value};
use std::cell::Cell;
use std::rc::Rc;
use std::{env, str};
@@ -30,6 +30,7 @@ use thiserror::Error;
use tokio::io::ErrorKind::AddrInUse;
use tokio::net::{UnixListener, UnixStream};
use tokio::runtime::Builder;
+use tokio::sync::mpsc;
use tokio::sync::mpsc::{channel, Sender};
use tokio::sync::Mutex;
use tokio::task;
@@ -184,6 +185,7 @@ async fn write_result(
) -> Result<(), io::Error> {
let mut response = Response::new();
response.callback_idx = callback_index;
+ response.is_push = false;
response.value = match resp_result {
Ok(Value::Okay) => Some(response::response::Value::ConstantResponse(
response::ConstantResponse::OK.into(),
@@ -473,8 +475,9 @@ pub fn close_socket(socket_path: &String) {
async fn create_client(
writer: &Rc,
request: ConnectionRequest,
+ push_tx: Option>,
) -> Result {
- let client = match Client::new(request.into()).await {
+ let client = match Client::new(request.into(), push_tx).await {
Ok(client) => client,
Err(err) => return Err(ClientCreationError::ConnectionError(err)),
};
@@ -485,13 +488,14 @@ async fn create_client(
async fn wait_for_connection_configuration_and_create_client(
client_listener: &mut UnixStreamListener,
writer: &Rc,
+ push_tx: Option>,
) -> Result {
// Wait for the server's address
match client_listener.next_values::().await {
Closed(reason) => Err(ClientCreationError::SocketListenerClosed(reason)),
ReceivedValues(mut received_requests) => {
if let Some(request) = received_requests.pop() {
- create_client(writer, request).await
+ create_client(writer, request, push_tx).await
} else {
Err(ClientCreationError::UnhandledError(
"No received requests".to_string(),
@@ -518,6 +522,35 @@ async fn read_values_loop(
}
}
+async fn push_manager_loop(mut push_rx: mpsc::UnboundedReceiver, writer: Rc) {
+ loop {
+ let result = push_rx.recv().await;
+ match result {
+ None => {
+ log_error("push manager loop", "got None from push manager");
+ return;
+ }
+ Some(push_msg) => {
+ log_debug("push manager loop", format!("got PushInfo: {:?}", push_msg));
+ let mut response = Response::new();
+ response.callback_idx = 0; // callback_idx is not used with push notifications
+ response.is_push = true;
+ response.value = {
+ let push_val = Value::Push {
+ kind: (push_msg.kind),
+ data: (push_msg.data),
+ };
+ let pointer = Box::leak(Box::new(push_val));
+ let raw_pointer = pointer as *mut redis::Value;
+ Some(response::response::Value::RespPointer(raw_pointer as u64))
+ };
+
+ _ = write_to_writer(response, &writer).await;
+ }
+ }
+ }
+}
+
async fn listen_on_client_stream(socket: UnixStream) {
let socket = Rc::new(socket);
// Spawn a new task to listen on this client's stream
@@ -525,14 +558,18 @@ async fn listen_on_client_stream(socket: UnixStream) {
let mut client_listener = UnixStreamListener::new(socket.clone());
let accumulated_outputs = Cell::new(Vec::new());
let (sender, mut receiver) = channel(1);
+ let (push_tx, push_rx) = tokio::sync::mpsc::unbounded_channel();
let writer = Rc::new(Writer {
socket,
lock: write_lock,
accumulated_outputs,
closing_sender: sender,
});
- let client_creation =
- wait_for_connection_configuration_and_create_client(&mut client_listener, &writer);
+ let client_creation = wait_for_connection_configuration_and_create_client(
+ &mut client_listener,
+ &writer,
+ Some(push_tx),
+ );
let client = match client_creation.await {
Ok(conn) => conn,
Err(ClientCreationError::SocketListenerClosed(ClosingReason::ReadSocketClosed)) => {
@@ -583,6 +620,9 @@ async fn listen_on_client_stream(socket: UnixStream) {
} else {
log_trace("client closing", "writer closed");
}
+ },
+ _ = push_manager_loop(push_rx, writer.clone()) => {
+ log_trace("client closing", "push manager closed");
}
}
log_trace("client closing", "closing connection");
diff --git a/glide-core/tests/test_client.rs b/glide-core/tests/test_client.rs
index 682b5de9b9..2dfe9fc248 100644
--- a/glide-core/tests/test_client.rs
+++ b/glide-core/tests/test_client.rs
@@ -1,5 +1,5 @@
/**
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
mod utilities;
@@ -35,6 +35,7 @@ pub(crate) mod shared_client_tests {
Client::new(
create_connection_request(&[connection_addr.clone()], &configuration)
.into(),
+ None,
)
.await
.ok()
diff --git a/glide-core/tests/test_cluster_client.rs b/glide-core/tests/test_cluster_client.rs
index de3e22e15a..1c60dc8c79 100644
--- a/glide-core/tests/test_cluster_client.rs
+++ b/glide-core/tests/test_cluster_client.rs
@@ -1,5 +1,5 @@
/**
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
mod utilities;
diff --git a/glide-core/tests/test_socket_listener.rs b/glide-core/tests/test_socket_listener.rs
index d2735aaab0..bfa27ebc9c 100644
--- a/glide-core/tests/test_socket_listener.rs
+++ b/glide-core/tests/test_socket_listener.rs
@@ -1,5 +1,5 @@
/*
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
#![cfg(feature = "socket-layer")]
diff --git a/glide-core/tests/test_standalone_client.rs b/glide-core/tests/test_standalone_client.rs
index aa7f3b6609..75e3262f80 100644
--- a/glide-core/tests/test_standalone_client.rs
+++ b/glide-core/tests/test_standalone_client.rs
@@ -1,5 +1,5 @@
/**
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
mod utilities;
@@ -199,7 +199,7 @@ mod standalone_client_tests {
connection_request.read_from = config.read_from.into();
block_on_all(async {
- let mut client = StandaloneClient::create_client(connection_request.into())
+ let mut client = StandaloneClient::create_client(connection_request.into(), None)
.await
.unwrap();
for mock in mocks.drain(1..config.number_of_replicas_dropped_after_connection + 1) {
@@ -305,7 +305,7 @@ mod standalone_client_tests {
let connection_request =
create_connection_request(addresses.as_slice(), &Default::default());
block_on_all(async {
- let client_res = StandaloneClient::create_client(connection_request.into())
+ let client_res = StandaloneClient::create_client(connection_request.into(), None)
.await
.map_err(ConnectionError::Standalone);
assert!(client_res.is_err());
@@ -344,7 +344,7 @@ mod standalone_client_tests {
create_connection_request(addresses.as_slice(), &Default::default());
block_on_all(async {
- let mut client = StandaloneClient::create_client(connection_request.into())
+ let mut client = StandaloneClient::create_client(connection_request.into(), None)
.await
.unwrap();
diff --git a/glide-core/tests/utilities/cluster.rs b/glide-core/tests/utilities/cluster.rs
index 6ff69a932e..9e7c356f4e 100644
--- a/glide-core/tests/utilities/cluster.rs
+++ b/glide-core/tests/utilities/cluster.rs
@@ -1,5 +1,5 @@
/**
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
use super::{create_connection_request, ClusterMode, TestConfiguration};
use futures::future::{join_all, BoxFuture};
@@ -249,7 +249,7 @@ pub async fn create_cluster_client(
configuration.request_timeout = configuration.request_timeout.or(Some(10000));
let connection_request = create_connection_request(&addresses, &configuration);
- Client::new(connection_request.into()).await.unwrap()
+ Client::new(connection_request.into(), None).await.unwrap()
}
pub async fn setup_test_basics_internal(configuration: TestConfiguration) -> ClusterTestBasics {
diff --git a/glide-core/tests/utilities/mocks.rs b/glide-core/tests/utilities/mocks.rs
index f465000988..160e8a3189 100644
--- a/glide-core/tests/utilities/mocks.rs
+++ b/glide-core/tests/utilities/mocks.rs
@@ -1,5 +1,5 @@
/**
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
use futures_intrusive::sync::ManualResetEvent;
use redis::{Cmd, ConnectionAddr, Value};
diff --git a/glide-core/tests/utilities/mod.rs b/glide-core/tests/utilities/mod.rs
index 04bd727a1d..05c6f1f05a 100644
--- a/glide-core/tests/utilities/mod.rs
+++ b/glide-core/tests/utilities/mod.rs
@@ -1,5 +1,5 @@
/*
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
#![allow(dead_code)]
@@ -12,7 +12,7 @@ use once_cell::sync::Lazy;
use rand::{distributions::Alphanumeric, Rng};
use redis::{
cluster_routing::{MultipleNodeRoutingInfo, RoutingInfo},
- ConnectionAddr, RedisConnectionInfo, RedisResult, Value,
+ ConnectionAddr, PushInfo, RedisConnectionInfo, RedisResult, Value,
};
use socket2::{Domain, Socket, Type};
use std::{
@@ -20,6 +20,7 @@ use std::{
sync::Mutex, time::Duration,
};
use tempfile::TempDir;
+use tokio::sync::mpsc;
pub mod cluster;
pub mod mocks;
@@ -456,7 +457,7 @@ pub async fn wait_for_server_to_become_ready(server_address: &ConnectionAddr) {
})
.unwrap();
loop {
- match client.get_multiplexed_async_connection().await {
+ match client.get_multiplexed_async_connection(None).await {
Err(err) => {
if err.is_connection_refusal() {
tokio::time::sleep(millisecond).await;
@@ -546,6 +547,7 @@ pub async fn send_set_and_get(mut client: Client, key: String) {
pub struct TestBasics {
pub server: Option,
pub client: StandaloneClient,
+ pub push_receiver: mpsc::UnboundedReceiver,
}
fn convert_to_protobuf_protocol(
@@ -592,7 +594,8 @@ pub async fn setup_acl(addr: &ConnectionAddr, connection_info: &RedisConnectionI
})
.unwrap();
let mut connection =
- repeat_try_create(|| async { client.get_multiplexed_async_connection().await.ok() }).await;
+ repeat_try_create(|| async { client.get_multiplexed_async_connection(None).await.ok() })
+ .await;
let password = connection_info.password.clone().unwrap();
let username = connection_info
@@ -689,11 +692,16 @@ pub(crate) async fn setup_test_basics_internal(configuration: &TestConfiguration
let mut connection_request = create_connection_request(&[connection_addr], configuration);
connection_request.cluster_mode_enabled = false;
connection_request.protocol = configuration.protocol.into();
- let client = StandaloneClient::create_client(connection_request.into())
+ let (push_sender, push_receiver) = tokio::sync::mpsc::unbounded_channel();
+ let client = StandaloneClient::create_client(connection_request.into(), Some(push_sender))
.await
.unwrap();
- TestBasics { server, client }
+ TestBasics {
+ server,
+ client,
+ push_receiver,
+ }
}
pub async fn setup_test_basics(use_tls: bool) -> TestBasics {
diff --git a/go/api/config.go b/go/api/config.go
index 9d2417b429..7b2955d828 100644
--- a/go/api/config.go
+++ b/go/api/config.go
@@ -1,4 +1,4 @@
-// Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+// Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
package api
diff --git a/go/api/config_test.go b/go/api/config_test.go
index 53a18e5308..e30a1b096b 100644
--- a/go/api/config_test.go
+++ b/go/api/config_test.go
@@ -1,4 +1,4 @@
-// Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+// Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
package api
diff --git a/go/cbindgen.toml b/go/cbindgen.toml
index 8bd3eb749f..9378736cd1 100644
--- a/go/cbindgen.toml
+++ b/go/cbindgen.toml
@@ -1,7 +1,7 @@
-# Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+# Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
language = "C"
-header = "/* Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */"
+header = "/* Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 */"
[parse]
parse_deps = true
diff --git a/go/src/lib.rs b/go/src/lib.rs
index 72ffeca427..bd76ebe347 100644
--- a/go/src/lib.rs
+++ b/go/src/lib.rs
@@ -1,5 +1,5 @@
/*
- * Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0
+ * Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0
*/
// TODO: Investigate using uniffi bindings for Go instead of cbindgen
@@ -81,7 +81,7 @@ fn create_client_internal(
errors::error_message(&redis_error)
})?;
let client = runtime
- .block_on(GlideClient::new(ConnectionRequest::from(request)))
+ .block_on(GlideClient::new(ConnectionRequest::from(request), None))
.map_err(|err| err.to_string())?;
Ok(ClientAdapter {
client,
diff --git a/java/THIRD_PARTY_LICENSES_JAVA b/java/THIRD_PARTY_LICENSES_JAVA
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/java/benchmarks/src/main/java/glide/benchmarks/BenchmarkingApp.java b/java/benchmarks/src/main/java/glide/benchmarks/BenchmarkingApp.java
index 594c82c030..31ab7bbd13 100644
--- a/java/benchmarks/src/main/java/glide/benchmarks/BenchmarkingApp.java
+++ b/java/benchmarks/src/main/java/glide/benchmarks/BenchmarkingApp.java
@@ -1,4 +1,4 @@
-/** Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */
+/** Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 */
package glide.benchmarks;
import static glide.benchmarks.utils.Benchmarking.testClientSetGet;
diff --git a/java/benchmarks/src/main/java/glide/benchmarks/clients/AsyncClient.java b/java/benchmarks/src/main/java/glide/benchmarks/clients/AsyncClient.java
index ce450bd118..8a6c8a9025 100644
--- a/java/benchmarks/src/main/java/glide/benchmarks/clients/AsyncClient.java
+++ b/java/benchmarks/src/main/java/glide/benchmarks/clients/AsyncClient.java
@@ -1,4 +1,4 @@
-/** Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */
+/** Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 */
package glide.benchmarks.clients;
import java.util.concurrent.ExecutionException;
diff --git a/java/benchmarks/src/main/java/glide/benchmarks/clients/Client.java b/java/benchmarks/src/main/java/glide/benchmarks/clients/Client.java
index 790229d9ec..d61f239642 100644
--- a/java/benchmarks/src/main/java/glide/benchmarks/clients/Client.java
+++ b/java/benchmarks/src/main/java/glide/benchmarks/clients/Client.java
@@ -1,4 +1,4 @@
-/** Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */
+/** Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 */
package glide.benchmarks.clients;
import glide.benchmarks.utils.ConnectionSettings;
diff --git a/java/benchmarks/src/main/java/glide/benchmarks/clients/SyncClient.java b/java/benchmarks/src/main/java/glide/benchmarks/clients/SyncClient.java
index 4a47e6ed3d..f8034435ae 100644
--- a/java/benchmarks/src/main/java/glide/benchmarks/clients/SyncClient.java
+++ b/java/benchmarks/src/main/java/glide/benchmarks/clients/SyncClient.java
@@ -1,4 +1,4 @@
-/** Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */
+/** Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 */
package glide.benchmarks.clients;
/** A Redis client with sync capabilities */
diff --git a/java/benchmarks/src/main/java/glide/benchmarks/clients/glide/GlideAsyncClient.java b/java/benchmarks/src/main/java/glide/benchmarks/clients/glide/GlideAsyncClient.java
index ee2bdeb83a..3cb1361ee1 100644
--- a/java/benchmarks/src/main/java/glide/benchmarks/clients/glide/GlideAsyncClient.java
+++ b/java/benchmarks/src/main/java/glide/benchmarks/clients/glide/GlideAsyncClient.java
@@ -1,4 +1,4 @@
-/** Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */
+/** Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 */
package glide.benchmarks.clients.glide;
import static java.util.concurrent.TimeUnit.SECONDS;
diff --git a/java/benchmarks/src/main/java/glide/benchmarks/clients/jedis/JedisClient.java b/java/benchmarks/src/main/java/glide/benchmarks/clients/jedis/JedisClient.java
index 0553cbba37..9745bdec38 100644
--- a/java/benchmarks/src/main/java/glide/benchmarks/clients/jedis/JedisClient.java
+++ b/java/benchmarks/src/main/java/glide/benchmarks/clients/jedis/JedisClient.java
@@ -1,4 +1,4 @@
-/** Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */
+/** Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 */
package glide.benchmarks.clients.jedis;
import glide.benchmarks.clients.SyncClient;
diff --git a/java/benchmarks/src/main/java/glide/benchmarks/clients/lettuce/LettuceAsyncClient.java b/java/benchmarks/src/main/java/glide/benchmarks/clients/lettuce/LettuceAsyncClient.java
index e628ed8f8c..d141582939 100644
--- a/java/benchmarks/src/main/java/glide/benchmarks/clients/lettuce/LettuceAsyncClient.java
+++ b/java/benchmarks/src/main/java/glide/benchmarks/clients/lettuce/LettuceAsyncClient.java
@@ -1,4 +1,4 @@
-/** Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */
+/** Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 */
package glide.benchmarks.clients.lettuce;
import glide.benchmarks.clients.AsyncClient;
diff --git a/java/benchmarks/src/main/java/glide/benchmarks/utils/Benchmarking.java b/java/benchmarks/src/main/java/glide/benchmarks/utils/Benchmarking.java
index 82bd607a70..0d38204be1 100644
--- a/java/benchmarks/src/main/java/glide/benchmarks/utils/Benchmarking.java
+++ b/java/benchmarks/src/main/java/glide/benchmarks/utils/Benchmarking.java
@@ -1,4 +1,4 @@
-/** Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */
+/** Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 */
package glide.benchmarks.utils;
import glide.benchmarks.BenchmarkingApp;
diff --git a/java/benchmarks/src/main/java/glide/benchmarks/utils/ChosenAction.java b/java/benchmarks/src/main/java/glide/benchmarks/utils/ChosenAction.java
index 90d62ba392..58c88ca08d 100644
--- a/java/benchmarks/src/main/java/glide/benchmarks/utils/ChosenAction.java
+++ b/java/benchmarks/src/main/java/glide/benchmarks/utils/ChosenAction.java
@@ -1,4 +1,4 @@
-/** Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */
+/** Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 */
package glide.benchmarks.utils;
public enum ChosenAction {
diff --git a/java/benchmarks/src/main/java/glide/benchmarks/utils/ConnectionSettings.java b/java/benchmarks/src/main/java/glide/benchmarks/utils/ConnectionSettings.java
index f15338bd01..e8eae01a1b 100644
--- a/java/benchmarks/src/main/java/glide/benchmarks/utils/ConnectionSettings.java
+++ b/java/benchmarks/src/main/java/glide/benchmarks/utils/ConnectionSettings.java
@@ -1,4 +1,4 @@
-/** Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */
+/** Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 */
package glide.benchmarks.utils;
/** Redis-client settings */
diff --git a/java/benchmarks/src/main/java/glide/benchmarks/utils/JsonWriter.java b/java/benchmarks/src/main/java/glide/benchmarks/utils/JsonWriter.java
index c41ca18906..fb8004d69c 100644
--- a/java/benchmarks/src/main/java/glide/benchmarks/utils/JsonWriter.java
+++ b/java/benchmarks/src/main/java/glide/benchmarks/utils/JsonWriter.java
@@ -1,4 +1,4 @@
-/** Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */
+/** Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 */
package glide.benchmarks.utils;
import com.google.gson.Gson;
diff --git a/java/benchmarks/src/main/java/glide/benchmarks/utils/LatencyResults.java b/java/benchmarks/src/main/java/glide/benchmarks/utils/LatencyResults.java
index f7214f9865..297a1e42d0 100644
--- a/java/benchmarks/src/main/java/glide/benchmarks/utils/LatencyResults.java
+++ b/java/benchmarks/src/main/java/glide/benchmarks/utils/LatencyResults.java
@@ -1,4 +1,4 @@
-/** Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */
+/** Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 */
package glide.benchmarks.utils;
import java.util.Arrays;
diff --git a/java/build.gradle b/java/build.gradle
index 1e8824a15f..d36a4bf750 100644
--- a/java/build.gradle
+++ b/java/build.gradle
@@ -79,7 +79,7 @@ spotless {
include '**/*.java'
exclude '**/build/**', '**/build-*/**', '**/protobuf/**'
}
- licenseHeader('/** Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */')
+ licenseHeader('/** Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 */')
importOrder()
removeUnusedImports()
trimTrailingWhitespace()
diff --git a/java/client/src/main/java/glide/api/BaseClient.java b/java/client/src/main/java/glide/api/BaseClient.java
index f7c47e4827..c777e40c30 100644
--- a/java/client/src/main/java/glide/api/BaseClient.java
+++ b/java/client/src/main/java/glide/api/BaseClient.java
@@ -1,10 +1,14 @@
-/** Copyright GLIDE-for-Redis Project Contributors - SPDX Identifier: Apache-2.0 */
+/** Copyright Valkey GLIDE Project Contributors - SPDX Identifier: Apache-2.0 */
package glide.api;
+import static glide.api.models.GlideString.gs;
+import static glide.api.models.commands.SortBaseOptions.STORE_COMMAND_STRING;
+import static glide.api.models.commands.SortOptions.STORE_COMMAND_STRING;
import static glide.api.models.commands.bitmap.BitFieldOptions.BitFieldReadOnlySubCommands;
import static glide.api.models.commands.bitmap.BitFieldOptions.BitFieldSubCommands;
import static glide.api.models.commands.bitmap.BitFieldOptions.createBitFieldArgs;
import static glide.ffi.resolvers.SocketListenerResolver.getSocket;
+import static glide.utils.ArrayTransformUtils.cast3DArray;
import static glide.utils.ArrayTransformUtils.castArray;
import static glide.utils.ArrayTransformUtils.castArrayofArrays;
import static glide.utils.ArrayTransformUtils.castMapOf2DArray;
@@ -30,11 +34,13 @@
import static redis_request.RedisRequestOuterClass.RequestType.Decr;
import static redis_request.RedisRequestOuterClass.RequestType.DecrBy;
import static redis_request.RedisRequestOuterClass.RequestType.Del;
+import static redis_request.RedisRequestOuterClass.RequestType.Dump;
import static redis_request.RedisRequestOuterClass.RequestType.Exists;
import static redis_request.RedisRequestOuterClass.RequestType.Expire;
import static redis_request.RedisRequestOuterClass.RequestType.ExpireAt;
import static redis_request.RedisRequestOuterClass.RequestType.ExpireTime;
import static redis_request.RedisRequestOuterClass.RequestType.FCall;
+import static redis_request.RedisRequestOuterClass.RequestType.FCallReadOnly;
import static redis_request.RedisRequestOuterClass.RequestType.GeoAdd;
import static redis_request.RedisRequestOuterClass.RequestType.GeoDist;
import static redis_request.RedisRequestOuterClass.RequestType.GeoHash;
@@ -42,6 +48,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.Get;
import static redis_request.RedisRequestOuterClass.RequestType.GetBit;
import static redis_request.RedisRequestOuterClass.RequestType.GetDel;
+import static redis_request.RedisRequestOuterClass.RequestType.GetEx;
import static redis_request.RedisRequestOuterClass.RequestType.GetRange;
import static redis_request.RedisRequestOuterClass.RequestType.HDel;
import static redis_request.RedisRequestOuterClass.RequestType.HExists;
@@ -94,6 +101,7 @@
import static redis_request.RedisRequestOuterClass.RequestType.RPushX;
import static redis_request.RedisRequestOuterClass.RequestType.Rename;
import static redis_request.RedisRequestOuterClass.RequestType.RenameNX;
+import static redis_request.RedisRequestOuterClass.RequestType.Restore;
import static redis_request.RedisRequestOuterClass.RequestType.SAdd;
import static redis_request.RedisRequestOuterClass.RequestType.SCard;
import static redis_request.RedisRequestOuterClass.RequestType.SDiff;
@@ -108,20 +116,31 @@
import static redis_request.RedisRequestOuterClass.RequestType.SPop;
import static redis_request.RedisRequestOuterClass.RequestType.SRandMember;
import static redis_request.RedisRequestOuterClass.RequestType.SRem;
+import static redis_request.RedisRequestOuterClass.RequestType.SUnion;
import static redis_request.RedisRequestOuterClass.RequestType.SUnionStore;
import static redis_request.RedisRequestOuterClass.RequestType.Set;
import static redis_request.RedisRequestOuterClass.RequestType.SetBit;
import static redis_request.RedisRequestOuterClass.RequestType.SetRange;
+import static redis_request.RedisRequestOuterClass.RequestType.Sort;
+import static redis_request.RedisRequestOuterClass.RequestType.SortReadOnly;
import static redis_request.RedisRequestOuterClass.RequestType.Strlen;
import static redis_request.RedisRequestOuterClass.RequestType.TTL;
import static redis_request.RedisRequestOuterClass.RequestType.Touch;
import static redis_request.RedisRequestOuterClass.RequestType.Type;
import static redis_request.RedisRequestOuterClass.RequestType.Unlink;
+import static redis_request.RedisRequestOuterClass.RequestType.Watch;
+import static redis_request.RedisRequestOuterClass.RequestType.XAck;
import static redis_request.RedisRequestOuterClass.RequestType.XAdd;
import static redis_request.RedisRequestOuterClass.RequestType.XDel;
+import static redis_request.RedisRequestOuterClass.RequestType.XGroupCreate;
+import static redis_request.RedisRequestOuterClass.RequestType.XGroupCreateConsumer;
+import static redis_request.RedisRequestOuterClass.RequestType.XGroupDelConsumer;
+import static redis_request.RedisRequestOuterClass.RequestType.XGroupDestroy;
import static redis_request.RedisRequestOuterClass.RequestType.XLen;
+import static redis_request.RedisRequestOuterClass.RequestType.XPending;
import static redis_request.RedisRequestOuterClass.RequestType.XRange;
import static redis_request.RedisRequestOuterClass.RequestType.XRead;
+import static redis_request.RedisRequestOuterClass.RequestType.XReadGroup;
import static redis_request.RedisRequestOuterClass.RequestType.XRevRange;
import static redis_request.RedisRequestOuterClass.RequestType.XTrim;
import static redis_request.RedisRequestOuterClass.RequestType.ZAdd;
@@ -162,8 +181,11 @@
import glide.api.commands.SortedSetBaseCommands;
import glide.api.commands.StreamBaseCommands;
import glide.api.commands.StringBaseCommands;
+import glide.api.commands.TransactionsBaseCommands;
+import glide.api.models.GlideString;
import glide.api.models.Script;
import glide.api.models.commands.ExpireOptions;
+import glide.api.models.commands.GetExOptions;
import glide.api.models.commands.LInsertOptions.InsertPosition;
import glide.api.models.commands.LPosOptions;
import glide.api.models.commands.ListDirection;
@@ -172,6 +194,7 @@
import glide.api.models.commands.RangeOptions.RangeQuery;
import glide.api.models.commands.RangeOptions.ScoreRange;
import glide.api.models.commands.RangeOptions.ScoredRangeQuery;
+import glide.api.models.commands.RestoreOptions;
import glide.api.models.commands.ScoreFilter;
import glide.api.models.commands.ScriptOptions;
import glide.api.models.commands.SetOptions;
@@ -185,7 +208,10 @@
import glide.api.models.commands.geospatial.GeoUnit;
import glide.api.models.commands.geospatial.GeospatialData;
import glide.api.models.commands.stream.StreamAddOptions;
+import glide.api.models.commands.stream.StreamGroupOptions;
+import glide.api.models.commands.stream.StreamPendingOptions;
import glide.api.models.commands.stream.StreamRange;
+import glide.api.models.commands.stream.StreamReadGroupOptions;
import glide.api.models.commands.stream.StreamReadOptions;
import glide.api.models.commands.stream.StreamTrimOptions;
import glide.api.models.configuration.BaseClientConfiguration;
@@ -199,8 +225,8 @@
import glide.managers.BaseCommandResponseResolver;
import glide.managers.CommandManager;
import glide.managers.ConnectionManager;
-import java.util.Arrays;
import java.util.EnumSet;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -228,7 +254,8 @@ public abstract class BaseClient
StreamBaseCommands,
HyperLogLogBaseCommands,
GeospatialIndicesBaseCommands,
- ScriptingAndFunctionsBaseCommands {
+ ScriptingAndFunctionsBaseCommands,
+ TransactionsBaseCommands {
/** Redis simple string response with "OK" */
public static final String OK = ConstantResponse.OK.toString();
@@ -303,12 +330,18 @@ protected static CommandManager buildCommandManager(ChannelHandler channelHandle
/**
* Extracts the value from a GLIDE core
response message and either throws an
- * exception or returns the value as an object of type T
. If isNullable
,
- * than also returns null
.
+ * exception or returns the value as an object of type T
.
*
* @param response Redis protobuf message.
* @param classType Parameter T
class type.
- * @param isNullable Accepts null values in the protobuf message.
+ * @param flags A set of parameters which describes how to handle the response. Could be empty or
+ * any combination of
+ *
+ * - {@link ResponseFlags#ENCODING_UTF8} to return the data as a
String
; if
+ * unset, a byte[]
is returned.
+ * - {@link ResponseFlags#IS_NULLABLE} to accept
null
values.
+ *
+ *
* @return Response as an object of type T
or null
.
* @param The return value type.
* @throws RedisException On a type mismatch.
@@ -326,6 +359,9 @@ protected T handleRedisResponse(
if (isNullable && (value == null)) {
return null;
}
+
+ value = convertByteArrayToGlideString(value);
+
if (classType.isInstance(value)) {
return (T) value;
}
@@ -352,7 +388,19 @@ protected String handleStringOrNullResponse(Response response) throws RedisExcep
}
protected byte[] handleBytesOrNullResponse(Response response) throws RedisException {
- return handleRedisResponse(byte[].class, EnumSet.of(ResponseFlags.IS_NULLABLE), response);
+ var result =
+ handleRedisResponse(GlideString.class, EnumSet.of(ResponseFlags.IS_NULLABLE), response);
+ if (result == null) return null;
+
+ return result.getBytes();
+ }
+
+ protected GlideString handleGlideStringOrNullResponse(Response response) throws RedisException {
+ return handleRedisResponse(GlideString.class, EnumSet.of(ResponseFlags.IS_NULLABLE), response);
+ }
+
+ protected GlideString handleGlideStringResponse(Response response) throws RedisException {
+ return handleRedisResponse(GlideString.class, EnumSet.noneOf(ResponseFlags.class), response);
}
protected Boolean handleBooleanResponse(Response response) throws RedisException {
@@ -386,6 +434,10 @@ protected Object[] handleArrayOrNullResponse(Response response) throws RedisExce
response);
}
+ protected Object[] handleArrayOrNullResponseBinary(Response response) throws RedisException {
+ return handleRedisResponse(Object[].class, EnumSet.of(ResponseFlags.IS_NULLABLE), response);
+ }
+
/**
* @param response A Protobuf response
* @return A map of String
to V
.
@@ -396,6 +448,19 @@ protected Map handleMapResponse(Response response) throws RedisEx
return handleRedisResponse(Map.class, EnumSet.of(ResponseFlags.ENCODING_UTF8), response);
}
+ /**
+ * Get a map and convert {@link Map} keys from byte[]
to {@link String}.
+ *
+ * @param response A Protobuf response
+ * @return A map of GlideString
to V
.
+ * @param Value type.
+ */
+ @SuppressWarnings("unchecked") // raw Map cast to Map
+ protected Map handleBinaryStringMapResponse(Response response)
+ throws RedisException {
+ return handleRedisResponse(Map.class, EnumSet.noneOf(ResponseFlags.class), response);
+ }
+
/**
* @param response A Protobuf response
* @return A map of String
to V
or null
@@ -429,6 +494,11 @@ protected Set handleSetResponse(Response response) throws RedisException
return handleRedisResponse(Set.class, EnumSet.of(ResponseFlags.ENCODING_UTF8), response);
}
+ @SuppressWarnings("unchecked")
+ protected Set handleSetBinaryResponse(Response response) throws RedisException {
+ return handleRedisResponse(Set.class, EnumSet.noneOf(ResponseFlags.class), response);
+ }
+
/** Process a FUNCTION LIST
standalone response. */
@SuppressWarnings("unchecked")
protected Map[] handleFunctionListResponse(Object[] response) {
@@ -452,6 +522,21 @@ protected Map> handleFunctionStatsResponse(
return response;
}
+ /** Process a LCS key1 key2 IDX
response */
+ protected Map handleLcsIdxResponse(Map response)
+ throws RedisException {
+ Long[][][] convertedMatchesObject =
+ cast3DArray((Object[]) (response.get(LCS_MATCHES_RESULT_KEY)), Long.class);
+
+ if (convertedMatchesObject == null) {
+ throw new NullPointerException(
+ "LCS result does not contain the key \"" + LCS_MATCHES_RESULT_KEY + "\"");
+ }
+
+ response.put("matches", convertedMatchesObject);
+ return response;
+ }
+
@Override
public CompletableFuture del(@NonNull String[] keys) {
return commandManager.submitNewCommand(Del, keys, this::handleLongResponse);
@@ -464,9 +549,9 @@ public CompletableFuture get(@NonNull String key) {
}
@Override
- public CompletableFuture get(@NonNull byte[] key) {
+ public CompletableFuture get(@NonNull GlideString key) {
return commandManager.submitNewCommand(
- Get, Arrays.asList(key), this::handleBytesOrNullResponse);
+ Get, new GlideString[] {key}, this::handleGlideStringOrNullResponse);
}
@Override
@@ -476,9 +561,27 @@ public CompletableFuture getdel(@NonNull String key) {
}
@Override
- public CompletableFuture set(@NonNull byte[] key, @NonNull byte[] value) {
+ public CompletableFuture getex(@NonNull String key) {
+ return commandManager.submitNewCommand(
+ GetEx, new String[] {key}, this::handleStringOrNullResponse);
+ }
+
+ @Override
+ public CompletableFuture getex(@NonNull String key, @NonNull GetExOptions options) {
+ String[] arguments = ArrayUtils.addFirst(options.toArgs(), key);
+ return commandManager.submitNewCommand(GetEx, arguments, this::handleStringOrNullResponse);
+ }
+
+ @Override
+ public CompletableFuture getdel(@NonNull GlideString key) {
+ return commandManager.submitNewCommand(
+ GetDel, new GlideString[] {key}, this::handleGlideStringOrNullResponse);
+ }
+
+ @Override
+ public CompletableFuture set(@NonNull GlideString key, @NonNull GlideString value) {
return commandManager.submitNewCommand(
- Set, Arrays.asList(key, value), this::handleStringResponse);
+ Set, new GlideString[] {key, value}, this::handleStringResponse);
}
@Override
@@ -494,18 +597,40 @@ public CompletableFuture set(
return commandManager.submitNewCommand(Set, arguments, this::handleStringOrNullResponse);
}
+ @Override
+ public CompletableFuture set(
+ @NonNull GlideString key, @NonNull GlideString value, @NonNull SetOptions options) {
+ GlideString[] arguments =
+ ArrayUtils.addAll(new GlideString[] {key, value}, options.toGlideStringArgs());
+ return commandManager.submitNewCommand(Set, arguments, this::handleStringOrNullResponse);
+ }
+
@Override
public CompletableFuture append(@NonNull String key, @NonNull String value) {
return commandManager.submitNewCommand(
Append, new String[] {key, value}, this::handleLongResponse);
}
+ @Override
+ public CompletableFuture append(@NonNull GlideString key, @NonNull GlideString value) {
+ return commandManager.submitNewCommand(
+ Append, new GlideString[] {key, value}, this::handleLongResponse);
+ }
+
@Override
public CompletableFuture mget(@NonNull String[] keys) {
return commandManager.submitNewCommand(
MGet, keys, response -> castArray(handleArrayOrNullResponse(response), String.class));
}
+ @Override
+ public CompletableFuture mget(@NonNull GlideString[] keys) {
+ return commandManager.submitNewCommand(
+ MGet,
+ keys,
+ response -> castArray(handleArrayOrNullResponseBinary(response), GlideString.class));
+ }
+
@Override
public CompletableFuture mset(@NonNull Map keyValueMap) {
String[] args = convertMapToKeyValueStringArray(keyValueMap);
@@ -518,36 +643,73 @@ public CompletableFuture objectEncoding(@NonNull String key) {
ObjectEncoding, new String[] {key}, this::handleStringOrNullResponse);
}
+ @Override
+ public CompletableFuture objectEncoding(@NonNull GlideString key) {
+ return commandManager.submitNewCommand(
+ ObjectEncoding, new GlideString[] {key}, this::handleStringOrNullResponse);
+ }
+
@Override
public CompletableFuture objectFreq(@NonNull String key) {
return commandManager.submitNewCommand(
ObjectFreq, new String[] {key}, this::handleLongOrNullResponse);
}
+ @Override
+ public CompletableFuture objectFreq(@NonNull GlideString key) {
+ return commandManager.submitNewCommand(
+ ObjectFreq, new GlideString[] {key}, this::handleLongOrNullResponse);
+ }
+
@Override
public CompletableFuture objectIdletime(@NonNull String key) {
return commandManager.submitNewCommand(
ObjectIdleTime, new String[] {key}, this::handleLongOrNullResponse);
}
+ @Override
+ public CompletableFuture objectIdletime(@NonNull GlideString key) {
+ return commandManager.submitNewCommand(
+ ObjectIdleTime, new GlideString[] {key}, this::handleLongOrNullResponse);
+ }
+
@Override
public CompletableFuture objectRefcount(@NonNull String key) {
return commandManager.submitNewCommand(
ObjectRefCount, new String[] {key}, this::handleLongOrNullResponse);
}
+ @Override
+ public CompletableFuture objectRefcount(@NonNull GlideString key) {
+ return commandManager.submitNewCommand(
+ ObjectRefCount, new GlideString[] {key}, this::handleLongOrNullResponse);
+ }
+
@Override
public CompletableFuture rename(@NonNull String key, @NonNull String newKey) {
return commandManager.submitNewCommand(
Rename, new String[] {key, newKey}, this::handleStringResponse);
}
+ @Override
+ public CompletableFuture rename(@NonNull GlideString key, @NonNull GlideString newKey) {
+ return commandManager.submitNewCommand(
+ Rename, new GlideString[] {key, newKey}, this::handleStringResponse);
+ }
+
@Override
public CompletableFuture renamenx(@NonNull String key, @NonNull String newKey) {
return commandManager.submitNewCommand(
RenameNX, new String[] {key, newKey}, this::handleBooleanResponse);
}
+ @Override
+ public CompletableFuture renamenx(
+ @NonNull GlideString key, @NonNull GlideString newKey) {
+ return commandManager.submitNewCommand(
+ RenameNX, new GlideString[] {key, newKey}, this::handleBooleanResponse);
+ }
+
@Override
public CompletableFuture incr(@NonNull String key) {
return commandManager.submitNewCommand(Incr, new String[] {key}, this::handleLongResponse);
@@ -559,12 +721,28 @@ public CompletableFuture incrBy(@NonNull String key, long amount) {
IncrBy, new String[] {key, Long.toString(amount)}, this::handleLongResponse);
}
+ @Override
+ public CompletableFuture incrBy(@NonNull GlideString key, long amount) {
+ return commandManager.submitNewCommand(
+ IncrBy,
+ new GlideString[] {key, gs(Long.toString(amount).getBytes())},
+ this::handleLongResponse);
+ }
+
@Override
public CompletableFuture incrByFloat(@NonNull String key, double amount) {
return commandManager.submitNewCommand(
IncrByFloat, new String[] {key, Double.toString(amount)}, this::handleDoubleResponse);
}
+ @Override
+ public CompletableFuture incrByFloat(@NonNull GlideString key, double amount) {
+ return commandManager.submitNewCommand(
+ IncrByFloat,
+ new GlideString[] {key, gs(Double.toString(amount).getBytes())},
+ this::handleDoubleResponse);
+ }
+
@Override
public CompletableFuture decr(@NonNull String key) {
return commandManager.submitNewCommand(Decr, new String[] {key}, this::handleLongResponse);
@@ -581,6 +759,12 @@ public CompletableFuture strlen(@NonNull String key) {
return commandManager.submitNewCommand(Strlen, new String[] {key}, this::handleLongResponse);
}
+ @Override
+ public CompletableFuture strlen(@NonNull GlideString key) {
+ return commandManager.submitNewCommand(
+ Strlen, new GlideString[] {key}, this::handleLongResponse);
+ }
+
@Override
public CompletableFuture setrange(@NonNull String key, int offset, @NonNull String value) {
String[] arguments = new String[] {key, Integer.toString(offset), value};
@@ -613,6 +797,13 @@ public CompletableFuture hsetnx(
HSetNX, new String[] {key, field, value}, this::handleBooleanResponse);
}
+ @Override
+ public CompletableFuture hsetnx(
+ @NonNull GlideString key, @NonNull GlideString field, @NonNull GlideString value) {
+ return commandManager.submitNewCommand(
+ HSetNX, new GlideString[] {key, field, value}, this::handleBooleanResponse);
+ }
+
@Override
public CompletableFuture hdel(@NonNull String key, @NonNull String[] fields) {
String[] args = ArrayUtils.addFirst(fields, key);
@@ -645,17 +836,38 @@ public CompletableFuture hexists(@NonNull String key, @NonNull String f
HExists, new String[] {key, field}, this::handleBooleanResponse);
}
+ @Override
+ public CompletableFuture hexists(@NonNull GlideString key, @NonNull GlideString field) {
+ return commandManager.submitNewCommand(
+ HExists, new GlideString[] {key, field}, this::handleBooleanResponse);
+ }
+
@Override
public CompletableFuture