Commit 234ff979 authored by Marc Gravell's avatar Marc Gravell

fix #535 - implement Execute/ExecuteAsync on IServer

parent 6e9f3db6
using System.Linq;
using System.Threading.Tasks;
using Xunit;
using Xunit.Abstractions;
namespace StackExchange.Redis.Tests
{
public class ExecuteTests : TestBase
{
public ExecuteTests(ITestOutputHelper output) : base(output) { }
[Fact]
public async Task DBExecute()
{
using (var conn = Create())
{
var db = conn.GetDatabase(4);
RedisKey key = Me();
db.StringSet(key, "some value");
var actual = (string)db.Execute("GET", key);
Assert.Equal("some value", actual);
actual = (string)await db.ExecuteAsync("GET", key);
Assert.Equal("some value", actual);
}
}
[Fact]
public async Task ServerExecute()
{
using (var conn = Create())
{
var server = conn.GetServer(conn.GetEndPoints().First());
var actual = (string)server.Execute("echo", "some value");
Assert.Equal("some value", actual);
actual = (string)await server.ExecuteAsync("echo", "some value");
Assert.Equal("some value", actual);
}
}
}
}
......@@ -795,6 +795,7 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// </summary>
/// <param name="command">The command to run.</param>
/// <param name="args">The arguments to pass for the command.</param>
/// <remarks>This API should be considered an advanced feature; inappropriate use can be harmful</remarks>
/// <returns>A dynamic representation of the command's result</returns>
RedisResult Execute(string command, params object[] args);
......@@ -806,6 +807,7 @@ public interface IDatabase : IRedis, IDatabaseAsync
/// <param name="command">The command to run.</param>
/// <param name="args">The arguments to pass for the command.</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <remarks>This API should be considered an advanced feature; inappropriate use can be harmful</remarks>
/// <returns>A dynamic representation of the command's result</returns>
RedisResult Execute(string command, ICollection<object> args, CommandFlags flags = CommandFlags.None);
......
......@@ -758,6 +758,7 @@ public interface IDatabaseAsync : IRedisAsync
/// </summary>
/// <param name="command">The command to run.</param>
/// <param name="args">The arguments to pass for the command.</param>
/// <remarks>This API should be considered an advanced feature; inappropriate use can be harmful</remarks>
/// <returns>A dynamic representation of the command's result</returns>
Task<RedisResult> ExecuteAsync(string command, params object[] args);
......@@ -769,6 +770,7 @@ public interface IDatabaseAsync : IRedisAsync
/// <param name="command">The command to run.</param>
/// <param name="args">The arguments to pass for the command.</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <remarks>This API should be considered an advanced feature; inappropriate use can be harmful</remarks>
/// <returns>A dynamic representation of the command's result</returns>
Task<RedisResult> ExecuteAsync(string command, ICollection<object> args, CommandFlags flags = CommandFlags.None);
......
......@@ -230,6 +230,52 @@ public partial interface IServer : IRedis
/// <remarks>https://redis.io/commands/echo</remarks>
Task<RedisValue> EchoAsync(RedisValue message, CommandFlags flags = CommandFlags.None);
/// <summary>
/// Execute an arbitrary command against the server; this is primarily intended for
/// executing modules, but may also be used to provide access to new features that lack
/// a direct API.
/// </summary>
/// <param name="command">The command to run.</param>
/// <param name="args">The arguments to pass for the command.</param>
/// <remarks>This API should be considered an advanced feature; inappropriate use can be harmful</remarks>
/// <returns>A dynamic representation of the command's result</returns>
RedisResult Execute(string command, params object[] args);
/// <summary>
/// Execute an arbitrary command against the server; this is primarily intended for
/// executing modules, but may also be used to provide access to new features that lack
/// a direct API.
/// </summary>
/// <param name="command">The command to run.</param>
/// <param name="args">The arguments to pass for the command.</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <remarks>This API should be considered an advanced feature; inappropriate use can be harmful</remarks>
/// <returns>A dynamic representation of the command's result</returns>
RedisResult Execute(string command, ICollection<object> args, CommandFlags flags = CommandFlags.None);
/// <summary>
/// Execute an arbitrary command against the server; this is primarily intended for
/// executing modules, but may also be used to provide access to new features that lack
/// a direct API.
/// </summary>
/// <param name="command">The command to run.</param>
/// <param name="args">The arguments to pass for the command.</param>
/// <remarks>This API should be considered an advanced feature; inappropriate use can be harmful</remarks>
/// <returns>A dynamic representation of the command's result</returns>
Task<RedisResult> ExecuteAsync(string command, params object[] args);
/// <summary>
/// Execute an arbitrary command against the server; this is primarily intended for
/// executing modules, but may also be used to provide access to new features that lack
/// a direct API.
/// </summary>
/// <param name="command">The command to run.</param>
/// <param name="args">The arguments to pass for the command.</param>
/// <param name="flags">The flags to use for this operation.</param>
/// <remarks>This API should be considered an advanced feature; inappropriate use can be harmful</remarks>
/// <returns>A dynamic representation of the command's result</returns>
Task<RedisResult> ExecuteAsync(string command, ICollection<object> args, CommandFlags flags = CommandFlags.None);
/// <summary>
/// Delete all the keys of all databases on the server.
/// </summary>
......
......@@ -85,7 +85,11 @@ internal abstract class Message : ICompletable
protected Message(int db, CommandFlags flags, RedisCommand command)
{
bool dbNeeded = RequiresDatabase(command);
if (db < 0)
if (command == RedisCommand.UNKNOWN)
{
// all bets are off here
}
else if (db < 0)
{
if (dbNeeded)
{
......
......@@ -3207,7 +3207,7 @@ protected override bool SetResultCore(PhysicalConnection connection, Message mes
}
}
private sealed class ExecuteMessage : Message
internal sealed class ExecuteMessage : Message
{
private readonly string _command;
private readonly ICollection<object> args;
......
......@@ -824,6 +824,22 @@ public Task SentinelFailoverAsync(string serviceName, CommandFlags flags = Comma
return ExecuteAsync(msg, ResultProcessor.SentinelArrayOfArrays);
}
public RedisResult Execute(string command, params object[] args) => Execute(command, args, CommandFlags.None);
public RedisResult Execute(string command, ICollection<object> args, CommandFlags flags = CommandFlags.None)
{
var msg = new RedisDatabase.ExecuteMessage(-1, flags, command, args);
return ExecuteSync(msg, ResultProcessor.ScriptResult);
}
public Task<RedisResult> ExecuteAsync(string command, params object[] args) => ExecuteAsync(command, args, CommandFlags.None);
public Task<RedisResult> ExecuteAsync(string command, ICollection<object> args, CommandFlags flags = CommandFlags.None)
{
var msg = new RedisDatabase.ExecuteMessage(-1, flags, command, args);
return ExecuteAsync(msg, ResultProcessor.ScriptResult);
}
#endregion
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment