Skip to content

Commit

Permalink
new "NoScriptCache" command-flag; fix #617
Browse files Browse the repository at this point in the history
  • Loading branch information
mgravell committed May 8, 2017
1 parent aa198df commit 86b9834
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 93 deletions.
102 changes: 12 additions & 90 deletions BasicTest/Program.cs
Original file line number Diff line number Diff line change
@@ -1,113 +1,35 @@
using System;
using System.Diagnostics;
using StackExchange.Redis;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using StackExchange.Redis;
using System.IO;
using System;

[assembly: AssemblyVersion("1.0.0")]

namespace BasicTest
{
static class YourPreferredSerializer
{
public static T Deserialize<T>(Stream s) { return default(T); }
}
static class Program
{
public static RedisValue JsonGet(this IDatabase db, RedisKey key,
string path = ".", CommandFlags flags = CommandFlags.None)
{
return (RedisValue)db.Execute("JSON.GET",
new object[] { key, path }, flags);
}

public static T JsonGet<T>(this IDatabase db, RedisKey key,
string path = ".", CommandFlags flags = CommandFlags.None)
{
byte[] bytes = (byte[])db.Execute("JSON.GET",
new object[] { key, path }, flags);
using (var ms = new MemoryStream(bytes))
{
return YourPreferredSerializer.Deserialize<T>(ms);
}
}
static void Main(string[] args)
static void Main()
{
using (var conn = ConnectionMultiplexer.Connect("127.0.0.1:6379"))
{
var db = conn.GetDatabase();

// needs explicit RedisKey type for key-based
// sharding to work; will still work with strings,
// but no key-based sharding support
RedisKey key = "some_key";
RedisKey key = Me();
db.KeyDelete(key);
db.StringSet(key, "abc");

// note: if command renames are configured in
// the API, they will still work automatically
db.Execute("del", key);
db.Execute("set", key, "12");
db.Execute("incrby", key, 4);
int i = (int)db.Execute("get", key);
string s = (string)db.ScriptEvaluate(@"
local val = redis.call('get', KEYS[1])
redis.call('del', KEYS[1])
return val", new RedisKey[] { key }, flags: CommandFlags.NoScriptCache);

Console.WriteLine(i); // 16;
Console.WriteLine(s);
Console.WriteLine(db.KeyExists(key));

}



//int AsyncOpsQty = 500000;
//if(args.Length == 1)
//{
// int tmp;
// if(int.TryParse(args[0], out tmp))
// AsyncOpsQty = tmp;
//}
//MassiveBulkOpsAsync(AsyncOpsQty, true, true);
//MassiveBulkOpsAsync(AsyncOpsQty, true, false);
//MassiveBulkOpsAsync(AsyncOpsQty, false, true);
//MassiveBulkOpsAsync(AsyncOpsQty, false, false);
}
static void MassiveBulkOpsAsync(int AsyncOpsQty, bool preserveOrder, bool withContinuation)
{
using (var muxer = ConnectionMultiplexer.Connect("localhost,resolvedns=1"))
{
muxer.PreserveAsyncOrder = preserveOrder;
RedisKey key = "MBOA";
var conn = muxer.GetDatabase();
muxer.Wait(conn.PingAsync());

#if CORE_CLR
int number = 0;
#endif
Action<Task> nonTrivial = delegate
{
#if !CORE_CLR
Thread.SpinWait(5);
#else
for (int i = 0; i < 50; i++)
{
number++;
}
#endif
};
var watch = Stopwatch.StartNew();
for (int i = 0; i <= AsyncOpsQty; i++)
{
var t = conn.StringSetAsync(key, i);
if (withContinuation) t.ContinueWith(nonTrivial);
}
int val = (int)muxer.Wait(conn.StringGetAsync(key));
watch.Stop();

Console.WriteLine("After {0}: {1}", AsyncOpsQty, val);
Console.WriteLine("({3}, {4})\r\n{2}: Time for {0} ops: {1}ms; ops/s: {5}", AsyncOpsQty, watch.ElapsedMilliseconds, Me(),
withContinuation ? "with continuation" : "no continuation", preserveOrder ? "preserve order" : "any order",
AsyncOpsQty / watch.Elapsed.TotalSeconds);
}
}
internal static string Me([CallerMemberName] string caller = null)
{
return caller;
Expand Down
7 changes: 6 additions & 1 deletion StackExchange.Redis/StackExchange/Redis/CommandFlags.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ public enum CommandFlags

// 128: used for "internal call"; never user-specified, so not visible on the public API

// 256: used for "retry"; never user-specified, so not visible on the public API
// 256: used for "script unavailable"; never user-specified, so not visible on the public API

/// <summary>
/// Indicates that script-related operations should use EVAL, not SCRIPT LOAD + EVALSHA
/// </summary>
NoScriptCache = 512,
}
}
2 changes: 1 addition & 1 deletion StackExchange.Redis/StackExchange/Redis/Message.cs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ abstract class Message : ICompletable
private const CommandFlags UserSelectableFlags
= CommandFlags.None | CommandFlags.DemandMaster | CommandFlags.DemandSlave
| CommandFlags.PreferMaster | CommandFlags.PreferSlave
| CommandFlags.HighPriority | CommandFlags.FireAndForget | CommandFlags.NoRedirect;
| CommandFlags.HighPriority | CommandFlags.FireAndForget | CommandFlags.NoRedirect | CommandFlags.NoScriptCache;

private CommandFlags flags;
internal CommandFlags FlagsRaw { get { return flags; } set { flags = value; } }
Expand Down
4 changes: 3 additions & 1 deletion StackExchange.Redis/StackExchange/Redis/RedisDatabase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2530,8 +2530,10 @@ public override int GetHashSlot(ServerSelectionStrategy serverSelectionStrategy)

public IEnumerable<Message> GetMessages(PhysicalConnection connection)
{
if (script != null && connection.Multiplexer.CommandMap.IsAvailable(RedisCommand.SCRIPT)) // a script was provided (rather than a hash); check it is known and supported
if (script != null && connection.Multiplexer.CommandMap.IsAvailable(RedisCommand.SCRIPT)
&& (Flags & CommandFlags.NoScriptCache) == 0)
{
// a script was provided (rather than a hash); check it is known and supported
asciiHash = connection.Bridge.ServerEndPoint.GetScriptHash(script, command);

if (asciiHash == null)
Expand Down

0 comments on commit 86b9834

Please sign in to comment.