Skip to content

Commit

Permalink
PrepareScript should work for parameterless scripts; fix #2164 (#2166)
Browse files Browse the repository at this point in the history
* PrepareScript should work for parameterless scripts; fix #2164

* update link in release notes

* tyop
  • Loading branch information
mgravell authored Jun 21, 2022
1 parent 5f1630e commit bc0c5a2
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 11 deletions.
4 changes: 4 additions & 0 deletions docs/ReleaseNotes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Release Notes

## Pending

- Fix: [#2164](https://github.com/StackExchange/StackExchange.Redis/issues/2164): fix `LuaScript.Prepare` for scripts that don't have parameters ([#2166 by MarcGravell](https://github.com/StackExchange/StackExchange.Redis/pull/2166))

## 2.6.45

- Adds: [Nullable reference type](https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references) annotations ([#2041 by NickCraver](https://github.com/StackExchange/StackExchange.Redis/pull/2041))
Expand Down
17 changes: 6 additions & 11 deletions src/StackExchange.Redis/ScriptParameterMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,12 @@ public ScriptParameters(RedisKey[] keys, RedisValue[] args)

private static readonly Regex ParameterExtractor = new Regex(@"@(?<paramName> ([a-z]|_) ([a-z]|_|\d)*)", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);

private static bool TryExtractParameters(string script, [NotNullWhen(true)] out string[]? parameters)
private static string[] ExtractParameters(string script)
{
var ps = ParameterExtractor.Matches(script);
if (ps.Count == 0)
{
parameters = null;
return false;
return Array.Empty<string>();
}

var ret = new HashSet<string>();
Expand All @@ -56,8 +55,7 @@ private static bool TryExtractParameters(string script, [NotNullWhen(true)] out
if (!ret.Contains(n)) ret.Add(n);
}

parameters = ret.ToArray();
return true;
return ret.ToArray();
}

private static string MakeOrdinalScriptWithoutKeys(string rawScript, string[] args)
Expand Down Expand Up @@ -137,12 +135,9 @@ static ScriptParameterMapper()
/// <param name="script">The script to prepare.</param>
public static LuaScript PrepareScript(string script)
{
if (TryExtractParameters(script, out var ps))
{
var ordinalScript = MakeOrdinalScriptWithoutKeys(script, ps);
return new LuaScript(script, ordinalScript, ps);
}
throw new ArgumentException("Count not parse script: " + script);
var ps = ExtractParameters(script);
var ordinalScript = MakeOrdinalScriptWithoutKeys(script, ps);
return new LuaScript(script, ordinalScript, ps);
}

private static readonly HashSet<Type> ConvertableTypes = new()
Expand Down
55 changes: 55 additions & 0 deletions tests/StackExchange.Redis.Tests/Issues/Issue2164.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
namespace StackExchange.Redis.Tests.Issues
{
public class Issue2164
{
[Fact]
public void LoadSimpleScript()
{
LuaScript.Prepare("return 42");
}
[Fact]
public void LoadComplexScript()
{
LuaScript.Prepare(@"
-------------------------------------------------------------------------------
-- API definitions
-------------------------------------------------------------------------------
local MessageStoreAPI = {}
MessageStoreAPI.confirmPendingDelivery = function(smscMessageId, smscDeliveredAt, smscMessageState)
local messageId = redis.call('hget', ""smId:"" .. smscMessageId, 'mId')
if not messageId then
return nil
end
-- delete pending delivery
redis.call('del', ""smId:"" .. smscMessageId)
local mIdK = 'm:'..messageId
local result = redis.call('hsetnx', mIdK, 'sState', smscMessageState)
if result == 1 then
redis.call('hset', mIdK, 'sDlvAt', smscDeliveredAt)
redis.call('zrem', ""msg.validUntil"", messageId)
return redis.call('hget', mIdK, 'payload')
else
return nil
end
end
-------------------------------------------------------------------------------
-- Function lookup
-------------------------------------------------------------------------------
-- None of the function calls accept keys
if #KEYS > 0 then error('No Keys should be provided') end
-- The first argument must be the function that we intend to call, and it must
-- exist
local command_name = assert(table.remove(ARGV, 1), 'Must provide a command as first argument')
local command = assert(MessageStoreAPI[command_name], 'Unknown command ' .. command_name)
return command(unpack(ARGV))");
}
}
}

0 comments on commit bc0c5a2

Please sign in to comment.