Skip to content

Commit

Permalink
EVAL_RO & EVALSHA_RO commands (#2168)
Browse files Browse the repository at this point in the history
Adds: Support for `EVAL_RO` and `EVALSHA_RO` via `IDatabase.ScriptEvaluateReadOnly`/`IDatabase.ScriptEvaluateReadOnlyAsync`

Co-authored-by: Nick Craver <nrcraver@gmail.com>
  • Loading branch information
shacharPash and NickCraver authored Jan 4, 2023
1 parent b04761e commit b1fddf3
Show file tree
Hide file tree
Showing 9 changed files with 210 additions and 38 deletions.
1 change: 1 addition & 0 deletions docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Current package versions:

## Unreleased

- Adds: Support for `EVAL_RO` and `EVALSHA_RO` via `IDatabase.ScriptEvaluateReadOnly`/`IDatabase.ScriptEvaluateReadOnlyAsync` ([#2168 by shacharPash](https://github.com/StackExchange/StackExchange.Redis/pull/2168))
- Fix [#1458](https://github.com/StackExchange/StackExchange.Redis/issues/1458): Fixes a leak condition when a connection completes on the TCP phase but not the Redis handshake ([#2238 by NickCraver](https://github.com/StackExchange/StackExchange.Redis/pull/2238))
- Internal: ServerSnapshot: Improve API and allow filtering with custom struct enumerator ([#2337 by mgravell](https://github.com/StackExchange/StackExchange.Redis/pull/2337))

Expand Down
4 changes: 4 additions & 0 deletions src/StackExchange.Redis/Enums/RedisCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ internal enum RedisCommand
ECHO,
EVAL,
EVALSHA,
EVAL_RO,
EVALSHA_RO,
EXEC,
EXISTS,
EXPIRE,
Expand Down Expand Up @@ -361,6 +363,8 @@ internal static bool IsPrimaryOnly(this RedisCommand command)
case RedisCommand.ECHO:
case RedisCommand.EVAL:
case RedisCommand.EVALSHA:
case RedisCommand.EVAL_RO:
case RedisCommand.EVALSHA_RO:
case RedisCommand.EXEC:
case RedisCommand.EXISTS:
case RedisCommand.GEODIST:
Expand Down
25 changes: 25 additions & 0 deletions src/StackExchange.Redis/Interfaces/IDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1302,6 +1302,31 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// <remarks><seealso href="https://redis.io/commands/eval"/></remarks>
RedisResult ScriptEvaluate(LoadedLuaScript script, object? parameters = null, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Read-only variant of the EVAL command that cannot execute commands that modify data, Execute a Lua script against the server.
/// </summary>
/// <param name="script">The script to execute.</param>
/// <param name="keys">The keys to execute against.</param>
/// <param name="values">The values to execute against.</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>A dynamic representation of the script's result.</returns>
/// <remarks>
/// <seealso href="https://redis.io/commands/eval_ro"/>,
/// <seealso href="https://redis.io/commands/evalsha_ro"/>
/// </remarks>
RedisResult ScriptEvaluateReadOnly(string script, RedisKey[]? keys = null, RedisValue[]? values = null, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Read-only variant of the EVALSHA command that cannot execute commands that modify data, Execute a Lua script against the server using just the SHA1 hash.
/// </summary>
/// <param name="hash">The hash of the script to execute.</param>
/// <param name="keys">The keys to execute against.</param>
/// <param name="values">The values to execute against.</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>A dynamic representation of the script's result.</returns>
/// <remarks><seealso href="https://redis.io/commands/evalsha_ro"/></remarks>
RedisResult ScriptEvaluateReadOnly(byte[] hash, RedisKey[]? keys = null, RedisValue[]? values = null, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Add the specified member to the set stored at key.
/// Specified members that are already a member of this set are ignored.
Expand Down
25 changes: 25 additions & 0 deletions src/StackExchange.Redis/Interfaces/IDatabaseAsync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1278,6 +1278,31 @@ public interface IDatabaseAsync : IRedisAsync
/// <remarks><seealso href="https://redis.io/commands/eval"/></remarks>
Task<RedisResult> ScriptEvaluateAsync(LoadedLuaScript script, object? parameters = null, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Read-only variant of the EVAL command that cannot execute commands that modify data, Execute a Lua script against the server.
/// </summary>
/// <param name="script">The script to execute.</param>
/// <param name="keys">The keys to execute against.</param>
/// <param name="values">The values to execute against.</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>A dynamic representation of the script's result.</returns>
/// <remarks>
/// <seealso href="https://redis.io/commands/eval_ro"/>,
/// <seealso href="https://redis.io/commands/evalsha_ro"/>
/// </remarks>
Task<RedisResult> ScriptEvaluateReadOnlyAsync(string script, RedisKey[]? keys = null, RedisValue[]? values = null, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Read-only variant of the EVALSHA command that cannot execute commands that modify data, Execute a Lua script against the server using just the SHA1 hash.
/// </summary>
/// <param name="hash">The hash of the script to execute.</param>
/// <param name="keys">The keys to execute against.</param>
/// <param name="values">The values to execute against.</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <returns>A dynamic representation of the script's result.</returns>
/// <remarks><seealso href="https://redis.io/commands/evalsha_ro"/></remarks>
Task<RedisResult> ScriptEvaluateReadOnlyAsync(byte[] hash, RedisKey[]? keys = null, RedisValue[]? values = null, CommandFlags flags = CommandFlags.None);

/// <summary>
/// Add the specified member to the set stored at key.
/// Specified members that are already a member of this set are ignored.
Expand Down
8 changes: 8 additions & 0 deletions src/StackExchange.Redis/KeyspaceIsolation/KeyPrefixed.cs
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,14 @@ public Task<RedisResult> ScriptEvaluateAsync(LoadedLuaScript script, object? par
// TODO: The return value could contain prefixed keys. It might make sense to 'unprefix' those?
script.EvaluateAsync(Inner, parameters, Prefix, flags);

public Task<RedisResult> ScriptEvaluateReadOnlyAsync(byte[] hash, 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(hash, ToInner(keys), values, flags);

public Task<RedisResult> 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);

public Task<long> SetAddAsync(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None) =>
Inner.SetAddAsync(ToInner(key), values, flags);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,14 @@ public RedisResult ScriptEvaluate(LoadedLuaScript script, object? parameters = n
// TODO: The return value could contain prefixed keys. It might make sense to 'unprefix' those?
script.Evaluate(Inner, parameters, Prefix, flags);

public RedisResult ScriptEvaluateReadOnly(byte[] hash, 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.ScriptEvaluateReadOnly(hash, ToInner(keys), values, flags);

public RedisResult ScriptEvaluateReadOnly(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.ScriptEvaluateReadOnly(script, ToInner(keys), values, flags);

public long SetAdd(RedisKey key, RedisValue[] values, CommandFlags flags = CommandFlags.None) =>
Inner.SetAdd(ToInner(key), values, flags);

Expand Down
4 changes: 4 additions & 0 deletions src/StackExchange.Redis/PublicAPI/PublicAPI.Shipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,8 @@ StackExchange.Redis.IDatabase.ScriptEvaluate(byte[]! hash, StackExchange.Redis.R
StackExchange.Redis.IDatabase.ScriptEvaluate(StackExchange.Redis.LoadedLuaScript! script, object? parameters = null, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> StackExchange.Redis.RedisResult!
StackExchange.Redis.IDatabase.ScriptEvaluate(StackExchange.Redis.LuaScript! script, object? parameters = null, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> StackExchange.Redis.RedisResult!
StackExchange.Redis.IDatabase.ScriptEvaluate(string! script, StackExchange.Redis.RedisKey[]? keys = null, StackExchange.Redis.RedisValue[]? values = null, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> StackExchange.Redis.RedisResult!
StackExchange.Redis.IDatabase.ScriptEvaluateReadOnly(byte[]! hash, StackExchange.Redis.RedisKey[]? keys = null, StackExchange.Redis.RedisValue[]? values = null, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> StackExchange.Redis.RedisResult!
StackExchange.Redis.IDatabase.ScriptEvaluateReadOnly(string! script, StackExchange.Redis.RedisKey[]? keys = null, StackExchange.Redis.RedisValue[]? values = null, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> StackExchange.Redis.RedisResult!
StackExchange.Redis.IDatabase.SetAdd(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue value, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> bool
StackExchange.Redis.IDatabase.SetAdd(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! values, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> long
StackExchange.Redis.IDatabase.SetCombine(StackExchange.Redis.SetOperation operation, StackExchange.Redis.RedisKey first, StackExchange.Redis.RedisKey second, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> StackExchange.Redis.RedisValue[]!
Expand Down Expand Up @@ -838,6 +840,8 @@ StackExchange.Redis.IDatabaseAsync.ScriptEvaluateAsync(byte[]! hash, StackExchan
StackExchange.Redis.IDatabaseAsync.ScriptEvaluateAsync(StackExchange.Redis.LoadedLuaScript! script, object? parameters = null, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<StackExchange.Redis.RedisResult!>!
StackExchange.Redis.IDatabaseAsync.ScriptEvaluateAsync(StackExchange.Redis.LuaScript! script, object? parameters = null, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<StackExchange.Redis.RedisResult!>!
StackExchange.Redis.IDatabaseAsync.ScriptEvaluateAsync(string! script, StackExchange.Redis.RedisKey[]? keys = null, StackExchange.Redis.RedisValue[]? values = null, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<StackExchange.Redis.RedisResult!>!
StackExchange.Redis.IDatabaseAsync.ScriptEvaluateReadOnlyAsync(byte[]! hash, StackExchange.Redis.RedisKey[]? keys = null, StackExchange.Redis.RedisValue[]? values = null, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<StackExchange.Redis.RedisResult!>!
StackExchange.Redis.IDatabaseAsync.ScriptEvaluateReadOnlyAsync(string! script, StackExchange.Redis.RedisKey[]? keys = null, StackExchange.Redis.RedisValue[]? values = null, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<StackExchange.Redis.RedisResult!>!
StackExchange.Redis.IDatabaseAsync.SetAddAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue value, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<bool>!
StackExchange.Redis.IDatabaseAsync.SetAddAsync(StackExchange.Redis.RedisKey key, StackExchange.Redis.RedisValue[]! values, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<long>!
StackExchange.Redis.IDatabaseAsync.SetCombineAndStoreAsync(StackExchange.Redis.SetOperation operation, StackExchange.Redis.RedisKey destination, StackExchange.Redis.RedisKey first, StackExchange.Redis.RedisKey second, StackExchange.Redis.CommandFlags flags = StackExchange.Redis.CommandFlags.None) -> System.Threading.Tasks.Task<long>!
Expand Down
Loading

0 comments on commit b1fddf3

Please sign in to comment.