diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml
index 679e796fd..1796710a7 100644
--- a/.github/workflows/CI.yml
+++ b/.github/workflows/CI.yml
@@ -30,6 +30,7 @@ jobs:
dotnet-version: |
6.0.x
8.0.x
+ 9.0.x
- name: .NET Build
run: dotnet build Build.csproj -c Release /p:CI=true
- name: StackExchange.Redis.Tests
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 12097728a..6d15ad199 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -8,25 +8,24 @@
-
-
+
-
+
-
+
-
+
-
+
-
-
+
+
\ No newline at end of file
diff --git a/StackExchange.Redis.sln b/StackExchange.Redis.sln
index f59d5f6fc..18a30a9af 100644
--- a/StackExchange.Redis.sln
+++ b/StackExchange.Redis.sln
@@ -93,7 +93,6 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{73A5C363-CA1F-44C4-9A9B-EF791A76BA6A}"
ProjectSection(SolutionItems) = preProject
tests\.editorconfig = tests\.editorconfig
- tests\Directory.Build.props = tests\Directory.Build.props
tests\Directory.Build.targets = tests\Directory.Build.targets
EndProjectSection
EndProject
diff --git a/appveyor.yml b/appveyor.yml
index d9dd350af..b180c6544 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -9,6 +9,8 @@ install:
choco install dotnet-6.0-sdk
choco install dotnet-7.0-sdk
+
+ choco install dotnet-9.0-sdk
cd tests\RedisConfigs\3.0.503
diff --git a/docs/ReleaseNotes.md b/docs/ReleaseNotes.md
index 62edec160..c775f6cb3 100644
--- a/docs/ReleaseNotes.md
+++ b/docs/ReleaseNotes.md
@@ -8,7 +8,7 @@ Current package versions:
## Unreleased
-No pending unreleased changes
+- Package updates ([#2906 by mgravell](https://github.com/StackExchange/StackExchange.Redis/pull/2906))
## 2.8.41
diff --git a/src/StackExchange.Redis/Interfaces/IServer.cs b/src/StackExchange.Redis/Interfaces/IServer.cs
index fad2d4232..4971c7f18 100644
--- a/src/StackExchange.Redis/Interfaces/IServer.cs
+++ b/src/StackExchange.Redis/Interfaces/IServer.cs
@@ -89,7 +89,7 @@ public partial interface IServer : IRedis
///
void ClientKill(EndPoint endpoint, CommandFlags flags = CommandFlags.None);
- ///
+ ///
Task ClientKillAsync(EndPoint endpoint, CommandFlags flags = CommandFlags.None);
///
@@ -104,7 +104,7 @@ public partial interface IServer : IRedis
///
long ClientKill(long? id = null, ClientType? clientType = null, EndPoint? endpoint = null, bool skipMe = true, CommandFlags flags = CommandFlags.None);
- ///
+ ///
Task ClientKillAsync(long? id = null, ClientType? clientType = null, EndPoint? endpoint = null, bool skipMe = true, CommandFlags flags = CommandFlags.None);
///
@@ -475,17 +475,17 @@ public partial interface IServer : IRedis
///
void Shutdown(ShutdownMode shutdownMode = ShutdownMode.Default, CommandFlags flags = CommandFlags.None);
- ///
+ ///
[Obsolete("Starting with Redis version 5, Redis has moved to 'replica' terminology. Please use " + nameof(ReplicaOfAsync) + " instead, this will be removed in 3.0.")]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
void SlaveOf(EndPoint master, CommandFlags flags = CommandFlags.None);
- ///
+ ///
[Obsolete("Starting with Redis version 5, Redis has moved to 'replica' terminology. Please use " + nameof(ReplicaOfAsync) + " instead, this will be removed in 3.0.")]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
Task SlaveOfAsync(EndPoint master, CommandFlags flags = CommandFlags.None);
- ///
+ ///
[Obsolete("Please use " + nameof(ReplicaOfAsync) + ", this will be removed in 3.0.")]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
void ReplicaOf(EndPoint master, CommandFlags flags = CommandFlags.None);
diff --git a/src/StackExchange.Redis/KeyspaceIsolation/KeyPrefixed.cs b/src/StackExchange.Redis/KeyspaceIsolation/KeyPrefixed.cs
index b97bba73b..f45c29886 100644
--- a/src/StackExchange.Redis/KeyspaceIsolation/KeyPrefixed.cs
+++ b/src/StackExchange.Redis/KeyspaceIsolation/KeyPrefixed.cs
@@ -351,7 +351,7 @@ public Task ScriptEvaluateAsync(byte[] hash, RedisKey[]? keys = nul
public Task ScriptEvaluateAsync(string script, RedisKey[]? keys = null, RedisValue[]? values = null, CommandFlags flags = CommandFlags.None) =>
// TODO: The return value could contain prefixed keys. It might make sense to 'unprefix' those?
- Inner.ScriptEvaluateAsync(script, ToInner(keys), values, flags);
+ Inner.ScriptEvaluateAsync(script: script, keys: ToInner(keys), values: values, flags: flags);
public Task ScriptEvaluateAsync(LuaScript script, object? parameters = null, CommandFlags flags = CommandFlags.None) =>
// TODO: The return value could contain prefixed keys. It might make sense to 'unprefix' those?
@@ -367,7 +367,7 @@ public Task ScriptEvaluateReadOnlyAsync(byte[] hash, RedisKey[]? ke
public Task ScriptEvaluateReadOnlyAsync(string script, RedisKey[]? keys = null, RedisValue[]? values = null, CommandFlags flags = CommandFlags.None) =>
// TODO: The return value could contain prefixed keys. It might make sense to 'unprefix' those?
- Inner.ScriptEvaluateAsync(script, ToInner(keys), values, flags);
+ Inner.ScriptEvaluateAsync(script: script, keys: ToInner(keys), values: values, flags: flags);
public Task SetAddAsync(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None) =>
Inner.SetAddAsync(ToInner(key), values, flags);
diff --git a/src/StackExchange.Redis/KeyspaceIsolation/KeyPrefixedDatabase.cs b/src/StackExchange.Redis/KeyspaceIsolation/KeyPrefixedDatabase.cs
index 75d93d0f9..a19dd0b7a 100644
--- a/src/StackExchange.Redis/KeyspaceIsolation/KeyPrefixedDatabase.cs
+++ b/src/StackExchange.Redis/KeyspaceIsolation/KeyPrefixedDatabase.cs
@@ -338,7 +338,7 @@ public RedisResult ScriptEvaluate(byte[] hash, RedisKey[]? keys = null, RedisVal
public RedisResult ScriptEvaluate(string script, RedisKey[]? keys = null, RedisValue[]? values = null, CommandFlags flags = CommandFlags.None) =>
// TODO: The return value could contain prefixed keys. It might make sense to 'unprefix' those?
- Inner.ScriptEvaluate(script, ToInner(keys), values, flags);
+ Inner.ScriptEvaluate(script: script, keys: ToInner(keys), values: values, flags: flags);
public RedisResult ScriptEvaluate(LuaScript script, object? parameters = null, CommandFlags flags = CommandFlags.None) =>
// TODO: The return value could contain prefixed keys. It might make sense to 'unprefix' those?
diff --git a/src/StackExchange.Redis/LuaScript.cs b/src/StackExchange.Redis/LuaScript.cs
index 8a9bdbcc1..7a99f635a 100644
--- a/src/StackExchange.Redis/LuaScript.cs
+++ b/src/StackExchange.Redis/LuaScript.cs
@@ -148,7 +148,7 @@ internal void ExtractParameters(object? ps, RedisKey? keyPrefix, out RedisKey[]?
public RedisResult Evaluate(IDatabase db, object? ps = null, RedisKey? withKeyPrefix = null, CommandFlags flags = CommandFlags.None)
{
ExtractParameters(ps, withKeyPrefix, out RedisKey[]? keys, out RedisValue[]? args);
- return db.ScriptEvaluate(ExecutableScript, keys, args, flags);
+ return db.ScriptEvaluate(script: ExecutableScript, keys: keys, values: args, flags: flags);
}
///
@@ -161,7 +161,7 @@ public RedisResult Evaluate(IDatabase db, object? ps = null, RedisKey? withKeyPr
public Task EvaluateAsync(IDatabaseAsync db, object? ps = null, RedisKey? withKeyPrefix = null, CommandFlags flags = CommandFlags.None)
{
ExtractParameters(ps, withKeyPrefix, out RedisKey[]? keys, out RedisValue[]? args);
- return db.ScriptEvaluateAsync(ExecutableScript, keys, args, flags);
+ return db.ScriptEvaluateAsync(script: ExecutableScript, keys: keys, values: args, flags: flags);
}
///
@@ -269,7 +269,7 @@ public RedisResult Evaluate(IDatabase db, object? ps = null, RedisKey? withKeyPr
{
Original.ExtractParameters(ps, withKeyPrefix, out RedisKey[]? keys, out RedisValue[]? args);
- return db.ScriptEvaluate(ExecutableScript, keys, args, flags);
+ return db.ScriptEvaluate(script: ExecutableScript, keys: keys, values: args, flags: flags);
}
///
@@ -287,7 +287,7 @@ public Task EvaluateAsync(IDatabaseAsync db, object? ps = null, Red
{
Original.ExtractParameters(ps, withKeyPrefix, out RedisKey[]? keys, out RedisValue[]? args);
- return db.ScriptEvaluateAsync(ExecutableScript, keys, args, flags);
+ return db.ScriptEvaluateAsync(script: ExecutableScript, keys: keys, values: args, flags: flags);
}
}
}
diff --git a/src/StackExchange.Redis/PhysicalConnection.cs b/src/StackExchange.Redis/PhysicalConnection.cs
index c92290696..8a0bad393 100644
--- a/src/StackExchange.Redis/PhysicalConnection.cs
+++ b/src/StackExchange.Redis/PhysicalConnection.cs
@@ -1598,8 +1598,8 @@ internal async ValueTask ConnectedAsync(Socket? socket, ILogger? log, Sock
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
- bridge.Multiplexer?.SetAuthSuspect(ex);
- bridge.Multiplexer?.Logger?.LogError(ex, ex.Message);
+ bridge.Multiplexer.SetAuthSuspect(ex);
+ bridge.Multiplexer.Logger?.LogError(ex, ex.Message);
throw;
}
log?.LogInformation($"TLS connection established successfully using protocol: {ssl.SslProtocol}");
diff --git a/src/StackExchange.Redis/ResultProcessor.cs b/src/StackExchange.Redis/ResultProcessor.cs
index 47974b278..03e0a8577 100644
--- a/src/StackExchange.Redis/ResultProcessor.cs
+++ b/src/StackExchange.Redis/ResultProcessor.cs
@@ -234,11 +234,11 @@ public virtual bool SetResult(PhysicalConnection connection, Message message, in
{
if (result.StartsWith(CommonReplies.NOAUTH))
{
- bridge?.Multiplexer?.SetAuthSuspect(new RedisServerException("NOAUTH Returned - connection has not yet authenticated"));
+ bridge?.Multiplexer.SetAuthSuspect(new RedisServerException("NOAUTH Returned - connection has not yet authenticated"));
}
else if (result.StartsWith(CommonReplies.WRONGPASS))
{
- bridge?.Multiplexer?.SetAuthSuspect(new RedisServerException(result.ToString()));
+ bridge?.Multiplexer.SetAuthSuspect(new RedisServerException(result.ToString()));
}
var server = bridge?.ServerEndPoint;
@@ -259,7 +259,7 @@ public virtual bool SetResult(PhysicalConnection connection, Message message, in
// no point sending back to same server, and no point sending to a dead server
if (!Equals(server?.EndPoint, endpoint))
{
- if (bridge == null)
+ if (bridge is null)
{
// already toast
}
@@ -308,7 +308,7 @@ public virtual bool SetResult(PhysicalConnection connection, Message message, in
{
bridge?.Multiplexer.OnErrorMessage(server.EndPoint, err);
}
- bridge?.Multiplexer?.Trace("Completed with error: " + err + " (" + GetType().Name + ")", ToString());
+ bridge?.Multiplexer.Trace("Completed with error: " + err + " (" + GetType().Name + ")", ToString());
if (unableToConnectError)
{
ConnectionFail(message, ConnectionFailureType.UnableToConnect, err);
@@ -323,7 +323,7 @@ public virtual bool SetResult(PhysicalConnection connection, Message message, in
bool coreResult = SetResultCore(connection, message, result);
if (coreResult)
{
- bridge?.Multiplexer?.Trace("Completed with success: " + result.ToString() + " (" + GetType().Name + ")", ToString());
+ bridge?.Multiplexer.Trace("Completed with success: " + result.ToString() + " (" + GetType().Name + ")", ToString());
}
else
{
diff --git a/src/StackExchange.Redis/ServerEndPoint.cs b/src/StackExchange.Redis/ServerEndPoint.cs
index 55fe6cff3..1e32275d6 100644
--- a/src/StackExchange.Redis/ServerEndPoint.cs
+++ b/src/StackExchange.Redis/ServerEndPoint.cs
@@ -708,7 +708,7 @@ internal void OnFullyEstablished(PhysicalConnection connection, string source)
}
catch (Exception ex)
{
- connection.RecordConnectionFailed(ConnectionFailureType.InternalFailure, ex);
+ connection?.RecordConnectionFailed(ConnectionFailureType.InternalFailure, ex);
}
}
diff --git a/src/StackExchange.Redis/StackExchange.Redis.csproj b/src/StackExchange.Redis/StackExchange.Redis.csproj
index 17e34eab9..e1b428a36 100644
--- a/src/StackExchange.Redis/StackExchange.Redis.csproj
+++ b/src/StackExchange.Redis/StackExchange.Redis.csproj
@@ -16,8 +16,9 @@
-
-
+
+
+
diff --git a/src/StackExchange.Redis/TextWriterLogger.cs b/src/StackExchange.Redis/TextWriterLogger.cs
index 0582b70d3..4d8507b95 100644
--- a/src/StackExchange.Redis/TextWriterLogger.cs
+++ b/src/StackExchange.Redis/TextWriterLogger.cs
@@ -17,7 +17,12 @@ public TextWriterLogger(TextWriter writer, ILogger? wrapped)
_wrapped = wrapped;
}
+#if NET8_0_OR_GREATER
+ public IDisposable? BeginScope(TState state) where TState : notnull => NothingDisposable.Instance;
+#else
public IDisposable BeginScope(TState state) => NothingDisposable.Instance;
+#endif
+
public bool IsEnabled(LogLevel logLevel) => _writer is not null || _wrapped is not null;
public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter)
{
diff --git a/tests/StackExchange.Redis.Tests/KeyPrefixedDatabaseTests.cs b/tests/StackExchange.Redis.Tests/KeyPrefixedDatabaseTests.cs
index f467aca24..e73225031 100644
--- a/tests/StackExchange.Redis.Tests/KeyPrefixedDatabaseTests.cs
+++ b/tests/StackExchange.Redis.Tests/KeyPrefixedDatabaseTests.cs
@@ -605,8 +605,8 @@ public void ScriptEvaluate_2()
RedisValue[] values = Array.Empty();
RedisKey[] keys = new RedisKey[] { "a", "b" };
Expression> valid = _ => _.Length == 2 && _[0] == "prefix:a" && _[1] == "prefix:b";
- prefixed.ScriptEvaluate("script", keys, values, CommandFlags.None);
- mock.Received().ScriptEvaluate("script", Arg.Is(valid), values, CommandFlags.None);
+ prefixed.ScriptEvaluate(script: "script", keys: keys, values: values, flags: CommandFlags.None);
+ mock.Received().ScriptEvaluate(script: "script", keys: Arg.Is(valid), values: values, flags: CommandFlags.None);
}
[Fact]
diff --git a/tests/StackExchange.Redis.Tests/KeyPrefixedTests.cs b/tests/StackExchange.Redis.Tests/KeyPrefixedTests.cs
index aebc8fc6d..e48227974 100644
--- a/tests/StackExchange.Redis.Tests/KeyPrefixedTests.cs
+++ b/tests/StackExchange.Redis.Tests/KeyPrefixedTests.cs
@@ -550,7 +550,7 @@ public async Task ScriptEvaluateAsync_2()
RedisKey[] keys = new RedisKey[] { "a", "b" };
Expression> valid = _ => _.Length == 2 && _[0] == "prefix:a" && _[1] == "prefix:b";
await prefixed.ScriptEvaluateAsync("script", keys, values, CommandFlags.None);
- await mock.Received().ScriptEvaluateAsync("script", Arg.Is(valid), values, CommandFlags.None);
+ await mock.Received().ScriptEvaluateAsync(script: "script", keys: Arg.Is(valid), values: values, flags: CommandFlags.None);
}
[Fact]
diff --git a/tests/StackExchange.Redis.Tests/LockingTests.cs b/tests/StackExchange.Redis.Tests/LockingTests.cs
index c2aa3611f..4f9dbd402 100644
--- a/tests/StackExchange.Redis.Tests/LockingTests.cs
+++ b/tests/StackExchange.Redis.Tests/LockingTests.cs
@@ -151,11 +151,11 @@ public async Task TakeLockAndExtend(TestMode testMode)
Assert.Equal(right, await t4);
if (withTran) Assert.False(await t5!, "5");
Assert.Equal(right, await t6);
- var ttl = (await t7).Value.TotalSeconds;
+ var ttl = (await t7)!.Value.TotalSeconds;
Assert.True(ttl > 0 && ttl <= 20, "7");
Assert.True(await t8, "8");
Assert.Equal(right, await t9);
- ttl = (await t10).Value.TotalSeconds;
+ ttl = (await t10)!.Value.TotalSeconds;
Assert.True(ttl > 50 && ttl <= 60, "10");
Assert.True(await t11, "11");
Assert.Null((string?)await t12);
@@ -185,7 +185,7 @@ public async Task TestBasicLockNotTaken(TestMode testMode)
}
Assert.True(await taken!, "taken");
Assert.Equal("new-value", await newValue!);
- var ttlValue = (await ttl!).Value.TotalSeconds;
+ var ttlValue = (await ttl!)!.Value.TotalSeconds;
Assert.True(ttlValue >= 8 && ttlValue <= 10, "ttl");
Assert.Equal(0, errorCount);
@@ -206,7 +206,7 @@ public async Task TestBasicLockTaken(TestMode testMode)
Assert.False(await taken, "taken");
Assert.Equal("old-value", await newValue);
- var ttlValue = (await ttl).Value.TotalSeconds;
+ var ttlValue = (await ttl)!.Value.TotalSeconds;
Assert.True(ttlValue >= 18 && ttlValue <= 20, "ttl");
}
}
diff --git a/tests/StackExchange.Redis.Tests/LoggerTests.cs b/tests/StackExchange.Redis.Tests/LoggerTests.cs
index 217864ba7..75077f9a9 100644
--- a/tests/StackExchange.Redis.Tests/LoggerTests.cs
+++ b/tests/StackExchange.Redis.Tests/LoggerTests.cs
@@ -69,7 +69,11 @@ public class TestWrapperLogger : ILogger
public TestWrapperLogger(ILogger toWrap) => Inner = toWrap;
+#if NET8_0_OR_GREATER
+ public IDisposable? BeginScope(TState state) where TState : notnull => Inner.BeginScope(state);
+#else
public IDisposable BeginScope(TState state) => Inner.BeginScope(state);
+#endif
public bool IsEnabled(LogLevel logLevel) => Inner.IsEnabled(logLevel);
public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter)
{
@@ -86,7 +90,11 @@ private class TestMultiLogger : ILogger
private readonly ILogger[] _loggers;
public TestMultiLogger(params ILogger[] loggers) => _loggers = loggers;
+#if NET8_0_OR_GREATER
+ public IDisposable? BeginScope(TState state) where TState : notnull => throw new NotImplementedException();
+#else
public IDisposable BeginScope(TState state) => throw new NotImplementedException();
+#endif
public bool IsEnabled(LogLevel logLevel) => true;
public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter)
{
@@ -106,7 +114,11 @@ private class TestLogger : ILogger
public TestLogger(LogLevel logLevel, TextWriter output) =>
(_logLevel, _output) = (logLevel, output);
+#if NET8_0_OR_GREATER
+ public IDisposable? BeginScope(TState state) where TState : notnull => throw new NotImplementedException();
+#else
public IDisposable BeginScope(TState state) => throw new NotImplementedException();
+#endif
public bool IsEnabled(LogLevel logLevel) => logLevel >= _logLevel;
public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter)
{
diff --git a/tests/StackExchange.Redis.Tests/RespProtocolTests.cs b/tests/StackExchange.Redis.Tests/RespProtocolTests.cs
index c508bd1c9..44932cf96 100644
--- a/tests/StackExchange.Redis.Tests/RespProtocolTests.cs
+++ b/tests/StackExchange.Redis.Tests/RespProtocolTests.cs
@@ -180,7 +180,7 @@ public async Task CheckLuaResult(string script, RedisProtocol protocol, ResultTy
db.HashSet("key", "b", 2);
db.HashSet("key", "c", 3);
}
- var result = await db.ScriptEvaluateAsync(script, flags: CommandFlags.NoScriptCache);
+ var result = await db.ScriptEvaluateAsync(script: script, flags: CommandFlags.NoScriptCache);
Assert.Equal(resp2, result.Resp2Type);
Assert.Equal(resp3, result.Resp3Type);
diff --git a/tests/StackExchange.Redis.Tests/ScriptingTests.cs b/tests/StackExchange.Redis.Tests/ScriptingTests.cs
index 59bb0e608..f6de8044a 100644
--- a/tests/StackExchange.Redis.Tests/ScriptingTests.cs
+++ b/tests/StackExchange.Redis.Tests/ScriptingTests.cs
@@ -8,6 +8,9 @@
using Xunit;
using Xunit.Abstractions;
+// ReSharper disable UseAwaitUsing # for consistency with existing tests
+// ReSharper disable MethodHasAsyncOverload # grandfathered existing usage
+// ReSharper disable StringLiteralTypo # because of Lua scripts
namespace StackExchange.Redis.Tests;
[RunPerProtocol]
@@ -27,7 +30,7 @@ private IConnectionMultiplexer GetScriptConn(bool allowAdmin = false)
public void ClientScripting()
{
using var conn = GetScriptConn();
- _ = conn.GetDatabase().ScriptEvaluate("return redis.call('info','server')", null, null);
+ _ = conn.GetDatabase().ScriptEvaluate(script: "return redis.call('info','server')", keys: null, values: null);
}
[Fact]
@@ -37,14 +40,14 @@ public async Task BasicScripting()
var db = conn.GetDatabase();
var noCache = db.ScriptEvaluateAsync(
- "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}",
- new RedisKey[] { "key1", "key2" },
- new RedisValue[] { "first", "second" });
+ script: "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}",
+ keys: new RedisKey[] { "key1", "key2" },
+ values: new RedisValue[] { "first", "second" });
var cache = db.ScriptEvaluateAsync(
- "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}",
- new RedisKey[] { "key1", "key2" },
- new RedisValue[] { "first", "second" });
- var results = (string[]?)await noCache;
+ script: "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}",
+ keys: new RedisKey[] { "key1", "key2" },
+ values: new RedisValue[] { "first", "second" });
+ var results = (string[]?)(await noCache)!;
Assert.NotNull(results);
Assert.Equal(4, results.Length);
Assert.Equal("key1", results[0]);
@@ -52,7 +55,7 @@ public async Task BasicScripting()
Assert.Equal("first", results[2]);
Assert.Equal("second", results[3]);
- results = (string[]?)await cache;
+ results = (string[]?)(await cache)!;
Assert.NotNull(results);
Assert.Equal(4, results.Length);
Assert.Equal("key1", results[0]);
@@ -69,16 +72,18 @@ public void KeysScripting()
var db = conn.GetDatabase();
var key = Me();
db.StringSet(key, "bar", flags: CommandFlags.FireAndForget);
- var result = (string?)db.ScriptEvaluate("return redis.call('get', KEYS[1])", new RedisKey[] { key }, null);
+ var result = (string?)db.ScriptEvaluate(script: "return redis.call('get', KEYS[1])", keys: new RedisKey[] { key }, values: null);
Assert.Equal("bar", result);
}
[Fact]
public async Task TestRandomThingFromForum()
{
- const string script = @"local currentVal = tonumber(redis.call('GET', KEYS[1]));
- if (currentVal <= 0 ) then return 1 elseif (currentVal - (tonumber(ARGV[1])) < 0 ) then return 0 end;
- return redis.call('INCRBY', KEYS[1], -tonumber(ARGV[1]));";
+ const string Script = """
+ local currentVal = tonumber(redis.call('GET', KEYS[1]));
+ if (currentVal <= 0 ) then return 1 elseif (currentVal - (tonumber(ARGV[1])) < 0 ) then return 0 end;
+ return redis.call('INCRBY', KEYS[1], -tonumber(ARGV[1]));
+ """;
using var conn = GetScriptConn();
@@ -88,18 +93,18 @@ public async Task TestRandomThingFromForum()
db.StringSet(prefix + "B", "5", flags: CommandFlags.FireAndForget);
db.StringSet(prefix + "C", "10", flags: CommandFlags.FireAndForget);
- var a = db.ScriptEvaluateAsync(script, new RedisKey[] { prefix + "A" }, new RedisValue[] { 6 }).ForAwait();
- var b = db.ScriptEvaluateAsync(script, new RedisKey[] { prefix + "B" }, new RedisValue[] { 6 }).ForAwait();
- var c = db.ScriptEvaluateAsync(script, new RedisKey[] { prefix + "C" }, new RedisValue[] { 6 }).ForAwait();
+ var a = db.ScriptEvaluateAsync(script: Script, keys: new RedisKey[] { prefix + "A" }, values: new RedisValue[] { 6 }).ForAwait();
+ var b = db.ScriptEvaluateAsync(script: Script, keys: new RedisKey[] { prefix + "B" }, values: new RedisValue[] { 6 }).ForAwait();
+ var c = db.ScriptEvaluateAsync(script: Script, keys: new RedisKey[] { prefix + "C" }, values: new RedisValue[] { 6 }).ForAwait();
- var vals = await db.StringGetAsync(new RedisKey[] { prefix + "A", prefix + "B", prefix + "C" }).ForAwait();
+ var values = await db.StringGetAsync(new RedisKey[] { prefix + "A", prefix + "B", prefix + "C" }).ForAwait();
Assert.Equal(1, (long)await a); // exit code when current val is non-positive
Assert.Equal(0, (long)await b); // exit code when result would be negative
Assert.Equal(4, (long)await c); // 10 - 6 = 4
- Assert.Equal("0", vals[0]);
- Assert.Equal("5", vals[1]);
- Assert.Equal("4", vals[2]);
+ Assert.Equal("0", values[0]);
+ Assert.Equal("5", values[1]);
+ Assert.Equal("4", values[2]);
}
[Fact]
@@ -118,9 +123,9 @@ public async Task MultiIncrWithoutReplies()
// run the script, passing "a", "b", "c", "c" to
// increment a & b by 1, c twice
var result = db.ScriptEvaluateAsync(
- "for i,key in ipairs(KEYS) do redis.call('incr', key) end",
- new RedisKey[] { prefix + "a", prefix + "b", prefix + "c", prefix + "c" }, // <== aka "KEYS" in the script
- null).ForAwait(); // <== aka "ARGV" in the script
+ script: "for i,key in ipairs(KEYS) do redis.call('incr', key) end",
+ keys: new RedisKey[] { prefix + "a", prefix + "b", prefix + "c", prefix + "c" }, // <== aka "KEYS" in the script
+ values: null).ForAwait(); // <== aka "ARGV" in the script
// check the incremented values
var a = db.StringGetAsync(prefix + "a").ForAwait();
@@ -151,9 +156,9 @@ public async Task MultiIncrByWithoutReplies()
// run the script, passing "a", "b", "c" and 1,2,3
// increment a & b by 1, c twice
var result = db.ScriptEvaluateAsync(
- "for i,key in ipairs(KEYS) do redis.call('incrby', key, ARGV[i]) end",
- new RedisKey[] { prefix + "a", prefix + "b", prefix + "c" }, // <== aka "KEYS" in the script
- new RedisValue[] { 1, 1, 2 }).ForAwait(); // <== aka "ARGV" in the script
+ script: "for i,key in ipairs(KEYS) do redis.call('incrby', key, ARGV[i]) end",
+ keys: new RedisKey[] { prefix + "a", prefix + "b", prefix + "c" }, // <== aka "KEYS" in the script
+ values: new RedisValue[] { 1, 1, 2 }).ForAwait(); // <== aka "ARGV" in the script
// check the incremented values
var a = db.StringGetAsync(prefix + "a").ForAwait();
@@ -174,7 +179,7 @@ public void DisableStringInference()
var db = conn.GetDatabase();
var key = Me();
db.StringSet(key, "bar", flags: CommandFlags.FireAndForget);
- var result = (byte[]?)db.ScriptEvaluate("return redis.call('get', KEYS[1])", new RedisKey[] { key });
+ var result = (byte[]?)db.ScriptEvaluate(script: "return redis.call('get', KEYS[1])", keys: new RedisKey[] { key });
Assert.NotNull(result);
Assert.Equal("bar", Encoding.UTF8.GetString(result));
}
@@ -188,16 +193,16 @@ public void FlushDetection()
var db = conn.GetDatabase();
var key = Me();
db.StringSet(key, "bar", flags: CommandFlags.FireAndForget);
- var result = (string?)db.ScriptEvaluate("return redis.call('get', KEYS[1])", new RedisKey[] { key }, null);
+ var result = (string?)db.ScriptEvaluate(script: "return redis.call('get', KEYS[1])", keys: new RedisKey[] { key }, values: null);
Assert.Equal("bar", result);
// now cause all kinds of problems
GetServer(conn).ScriptFlush();
// expect this one to fail just work fine (self-fix)
- db.ScriptEvaluate("return redis.call('get', KEYS[1])", new RedisKey[] { key }, null);
+ db.ScriptEvaluate(script: "return redis.call('get', KEYS[1])", keys: new RedisKey[] { key }, values: null);
- result = (string?)db.ScriptEvaluate("return redis.call('get', KEYS[1])", new RedisKey[] { key }, null);
+ result = (string?)db.ScriptEvaluate(script: "return redis.call('get', KEYS[1])", keys: new RedisKey[] { key }, values: null);
Assert.Equal("bar", result);
}
@@ -241,11 +246,11 @@ public void NonAsciiScripts()
{
using var conn = GetScriptConn();
- const string evil = "return '僕'";
+ const string Evil = "return '僕'";
var db = conn.GetDatabase();
- GetServer(conn).ScriptLoad(evil);
+ GetServer(conn).ScriptLoad(Evil);
- var result = (string?)db.ScriptEvaluate(evil, null, null);
+ var result = (string?)db.ScriptEvaluate(script: Evil, keys: null, values: null);
Assert.Equal("僕", result);
}
@@ -258,7 +263,7 @@ await Assert.ThrowsAsync(async () =>
var db = conn.GetDatabase();
try
{
- await db.ScriptEvaluateAsync("return redis.error_reply('oops')", null, null).ForAwait();
+ await db.ScriptEvaluateAsync(script: "return redis.error_reply('oops')", keys: null, values: null).ForAwait();
}
catch (AggregateException ex)
{
@@ -280,7 +285,7 @@ public void ScriptThrowsErrorInsideTransaction()
var tran = db.CreateTransaction();
{
var a = tran.StringIncrementAsync(key);
- var b = tran.ScriptEvaluateAsync("return redis.error_reply('oops')", null, null);
+ var b = tran.ScriptEvaluateAsync(script: "return redis.error_reply('oops')", keys: null, values: null);
var c = tran.StringIncrementAsync(key);
var complete = tran.ExecuteAsync();
@@ -322,10 +327,10 @@ public async Task ChangeDbInScript()
Log("Key: " + key);
var db = conn.GetDatabase(2);
var evalResult = db.ScriptEvaluateAsync(
- @"redis.call('select', 1)
+ script: @"redis.call('select', 1)
return redis.call('get','" + key + "')",
- null,
- null);
+ keys: null,
+ values: null);
var getResult = db.StringGetAsync(key);
Assert.Equal("db 1", (string?)await evalResult);
@@ -345,10 +350,10 @@ public async Task ChangeDbInTranScript()
var db = conn.GetDatabase(2);
var tran = db.CreateTransaction();
var evalResult = tran.ScriptEvaluateAsync(
- @"redis.call('select', 1)
+ script: @"redis.call('select', 1)
return redis.call('get','" + key + "')",
- null,
- null);
+ keys: null,
+ values: null);
var getResult = tran.StringGetAsync(key);
Assert.True(tran.Execute());
@@ -369,16 +374,16 @@ public void TestBasicScripting()
db.HashSet(key, "id", 123, flags: CommandFlags.FireAndForget);
var wasSet = (bool)db.ScriptEvaluate(
- "if redis.call('hexists', KEYS[1], 'UniqueId') then return redis.call('hset', KEYS[1], 'UniqueId', ARGV[1]) else return 0 end",
- new[] { key },
- new[] { newId });
+ script: "if redis.call('hexists', KEYS[1], 'UniqueId') then return redis.call('hset', KEYS[1], 'UniqueId', ARGV[1]) else return 0 end",
+ keys: new[] { key },
+ values: new[] { newId });
Assert.True(wasSet);
wasSet = (bool)db.ScriptEvaluate(
- "if redis.call('hexists', KEYS[1], 'UniqueId') then return redis.call('hset', KEYS[1], 'UniqueId', ARGV[1]) else return 0 end",
- new[] { key },
- new[] { newId });
+ script: "if redis.call('hexists', KEYS[1], 'UniqueId') then return redis.call('hset', KEYS[1], 'UniqueId', ARGV[1]) else return 0 end",
+ keys: new[] { key },
+ values: new[] { newId });
Assert.False(wasSet);
}
@@ -394,16 +399,16 @@ public async Task CheckLoads(bool async)
// the flush to drop the local cache - assume it is a surprise!)
var server = conn0.GetServer(TestConfig.Current.PrimaryServerAndPort);
var db = conn1.GetDatabase();
- const string script = "return 1;";
+ const string Script = "return 1;";
// start empty
server.ScriptFlush();
- Assert.False(server.ScriptExists(script));
+ Assert.False(server.ScriptExists(Script));
// run once, causes to be cached
Assert.True(await EvaluateScript());
- Assert.True(server.ScriptExists(script));
+ Assert.True(server.ScriptExists(Script));
// can run again
Assert.True(await EvaluateScript());
@@ -411,7 +416,7 @@ public async Task CheckLoads(bool async)
// ditch the scripts; should no longer exist
db.Ping();
server.ScriptFlush();
- Assert.False(server.ScriptExists(script));
+ Assert.False(server.ScriptExists(Script));
db.Ping();
// just works; magic
@@ -421,13 +426,13 @@ public async Task CheckLoads(bool async)
Assert.True(await EvaluateScript());
// which will cause it to be cached
- Assert.True(server.ScriptExists(script));
+ Assert.True(server.ScriptExists(Script));
async Task EvaluateScript()
{
return async ?
- (bool)await db!.ScriptEvaluateAsync(script) :
- (bool)db!.ScriptEvaluate(script);
+ (bool)await db.ScriptEvaluateAsync(script: Script) :
+ (bool)db.ScriptEvaluate(script: Script);
}
}
@@ -445,25 +450,25 @@ public void CompareScriptToDirect()
db.Ping(); // k, we're all up to date now; clean db, minimal script cache
// we're using a pipeline here, so send 1000 messages, but for timing: only care about the last
- const int LOOP = 5000;
+ const int Loop = 5000;
RedisKey key = Me();
RedisKey[] keys = new[] { key }; // script takes an array
// run via script
db.KeyDelete(key, CommandFlags.FireAndForget);
var watch = Stopwatch.StartNew();
- for (int i = 1; i < LOOP; i++) // the i=1 is to do all-but-one
+ for (int i = 1; i < Loop; i++) // the i=1 is to do all-but-one
{
- db.ScriptEvaluate(Script, keys, flags: CommandFlags.FireAndForget);
+ db.ScriptEvaluate(script: Script, keys: keys, flags: CommandFlags.FireAndForget);
}
- var scriptResult = db.ScriptEvaluate(Script, keys); // last one we wait for (no F+F)
+ var scriptResult = db.ScriptEvaluate(script: Script, keys: keys); // last one we wait for (no F+F)
watch.Stop();
TimeSpan scriptTime = watch.Elapsed;
// run via raw op
db.KeyDelete(key, CommandFlags.FireAndForget);
watch = Stopwatch.StartNew();
- for (int i = 1; i < LOOP; i++) // the i=1 is to do all-but-one
+ for (int i = 1; i < Loop; i++) // the i=1 is to do all-but-one
{
db.StringIncrement(key, flags: CommandFlags.FireAndForget);
}
@@ -471,8 +476,8 @@ public void CompareScriptToDirect()
watch.Stop();
TimeSpan directTime = watch.Elapsed;
- Assert.Equal(LOOP, (long)scriptResult);
- Assert.Equal(LOOP, directResult);
+ Assert.Equal(Loop, (long)scriptResult);
+ Assert.Equal(Loop, directResult);
Log("script: {0}ms; direct: {1}ms", scriptTime.TotalMilliseconds, directTime.TotalMilliseconds);
}
@@ -486,7 +491,7 @@ public void TestCallByHash()
var server = conn.GetServer(TestConfig.Current.PrimaryServerAndPort);
server.ScriptFlush();
- byte[]? hash = server.ScriptLoad(Script);
+ byte[] hash = server.ScriptLoad(Script);
Assert.NotNull(hash);
var db = conn.GetDatabase();
@@ -497,7 +502,7 @@ public void TestCallByHash()
string hexHash = string.Concat(hash.Select(x => x.ToString("X2")));
Assert.Equal("2BAB3B661081DB58BD2341920E0BA7CF5DC77B25", hexHash);
- db.ScriptEvaluate(hexHash, keys, flags: CommandFlags.FireAndForget);
+ db.ScriptEvaluate(script: hexHash, keys: keys, flags: CommandFlags.FireAndForget);
db.ScriptEvaluate(hash, keys, flags: CommandFlags.FireAndForget);
var count = (int)db.StringGet(keys)[0];
@@ -571,39 +576,39 @@ public void SimpleRawScriptEvaluate()
// Scopes for repeated use
{
- var val = db.ScriptEvaluate(Script, values: new RedisValue[] { "hello" });
+ var val = db.ScriptEvaluate(script: Script, values: new RedisValue[] { "hello" });
Assert.Equal("hello", (string?)val);
}
{
- var val = db.ScriptEvaluate(Script, values: new RedisValue[] { 123 });
+ var val = db.ScriptEvaluate(script: Script, values: new RedisValue[] { 123 });
Assert.Equal(123, (int)val);
}
{
- var val = db.ScriptEvaluate(Script, values: new RedisValue[] { 123L });
+ var val = db.ScriptEvaluate(script: Script, values: new RedisValue[] { 123L });
Assert.Equal(123L, (long)val);
}
{
- var val = db.ScriptEvaluate(Script, values: new RedisValue[] { 1.1 });
+ var val = db.ScriptEvaluate(script: Script, values: new RedisValue[] { 1.1 });
Assert.Equal(1.1, (double)val);
}
{
- var val = db.ScriptEvaluate(Script, values: new RedisValue[] { true });
+ var val = db.ScriptEvaluate(script: Script, values: new RedisValue[] { true });
Assert.True((bool)val);
}
{
- var val = db.ScriptEvaluate(Script, values: new RedisValue[] { new byte[] { 4, 5, 6 } });
+ var val = db.ScriptEvaluate(script: Script, values: new RedisValue[] { new byte[] { 4, 5, 6 } });
var valArray = (byte[]?)val;
Assert.NotNull(valArray);
Assert.True(new byte[] { 4, 5, 6 }.SequenceEqual(valArray));
}
{
- var val = db.ScriptEvaluate(Script, values: new RedisValue[] { new ReadOnlyMemory(new byte[] { 4, 5, 6 }) });
+ var val = db.ScriptEvaluate(script: Script, values: new RedisValue[] { new ReadOnlyMemory(new byte[] { 4, 5, 6 }) });
var valArray = (byte[]?)val;
Assert.NotNull(valArray);
Assert.True(new byte[] { 4, 5, 6 }.SequenceEqual(valArray));
@@ -786,7 +791,7 @@ public void PurgeLuaScriptOnFinalize()
Assert.Equal(0, LuaScript.GetCachedScriptCount());
// This has to be a separate method to guarantee that the created LuaScript objects go out of scope,
- // and are thus available to be GC'd
+ // and are thus available to be garbage collected.
PurgeLuaScriptOnFinalizeImpl(Script);
CollectGarbage();
@@ -797,7 +802,7 @@ public void PurgeLuaScriptOnFinalize()
}
[Fact]
- public void IDatabaseLuaScriptConvenienceMethods()
+ public void DatabaseLuaScriptConvenienceMethods()
{
using var conn = Create(allowAdmin: true, require: RedisFeatures.v2_6_0);
@@ -818,7 +823,7 @@ public void IDatabaseLuaScriptConvenienceMethods()
}
[Fact]
- public void IServerLuaScriptConvenienceMethods()
+ public void ServerLuaScriptConvenienceMethods()
{
using var conn = Create(allowAdmin: true, require: RedisFeatures.v2_6_0);
@@ -978,14 +983,14 @@ public void ScriptWithKeyPrefixViaArrays()
var p = conn.GetDatabase().WithKeyPrefix("prefix/");
- const string script = @"
+ const string Script = @"
local arr = {};
arr[1] = ARGV[1];
arr[2] = KEYS[1];
arr[3] = ARGV[2];
return arr;
";
- var result = (RedisValue[]?)p.ScriptEvaluate(script, new RedisKey[] { "def" }, new RedisValue[] { "abc", 123 });
+ var result = (RedisValue[]?)p.ScriptEvaluate(script: Script, keys: new RedisKey[] { "def" }, values: new RedisValue[] { "abc", 123 });
Assert.NotNull(result);
Assert.Equal("abc", result[0]);
Assert.Equal("prefix/def", result[1]);
@@ -1002,7 +1007,7 @@ public void ScriptWithKeyPrefixCompare()
LuaScript lua = LuaScript.Prepare("return {@k, @s, @v}");
var viaArgs = (RedisValue[]?)p.ScriptEvaluate(lua, args);
- var viaArr = (RedisValue[]?)p.ScriptEvaluate("return {KEYS[1], ARGV[1], ARGV[2]}", new[] { args.k }, new RedisValue[] { args.s, args.v });
+ var viaArr = (RedisValue[]?)p.ScriptEvaluate(script: "return {KEYS[1], ARGV[1], ARGV[2]}", keys: new[] { args.k }, values: new RedisValue[] { args.s, args.v });
Assert.NotNull(viaArr);
Assert.NotNull(viaArgs);
Assert.Equal(string.Join(",", viaArr), string.Join(",", viaArgs));
@@ -1035,10 +1040,10 @@ private static void TestNullArray(RedisResult? value)
Assert.Null((bool[]?)value);
Assert.Null((long[]?)value);
Assert.Null((ulong[]?)value);
- Assert.Null((string[]?)value);
+ Assert.Null((string[]?)value!);
Assert.Null((int[]?)value);
Assert.Null((double[]?)value);
- Assert.Null((byte[][]?)value);
+ Assert.Null((byte[][]?)value!);
Assert.Null((RedisResult[]?)value);
}
@@ -1054,8 +1059,8 @@ public void TestEvalReadonly()
var db = conn.GetDatabase();
string script = "return KEYS[1]";
- RedisKey[] keys = new RedisKey[1] { "key1" };
- RedisValue[] values = new RedisValue[1] { "first" };
+ RedisKey[] keys = { "key1" };
+ RedisValue[] values = { "first" };
var result = db.ScriptEvaluateReadOnly(script, keys, values);
Assert.Equal("key1", result.ToString());
@@ -1068,8 +1073,8 @@ public async Task TestEvalReadonlyAsync()
var db = conn.GetDatabase();
string script = "return KEYS[1]";
- RedisKey[] keys = new RedisKey[1] { "key1" };
- RedisValue[] values = new RedisValue[1] { "first" };
+ RedisKey[] keys = { "key1" };
+ RedisValue[] values = { "first" };
var result = await db.ScriptEvaluateReadOnlyAsync(script, keys, values);
Assert.Equal("key1", result.ToString());
@@ -1081,7 +1086,7 @@ public void TestEvalShaReadOnly()
using var conn = GetScriptConn();
var db = conn.GetDatabase();
db.StringSet("foo", "bar");
- db.ScriptEvaluate("return redis.call('get','foo')");
+ db.ScriptEvaluate(script: "return redis.call('get','foo')");
// Create a SHA1 hash of the script: 6b1bf486c81ceb7edf3c093f4c48582e38c0e791
SHA1 sha1Hash = SHA1.Create();
@@ -1097,7 +1102,7 @@ public async Task TestEvalShaReadOnlyAsync()
using var conn = GetScriptConn();
var db = conn.GetDatabase();
db.StringSet("foo", "bar");
- db.ScriptEvaluate("return redis.call('get','foo')");
+ db.ScriptEvaluate(script: "return redis.call('get','foo')");
// Create a SHA1 hash of the script: 6b1bf486c81ceb7edf3c093f4c48582e38c0e791
SHA1 sha1Hash = SHA1.Create();
diff --git a/tests/StackExchange.Redis.Tests/SortedSetTests.cs b/tests/StackExchange.Redis.Tests/SortedSetTests.cs
index 9bcd02e2e..7ba86fcf6 100644
--- a/tests/StackExchange.Redis.Tests/SortedSetTests.cs
+++ b/tests/StackExchange.Redis.Tests/SortedSetTests.cs
@@ -338,7 +338,7 @@ public void SortedSetRangeViaScript()
db.KeyDelete(key, CommandFlags.FireAndForget);
db.SortedSetAdd(key, entries, CommandFlags.FireAndForget);
- var result = db.ScriptEvaluate("return redis.call('ZRANGE', KEYS[1], 0, -1, 'WITHSCORES')", new RedisKey[] { key });
+ var result = db.ScriptEvaluate(script: "return redis.call('ZRANGE', KEYS[1], 0, -1, 'WITHSCORES')", keys: new RedisKey[] { key });
AssertFlatArrayEntries(result);
}