Skip to content

Commit

Permalink
specifying keys in read/write commands (#463)
Browse files Browse the repository at this point in the history
  • Loading branch information
slorello89 authored Jul 15, 2024
1 parent 27edd7b commit 28b34e0
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 32 deletions.
39 changes: 20 additions & 19 deletions src/Redis.OM/RedisCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Threading.Tasks;
using Redis.OM.Contracts;
using Redis.OM.Modeling;
using StackExchange.Redis;

namespace Redis.OM
{
Expand Down Expand Up @@ -84,7 +85,7 @@ public static async Task<string> SetAsync(this IRedisConnection connection, obje
/// <returns>How many new fields were created.</returns>
public static async Task<int> HSetAsync(this IRedisConnection connection, string key, params KeyValuePair<string, object>[] fieldValues)
{
var args = new List<object> { key };
var args = new List<object> { new RedisKey(key) };
foreach (var kvp in fieldValues)
{
args.Add(kvp.Key);
Expand All @@ -104,7 +105,7 @@ public static async Task<int> HSetAsync(this IRedisConnection connection, string
/// <returns>How many new fields were created.</returns>
public static async Task<int> HSetAsync(this IRedisConnection connection, string key, TimeSpan timeSpan, params KeyValuePair<string, object>[] fieldValues)
{
var args = new List<object> { key };
var args = new List<object> { new RedisKey(key) };
foreach (var kvp in fieldValues)
{
args.Add(kvp.Key);
Expand All @@ -124,7 +125,7 @@ public static async Task<int> HSetAsync(this IRedisConnection connection, string
/// <returns>whether the operation succeeded.</returns>
public static async Task<bool> JsonSetAsync(this IRedisConnection connection, string key, string path, string json)
{
var result = await connection.ExecuteAsync("JSON.SET", key, path, json);
var result = await connection.ExecuteAsync("JSON.SET", new RedisKey(key), path, json);
return result == "OK";
}

Expand All @@ -139,7 +140,7 @@ public static async Task<bool> JsonSetAsync(this IRedisConnection connection, st
public static async Task<bool> JsonSetAsync(this IRedisConnection connection, string key, string path, object obj)
{
var json = JsonSerializer.Serialize(obj, RedisSerializationSettings.JsonSerializerOptions);
var result = await connection.ExecuteAsync("JSON.SET", key, path, json);
var result = await connection.ExecuteAsync("JSON.SET", new RedisKey(key), path, json);
return result == "OK";
}

Expand All @@ -154,7 +155,7 @@ public static async Task<bool> JsonSetAsync(this IRedisConnection connection, st
/// <returns>whether the operation succeeded.</returns>
public static async Task<bool> JsonSetAsync(this IRedisConnection connection, string key, string path, string json, TimeSpan timeSpan)
{
var args = new[] { key, path, json };
var args = new object[] { new RedisKey(key), path, json };
return (await connection.SendCommandWithExpiryAsync("JSON.SET", args, key, timeSpan)).First() == "OK";
}

Expand Down Expand Up @@ -227,7 +228,7 @@ public static async Task<bool> JsonSetAsync(this IRedisConnection connection, st
public static int HSet(this IRedisConnection connection, string key, TimeSpan timeSpan, params KeyValuePair<string, object>[] fieldValues)
{
var args = new List<object>();
args.Add(key);
args.Add(new RedisKey(key));
foreach (var kvp in fieldValues)
{
args.Add(kvp.Key);
Expand All @@ -246,7 +247,7 @@ public static int HSet(this IRedisConnection connection, string key, TimeSpan ti
/// <returns>How many new fields were created.</returns>
public static int HSet(this IRedisConnection connection, string key, params KeyValuePair<string, object>[] fieldValues)
{
var args = new List<object> { key };
var args = new List<object> { new RedisKey(key) };
foreach (var kvp in fieldValues)
{
args.Add(kvp.Key);
Expand All @@ -266,7 +267,7 @@ public static int HSet(this IRedisConnection connection, string key, params KeyV
/// <returns>whether the operation succeeded.</returns>
public static bool JsonSet(this IRedisConnection connection, string key, string path, string json)
{
var result = connection.Execute("JSON.SET", key, path, json);
var result = connection.Execute("JSON.SET", new RedisKey(key), path, json);
return result == "OK";
}

Expand All @@ -281,7 +282,7 @@ public static bool JsonSet(this IRedisConnection connection, string key, string
public static bool JsonSet(this IRedisConnection connection, string key, string path, object obj)
{
var json = JsonSerializer.Serialize(obj, RedisSerializationSettings.JsonSerializerOptions);
var result = connection.Execute("JSON.SET", key, path, json);
var result = connection.Execute("JSON.SET", new RedisKey(key), path, json);
return result == "OK";
}

Expand All @@ -296,7 +297,7 @@ public static bool JsonSet(this IRedisConnection connection, string key, string
/// <returns>whether the operation succeeded.</returns>
public static bool JsonSet(this IRedisConnection connection, string key, string path, string json, TimeSpan timeSpan)
{
var arr = new[] { key, path, json };
var arr = new object[] { new RedisKey(key), path, json };
return connection.SendCommandWithExpiry("JSON.SET", arr, key, timeSpan).First() == "OK";
}

Expand Down Expand Up @@ -570,7 +571,7 @@ public static string Set(this IRedisConnection connection, object obj, TimeSpan
/// <returns>the object pulled out of redis.</returns>
public static T? JsonGet<T>(this IRedisConnection connection, string key, params string[] paths)
{
var args = new List<string> { key };
var args = new List<object> { new RedisKey(key) };
args.AddRange(paths);
var res = (string)connection.Execute("JSON.GET", args.ToArray());
return !string.IsNullOrEmpty(res) ? JsonSerializer.Deserialize<T>(res, RedisSerializationSettings.JsonSerializerOptions) : default;
Expand All @@ -586,7 +587,7 @@ public static string Set(this IRedisConnection connection, object obj, TimeSpan
/// <returns>the object pulled out of redis.</returns>
public static async Task<T?> JsonGetAsync<T>(this IRedisConnection connection, string key, params string[] paths)
{
var args = new List<string> { key };
var args = new List<object> { new RedisKey(key) };
args.AddRange(paths);
var res = (string)await connection.ExecuteAsync("JSON.GET", args.ToArray());
return !string.IsNullOrEmpty(res) ? JsonSerializer.Deserialize<T>(res, RedisSerializationSettings.JsonSerializerOptions) : default;
Expand All @@ -601,7 +602,7 @@ public static string Set(this IRedisConnection connection, object obj, TimeSpan
public static IDictionary<string, RedisReply> HGetAll(this IRedisConnection connection, string keyName)
{
var ret = new Dictionary<string, RedisReply>();
var res = connection.Execute("HGETALL", keyName).ToArray();
var res = connection.Execute("HGETALL", new RedisKey(keyName)).ToArray();
for (var i = 0; i < res.Length; i += 2)
{
ret.Add(res[i], res[i + 1]);
Expand All @@ -619,7 +620,7 @@ public static IDictionary<string, RedisReply> HGetAll(this IRedisConnection conn
public static async Task<IDictionary<string, RedisReply>> HGetAllAsync(this IRedisConnection connection, string keyName)
{
var ret = new Dictionary<string, RedisReply>();
var res = (await connection.ExecuteAsync("HGETALL", keyName)).ToArray();
var res = (await connection.ExecuteAsync("HGETALL", new RedisKey(keyName))).ToArray();
for (var i = 0; i < res.Length; i += 2)
{
ret.Add(res[i], res[i + 1]);
Expand Down Expand Up @@ -664,7 +665,7 @@ public static async Task<IDictionary<string, RedisReply>> HGetAllAsync(this IRed
sha,
keys.Count().ToString(),
};
args.AddRange(keys);
args.AddRange(keys.Select(x => new RedisKey(x)).Cast<object>());
args.AddRange(argv);
try
{
Expand Down Expand Up @@ -756,15 +757,15 @@ public static async Task<IDictionary<string, RedisReply>> HGetAllAsync(this IRed
/// <param name="connection">the connection.</param>
/// <param name="key">the key to unlink.</param>
/// <returns>the status.</returns>
public static async Task<long> UnlinkAsync(this IRedisConnection connection, string key) => await connection.ExecuteAsync("UNLINK", key);
public static async Task<long> UnlinkAsync(this IRedisConnection connection, string key) => await connection.ExecuteAsync("UNLINK", new RedisKey(key));

/// <summary>
/// Unlinks array of keys.
/// </summary>
/// <param name="connection">the connection.</param>
/// <param name="keys">the keys to unlink.</param>
/// <returns>the status.</returns>
public static async Task<long> UnlinkAsync(this IRedisConnection connection, string[] keys) => await connection.ExecuteAsync("UNLINK", keys);
public static async Task<long> UnlinkAsync(this IRedisConnection connection, string[] keys) => await connection.ExecuteAsync("UNLINK", keys.Select(x => new RedisKey(x)).Cast<object>().ToArray());

/// <summary>
/// Unlinks the key and then adds an updated value of it.
Expand Down Expand Up @@ -835,7 +836,7 @@ private static RedisReply[] SendCommandWithExpiry(
TimeSpan ts)
{
var commandTuple = Tuple.Create(command, args);
var expireTuple = Tuple.Create("PEXPIRE", new object[] { keyToExpire, ((long)ts.TotalMilliseconds).ToString(CultureInfo.InvariantCulture) });
var expireTuple = Tuple.Create("PEXPIRE", new object[] { new RedisKey(keyToExpire), ((long)ts.TotalMilliseconds).ToString(CultureInfo.InvariantCulture) });
return connection.ExecuteInTransaction(new[] { commandTuple, expireTuple });
}

Expand All @@ -847,7 +848,7 @@ private static Task<RedisReply[]> SendCommandWithExpiryAsync(
TimeSpan ts)
{
var commandTuple = Tuple.Create(command, args);
var expireTuple = Tuple.Create("PEXPIRE", new object[] { keyToExpire, ((long)ts.TotalMilliseconds).ToString(CultureInfo.InvariantCulture) });
var expireTuple = Tuple.Create("PEXPIRE", new object[] { new RedisKey(keyToExpire), ((long)ts.TotalMilliseconds).ToString(CultureInfo.InvariantCulture) });
return connection.ExecuteInTransactionAsync(new[] { commandTuple, expireTuple });
}
}
Expand Down
20 changes: 20 additions & 0 deletions test/Redis.OM.Unit.Tests/CoreTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -493,5 +493,25 @@ public void TestUnlink()
connection.Execute("SET", key1, "bar");
Assert.Equal(1,connection.Unlink(new []{key1, key2}));
}

[SkipIfMissingEnvVar("CLUSTER_HOST_PORT")]
public async Task TestClusterOperations()
{
var hostInfo = System.Environment.GetEnvironmentVariable("CLUSTER_HOST_PORT");
Console.WriteLine($"Current host info: {hostInfo}");
var connectionString = $"redis://{hostInfo}";
var provider = new RedisConnectionProvider(connectionString);
var connection = provider.Connection;

var tasks = new List<Task>();
for(var i = 0; i < 10_000; i++)
{
var person = new Person();
tasks.Add(connection.SetAsync(person));
}

await Task.WhenAll(tasks);
}

}
}
22 changes: 11 additions & 11 deletions test/Redis.OM.Unit.Tests/RediSearchTests/SearchTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -992,7 +992,7 @@ public async Task TestUpdateJson()
var steve = await collection.FirstAsync(x => x.Name == "Steve");
steve.Age = 33;
await collection.UpdateAsync(steve);
await _substitute.Received().ExecuteAsync("EVALSHA", Arg.Any<string>(), "1", "Redis.OM.Unit.Tests.RediSearchTests.Person:01FVN836BNQGYMT80V7RCVY73N", "SET", "$.Age", "33");
await _substitute.Received().ExecuteAsync("EVALSHA", Arg.Any<string>(), "1", new RedisKey("Redis.OM.Unit.Tests.RediSearchTests.Person:01FVN836BNQGYMT80V7RCVY73N"), "SET", "$.Age", "33");
Scripts.ShaCollection.Clear();
}

Expand All @@ -1010,8 +1010,8 @@ public async Task TestUpdateJsonUnloadedScriptAsync()
var steve = await collection.FirstAsync(x => x.Name == "Steve");
steve.Age = 33;
await collection.UpdateAsync(steve);
await _substitute.Received().ExecuteAsync("EVALSHA", Arg.Any<string>(), "1", "Redis.OM.Unit.Tests.RediSearchTests.Person:01FVN836BNQGYMT80V7RCVY73N", "SET", "$.Age", "33");
await _substitute.Received().ExecuteAsync("EVAL", Scripts.JsonDiffResolution, "1", "Redis.OM.Unit.Tests.RediSearchTests.Person:01FVN836BNQGYMT80V7RCVY73N", "SET", "$.Age", "33");
await _substitute.Received().ExecuteAsync("EVALSHA", Arg.Any<string>(), "1", new RedisKey("Redis.OM.Unit.Tests.RediSearchTests.Person:01FVN836BNQGYMT80V7RCVY73N"), "SET", "$.Age", "33");
await _substitute.Received().ExecuteAsync("EVAL", Scripts.JsonDiffResolution, "1", new RedisKey("Redis.OM.Unit.Tests.RediSearchTests.Person:01FVN836BNQGYMT80V7RCVY73N"), "SET", "$.Age", "33");
Scripts.ShaCollection.Clear();
}

Expand All @@ -1028,8 +1028,8 @@ public void TestUpdateJsonUnloadedScript()
var steve = collection.First(x => x.Name == "Steve");
steve.Age = 33;
collection.Update(steve);
_substitute.Received().Execute("EVALSHA", Arg.Any<string>(), "1", "Redis.OM.Unit.Tests.RediSearchTests.Person:01FVN836BNQGYMT80V7RCVY73N", "SET", "$.Age", "33");
_substitute.Received().Execute("EVAL", Scripts.JsonDiffResolution, "1", "Redis.OM.Unit.Tests.RediSearchTests.Person:01FVN836BNQGYMT80V7RCVY73N", "SET", "$.Age", "33");
_substitute.Received().Execute("EVALSHA", Arg.Any<string>(), "1", new RedisKey("Redis.OM.Unit.Tests.RediSearchTests.Person:01FVN836BNQGYMT80V7RCVY73N"), "SET", "$.Age", "33");
_substitute.Received().Execute("EVAL", Scripts.JsonDiffResolution, "1", new RedisKey("Redis.OM.Unit.Tests.RediSearchTests.Person:01FVN836BNQGYMT80V7RCVY73N"), "SET", "$.Age", "33");
Scripts.ShaCollection.Clear();
}

Expand All @@ -1043,7 +1043,7 @@ public async Task TestUpdateJsonName()
var steve = await collection.FirstAsync(x => x.Name == "Steve");
steve.Name = "Bob";
await collection.UpdateAsync(steve);
await _substitute.Received().ExecuteAsync("EVALSHA", Arg.Any<string>(), "1", "Redis.OM.Unit.Tests.RediSearchTests.Person:01FVN836BNQGYMT80V7RCVY73N", "SET", "$.Name", "\"Bob\"");
await _substitute.Received().ExecuteAsync("EVALSHA", Arg.Any<string>(), "1", new RedisKey("Redis.OM.Unit.Tests.RediSearchTests.Person:01FVN836BNQGYMT80V7RCVY73N"), "SET", "$.Name", "\"Bob\"");
Scripts.ShaCollection.Clear();
}

Expand All @@ -1058,12 +1058,12 @@ public async Task TestUpdateJsonNestedObject()
steve.Address = new Address { State = "Florida" };
await collection.UpdateAsync(steve);
var expected = $"{{{Environment.NewLine} \"State\": \"Florida\"{Environment.NewLine}}}";
await _substitute.Received().ExecuteAsync("EVALSHA", Arg.Any<string>(), "1", "Redis.OM.Unit.Tests.RediSearchTests.Person:01FVN836BNQGYMT80V7RCVY73N", "SET", "$.Address", expected);
await _substitute.Received().ExecuteAsync("EVALSHA", Arg.Any<string>(), "1", new RedisKey("Redis.OM.Unit.Tests.RediSearchTests.Person:01FVN836BNQGYMT80V7RCVY73N"), "SET", "$.Address", expected);

steve.Address.City = "Satellite Beach";
await collection.UpdateAsync(steve);
expected = "\"Satellite Beach\"";
await _substitute.Received().ExecuteAsync("EVALSHA", Arg.Any<string>(), "1", "Redis.OM.Unit.Tests.RediSearchTests.Person:01FVN836BNQGYMT80V7RCVY73N", "SET", "$.Address.City", expected);
await _substitute.Received().ExecuteAsync("EVALSHA", Arg.Any<string>(), "1", new RedisKey("Redis.OM.Unit.Tests.RediSearchTests.Person:01FVN836BNQGYMT80V7RCVY73N"), "SET", "$.Address.City", expected);

Scripts.ShaCollection.Clear();
}
Expand All @@ -1079,7 +1079,7 @@ public async Task TestUpdateJsonWithDouble()
steve.Age = 33;
steve.Height = 71.5;
await collection.UpdateAsync(steve);
await _substitute.Received().ExecuteAsync("EVALSHA", Arg.Any<string>(), "1", "Redis.OM.Unit.Tests.RediSearchTests.Person:01FVN836BNQGYMT80V7RCVY73N", "SET", "$.Age", "33", "SET", "$.Height", "71.5");
await _substitute.Received().ExecuteAsync("EVALSHA", Arg.Any<string>(), "1", new RedisKey("Redis.OM.Unit.Tests.RediSearchTests.Person:01FVN836BNQGYMT80V7RCVY73N"), "SET", "$.Age", "33", "SET", "$.Height", "71.5");
Scripts.ShaCollection.Clear();
}

Expand All @@ -1103,7 +1103,7 @@ public async Task TestDeleteAsync()
Assert.True(collection.StateManager.Data.ContainsKey(key));
Assert.True(collection.StateManager.Snapshot.ContainsKey(key));
await collection.DeleteAsync(steve);
await _substitute.Received().ExecuteAsync("UNLINK", key);
await _substitute.Received().ExecuteAsync("UNLINK", new RedisKey(key));
Assert.False(collection.StateManager.Data.ContainsKey(key));
Assert.False(collection.StateManager.Snapshot.ContainsKey(key));
}
Expand All @@ -1119,7 +1119,7 @@ public void TestDelete()
Assert.True(collection.StateManager.Data.ContainsKey(key));
Assert.True(collection.StateManager.Snapshot.ContainsKey(key));
collection.Delete(steve);
_substitute.Received().Execute("UNLINK", key);
_substitute.Received().Execute("UNLINK", new RedisKey(key));
Assert.False(collection.StateManager.Data.ContainsKey(key));
Assert.False(collection.StateManager.Snapshot.ContainsKey(key));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Redis.OM.Modeling;
using Redis.OM.Modeling.Vectors;
using Redis.OM.Searching;
using StackExchange.Redis;
using Xunit;

namespace Redis.OM.Unit.Tests;
Expand Down Expand Up @@ -189,9 +190,9 @@ public void InsertVectors()
_substitute.Execute("JSON.SET", Arg.Any<object[]>()).Returns(new RedisReply("OK"));
_substitute.Set(hashObj);
_substitute.Set(jsonObj);
_substitute.Received().Execute("HSET", "Redis.OM.Unit.Tests.ObjectWithVectorHash:foo", "Id", "foo", "Num", "0", "SimpleHnswVector",
_substitute.Received().Execute("HSET", new RedisKey("Redis.OM.Unit.Tests.ObjectWithVectorHash:foo"), "Id", "foo", "Num", "0", "SimpleHnswVector",
Arg.Is<byte[]>(x=>x.SequenceEqual(simpleHnswBytes)), "SimpleVectorizedVector.Vector", Arg.Is<byte[]>(x=>x.SequenceEqual(flatVectorizedBytes)), "SimpleVectorizedVector.Value", "\"foobar\"");
_substitute.Received().Execute("JSON.SET", "Redis.OM.Unit.Tests.ObjectWithVector:foo", ".", json);
_substitute.Received().Execute("JSON.SET", new RedisKey("Redis.OM.Unit.Tests.ObjectWithVector:foo"), ".", json);
var deseralized = JsonSerializer.Deserialize<ObjectWithVector>(json);
Assert.Equal("foobar", deseralized.SimpleVectorizedVector.Value);
}
Expand Down

0 comments on commit 28b34e0

Please sign in to comment.