Skip to content

Commit 8ed38d5

Browse files
committed
Condition
1 parent 7705432 commit 8ed38d5

File tree

3 files changed

+516
-84
lines changed

3 files changed

+516
-84
lines changed

src/StackExchange.Redis/Condition.cs

Lines changed: 90 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using RESPite.Messages;
34

45
namespace StackExchange.Redis
56
{
@@ -372,7 +373,8 @@ public static Condition StringNotEqual(RedisKey key, RedisValue value)
372373
internal abstract IEnumerable<Message> CreateMessages(int db, IResultBox? resultBox);
373374

374375
internal abstract int GetHashSlot(ServerSelectionStrategy serverSelectionStrategy);
375-
internal abstract bool TryValidate(in RawResult result, out bool value);
376+
377+
internal abstract bool TryValidate(ref RespReader reader, out bool value);
376378

377379
internal sealed class ConditionProcessor : ResultProcessor<bool>
378380
{
@@ -387,13 +389,12 @@ public static Message CreateMessage(Condition condition, int db, CommandFlags fl
387389
public static Message CreateMessage(Condition condition, int db, CommandFlags flags, RedisCommand command, in RedisKey key, in RedisValue value, in RedisValue value1, in RedisValue value2, in RedisValue value3, in RedisValue value4) =>
388390
new ConditionMessage(condition, db, flags, command, key, value, value1, value2, value3, value4);
389391

390-
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0071:Simplify interpolation", Justification = "Allocations (string.Concat vs. string.Format)")]
391-
protected override bool SetResultCore(PhysicalConnection connection, Message message, RawResult result)
392+
protected override bool SetResultCore(PhysicalConnection connection, Message message, ref RespReader reader)
392393
{
393-
connection?.BridgeCouldBeNull?.Multiplexer?.OnTransactionLog($"condition '{message.CommandAndKey}' got '{result.ToString()}'");
394+
connection?.BridgeCouldBeNull?.Multiplexer?.OnTransactionLog($"condition '{message.CommandAndKey}' got '{reader.GetOverview()}'");
394395
var msg = message as ConditionMessage;
395396
var condition = msg?.Condition;
396-
if (condition != null && condition.TryValidate(result, out bool final))
397+
if (condition != null && condition.TryValidate(ref reader, out bool final))
397398
{
398399
SetResult(message, final);
399400
return true;
@@ -510,19 +511,20 @@ internal override IEnumerable<Message> CreateMessages(int db, IResultBox? result
510511

511512
internal override int GetHashSlot(ServerSelectionStrategy serverSelectionStrategy) => serverSelectionStrategy.HashSlot(key);
512513

513-
internal override bool TryValidate(in RawResult result, out bool value)
514+
internal override bool TryValidate(ref RespReader reader, out bool value)
514515
{
515516
switch (type)
516517
{
517518
case RedisType.SortedSet:
518-
var parsedValue = result.AsRedisValue();
519-
value = parsedValue.IsNull != expectedResult;
520-
ConnectionMultiplexer.TraceWithoutContext("exists: " + parsedValue + "; expected: " + expectedResult + "; voting: " + value);
519+
// ZSCORE returns bulk string (score) or null
520+
var parsedValue = reader.IsNull;
521+
value = parsedValue != expectedResult;
522+
ConnectionMultiplexer.TraceWithoutContext("exists: " + !parsedValue + "; expected: " + expectedResult + "; voting: " + value);
521523
return true;
522524

523525
default:
524-
bool parsed;
525-
if (ResultProcessor.DemandZeroOrOneProcessor.TryGet(result, out parsed))
526+
// EXISTS, HEXISTS, SISMEMBER return integer 0 or 1
527+
if (ResultProcessor.DemandZeroOrOneProcessor.TryGet(ref reader, out bool parsed))
526528
{
527529
value = parsed == expectedResult;
528530
ConnectionMultiplexer.TraceWithoutContext("exists: " + parsed + "; expected: " + expectedResult + "; voting: " + value);
@@ -586,12 +588,30 @@ internal override IEnumerable<Message> CreateMessages(int db, IResultBox? result
586588

587589
internal override int GetHashSlot(ServerSelectionStrategy serverSelectionStrategy) => serverSelectionStrategy.HashSlot(key);
588590

589-
internal override bool TryValidate(in RawResult result, out bool value)
591+
internal override bool TryValidate(ref RespReader reader, out bool value)
590592
{
591-
value = result.ItemsCount == 1 && result[0].AsRedisValue().StartsWith(prefix);
592-
593-
if (!expectedResult) value = !value;
594-
return true;
593+
// ZRANGEBYLEX returns an array with 0 or 1 elements
594+
if (reader.IsAggregate)
595+
{
596+
var count = reader.AggregateLength();
597+
if (count == 1)
598+
{
599+
// Check if the first element starts with prefix
600+
if (reader.TryMoveNext() && reader.IsScalar)
601+
{
602+
value = reader.ReadRedisValue().StartsWith(prefix);
603+
if (!expectedResult) value = !value;
604+
return true;
605+
}
606+
}
607+
else if (count == 0)
608+
{
609+
value = !expectedResult; // No match found
610+
return true;
611+
}
612+
}
613+
value = false;
614+
return false;
595615
}
596616
}
597617

@@ -640,13 +660,21 @@ internal override IEnumerable<Message> CreateMessages(int db, IResultBox? result
640660

641661
internal override int GetHashSlot(ServerSelectionStrategy serverSelectionStrategy) => serverSelectionStrategy.HashSlot(key);
642662

643-
internal override bool TryValidate(in RawResult result, out bool value)
663+
internal override bool TryValidate(ref RespReader reader, out bool value)
644664
{
665+
// All commands (ZSCORE, GET, HGET) return scalar values
666+
if (!reader.IsScalar)
667+
{
668+
value = false;
669+
return false;
670+
}
671+
645672
switch (type)
646673
{
647674
case RedisType.SortedSet:
675+
// ZSCORE returns bulk string (score as double) or null
648676
var parsedValue = RedisValue.Null;
649-
if (!result.IsNull && result.TryGetDouble(out var val))
677+
if (!reader.IsNull && reader.TryReadDouble(out var val))
650678
{
651679
parsedValue = val;
652680
}
@@ -657,19 +685,12 @@ internal override bool TryValidate(in RawResult result, out bool value)
657685
return true;
658686

659687
default:
660-
switch (result.Resp2TypeBulkString)
661-
{
662-
case ResultType.BulkString:
663-
case ResultType.SimpleString:
664-
case ResultType.Integer:
665-
var parsed = result.AsRedisValue();
666-
value = (parsed == expectedValue) == expectedEqual;
667-
ConnectionMultiplexer.TraceWithoutContext("actual: " + (string?)parsed + "; expected: " + (string?)expectedValue +
668-
"; wanted: " + (expectedEqual ? "==" : "!=") + "; voting: " + value);
669-
return true;
670-
}
671-
value = false;
672-
return false;
688+
// GET or HGET returns bulk string, simple string, or integer
689+
var parsed = reader.ReadRedisValue();
690+
value = (parsed == expectedValue) == expectedEqual;
691+
ConnectionMultiplexer.TraceWithoutContext("actual: " + (string?)parsed + "; expected: " + (string?)expectedValue +
692+
"; wanted: " + (expectedEqual ? "==" : "!=") + "; voting: " + value);
693+
return true;
673694
}
674695
}
675696
}
@@ -711,26 +732,24 @@ internal override IEnumerable<Message> CreateMessages(int db, IResultBox? result
711732

712733
internal override int GetHashSlot(ServerSelectionStrategy serverSelectionStrategy) => serverSelectionStrategy.HashSlot(key);
713734

714-
internal override bool TryValidate(in RawResult result, out bool value)
735+
internal override bool TryValidate(ref RespReader reader, out bool value)
715736
{
716-
switch (result.Resp2TypeBulkString)
737+
// LINDEX returns bulk string, simple string, or integer
738+
if (reader.IsScalar)
717739
{
718-
case ResultType.BulkString:
719-
case ResultType.SimpleString:
720-
case ResultType.Integer:
721-
var parsed = result.AsRedisValue();
722-
if (expectedValue.HasValue)
723-
{
724-
value = (parsed == expectedValue.Value) == expectedResult;
725-
ConnectionMultiplexer.TraceWithoutContext("actual: " + (string?)parsed + "; expected: " + (string?)expectedValue.Value +
726-
"; wanted: " + (expectedResult ? "==" : "!=") + "; voting: " + value);
727-
}
728-
else
729-
{
730-
value = parsed.IsNull != expectedResult;
731-
ConnectionMultiplexer.TraceWithoutContext("exists: " + parsed + "; expected: " + expectedResult + "; voting: " + value);
732-
}
733-
return true;
740+
var parsed = reader.ReadRedisValue();
741+
if (expectedValue.HasValue)
742+
{
743+
value = (parsed == expectedValue.Value) == expectedResult;
744+
ConnectionMultiplexer.TraceWithoutContext("actual: " + (string?)parsed + "; expected: " + (string?)expectedValue.Value +
745+
"; wanted: " + (expectedResult ? "==" : "!=") + "; voting: " + value);
746+
}
747+
else
748+
{
749+
value = parsed.IsNull != expectedResult;
750+
ConnectionMultiplexer.TraceWithoutContext("exists: " + parsed + "; expected: " + expectedResult + "; voting: " + value);
751+
}
752+
return true;
734753
}
735754
value = false;
736755
return false;
@@ -784,18 +803,15 @@ internal override IEnumerable<Message> CreateMessages(int db, IResultBox? result
784803

785804
internal override int GetHashSlot(ServerSelectionStrategy serverSelectionStrategy) => serverSelectionStrategy.HashSlot(key);
786805

787-
internal override bool TryValidate(in RawResult result, out bool value)
806+
internal override bool TryValidate(ref RespReader reader, out bool value)
788807
{
789-
switch (result.Resp2TypeBulkString)
808+
// Length commands (HLEN, SCARD, LLEN, ZCARD, XLEN, STRLEN) return integer
809+
if (reader.IsScalar && reader.TryReadInt64(out var parsed))
790810
{
791-
case ResultType.BulkString:
792-
case ResultType.SimpleString:
793-
case ResultType.Integer:
794-
var parsed = result.AsRedisValue();
795-
value = parsed.IsInteger && (expectedLength.CompareTo((long)parsed) == compareToResult);
796-
ConnectionMultiplexer.TraceWithoutContext("actual: " + (string?)parsed + "; expected: " + expectedLength +
797-
"; wanted: " + GetComparisonString() + "; voting: " + value);
798-
return true;
811+
value = expectedLength.CompareTo(parsed) == compareToResult;
812+
ConnectionMultiplexer.TraceWithoutContext("actual: " + parsed + "; expected: " + expectedLength +
813+
"; wanted: " + GetComparisonString() + "; voting: " + value);
814+
return true;
799815
}
800816
value = false;
801817
return false;
@@ -841,18 +857,16 @@ internal override IEnumerable<Message> CreateMessages(int db, IResultBox? result
841857

842858
internal override int GetHashSlot(ServerSelectionStrategy serverSelectionStrategy) => serverSelectionStrategy.HashSlot(key);
843859

844-
internal override bool TryValidate(in RawResult result, out bool value)
860+
internal override bool TryValidate(ref RespReader reader, out bool value)
845861
{
846-
switch (result.Resp2TypeBulkString)
862+
// Length commands (HLEN, SCARD, LLEN, ZCARD, XLEN, STRLEN) return integer
863+
if (reader.IsScalar)
847864
{
848-
case ResultType.BulkString:
849-
case ResultType.SimpleString:
850-
case ResultType.Integer:
851-
var parsed = result.AsRedisValue();
852-
value = parsed.IsInteger && (expectedLength.CompareTo((long)parsed) == compareToResult);
853-
ConnectionMultiplexer.TraceWithoutContext("actual: " + (string?)parsed + "; expected: " + expectedLength +
854-
"; wanted: " + GetComparisonString() + "; voting: " + value);
855-
return true;
865+
var parsed = reader.ReadRedisValue();
866+
value = parsed.IsInteger && (expectedLength.CompareTo((long)parsed) == compareToResult);
867+
ConnectionMultiplexer.TraceWithoutContext("actual: " + (string?)parsed + "; expected: " + expectedLength +
868+
"; wanted: " + GetComparisonString() + "; voting: " + value);
869+
return true;
856870
}
857871
value = false;
858872
return false;
@@ -898,17 +912,16 @@ internal override IEnumerable<Message> CreateMessages(int db, IResultBox? result
898912

899913
internal override int GetHashSlot(ServerSelectionStrategy serverSelectionStrategy) => serverSelectionStrategy.HashSlot(key);
900914

901-
internal override bool TryValidate(in RawResult result, out bool value)
915+
internal override bool TryValidate(ref RespReader reader, out bool value)
902916
{
903-
switch (result.Resp2TypeBulkString)
917+
// ZCOUNT returns integer
918+
if (reader.IsScalar)
904919
{
905-
case ResultType.Integer:
906-
var parsedValue = result.AsRedisValue();
907-
value = (parsedValue == expectedValue) == expectedEqual;
908-
ConnectionMultiplexer.TraceWithoutContext("actual: " + (string?)parsedValue + "; expected: " + (string?)expectedValue + "; wanted: " + (expectedEqual ? "==" : "!=") + "; voting: " + value);
909-
return true;
920+
var parsedValue = reader.ReadRedisValue();
921+
value = (parsedValue == expectedValue) == expectedEqual;
922+
ConnectionMultiplexer.TraceWithoutContext("actual: " + (string?)parsedValue + "; expected: " + (string?)expectedValue + "; wanted: " + (expectedEqual ? "==" : "!=") + "; voting: " + value);
923+
return true;
910924
}
911-
912925
value = false;
913926
return false;
914927
}

src/StackExchange.Redis/ResultProcessor.cs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ protected virtual bool SetResultCore(PhysicalConnection connection, Message mess
354354
return SetResultCore(connection, message, rawResult);
355355
}
356356

357-
private static RawResult AsRaw(ref RespReader reader, bool resp3)
357+
internal static RawResult AsRaw(ref RespReader reader, bool resp3)
358358
{
359359
var flags = RawResult.ResultFlags.HasValue;
360360
if (!reader.IsNull) flags |= RawResult.ResultFlags.NonNull;
@@ -585,23 +585,34 @@ public static bool TryGet(in RawResult result, out bool value)
585585
return false;
586586
}
587587

588-
protected override bool SetResultCore(PhysicalConnection connection, Message message, ref RespReader reader)
588+
public static bool TryGet(ref RespReader reader, out bool value)
589589
{
590590
if (reader.IsScalar && reader.ScalarLengthIs(1))
591591
{
592592
var span = reader.TryGetSpan(out var tmp) ? tmp : reader.Buffer(stackalloc byte[1]);
593-
var value = span[0];
594-
if (value == (byte)'1')
593+
var byteValue = span[0];
594+
if (byteValue == (byte)'1')
595595
{
596-
SetResult(message, true);
596+
value = true;
597597
return true;
598598
}
599-
else if (value == (byte)'0')
599+
else if (byteValue == (byte)'0')
600600
{
601-
SetResult(message, false);
601+
value = false;
602602
return true;
603603
}
604604
}
605+
value = false;
606+
return false;
607+
}
608+
609+
protected override bool SetResultCore(PhysicalConnection connection, Message message, ref RespReader reader)
610+
{
611+
if (TryGet(ref reader, out bool value))
612+
{
613+
SetResult(message, value);
614+
return true;
615+
}
605616
return false;
606617
}
607618
}

0 commit comments

Comments
 (0)