Skip to content

Commit ef81e6d

Browse files
committed
Redis doesn't do the BLMOVE check when the initial key does not exist.
1 parent 683e0e4 commit ef81e6d

File tree

2 files changed

+44
-41
lines changed

2 files changed

+44
-41
lines changed

libs/server/Objects/ItemBroker/CollectionItemBroker.cs

+41-38
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,10 @@ private static unsafe bool TryGetNextSetObjects(byte[] key, SortedSetObject sort
436436
}
437437
}
438438

439+
/// <summary>
440+
/// Try to get available item(s) from sorted set object based on command type and arguments
441+
/// When run from initializer (initial = true), can return WRONGTYPE errors
442+
/// </summary>
439443
private unsafe bool TryGetResult(byte[] key, StorageSession storageSession,
440444
RespCommand command, ArgSlice[] cmdArgs, bool initial,
441445
out int currCount, out CollectionItemResult result)
@@ -451,13 +455,13 @@ private unsafe bool TryGetResult(byte[] key, StorageSession storageSession,
451455
_ => throw new NotSupportedException()
452456
};
453457

458+
var asKey = storageSession.scratchBufferManager.CreateArgSlice(key);
454459
ArgSlice dstKey = default;
455460
if (command == RespCommand.BLMOVE)
456461
{
457462
dstKey = cmdArgs[0];
458463
}
459464

460-
var asKey = storageSession.scratchBufferManager.CreateArgSlice(key);
461465
// Create a transaction if not currently in a running transaction
462466
if (storageSession.txnManager.state != TxnState.Running)
463467
{
@@ -479,8 +483,6 @@ private unsafe bool TryGetResult(byte[] key, StorageSession storageSession,
479483

480484
var lockableContext = storageSession.txnManager.LockableContext;
481485
var objectLockableContext = storageSession.txnManager.ObjectStoreLockableContext;
482-
IGarnetObject dstObj = null;
483-
byte[] arrDstKey = default;
484486

485487
try
486488
{
@@ -491,42 +493,18 @@ private unsafe bool TryGetResult(byte[] key, StorageSession storageSession,
491493
if (!initial)
492494
return false;
493495

496+
// Check the string store as well to see if WRONGTYPE should be returned.
494497
statusOp = storageSession.GET(asKey, out ArgSlice _, ref lockableContext);
495498

496499
if (statusOp != GarnetStatus.NOTFOUND)
497500
{
498501
result = new CollectionItemResult(GarnetStatus.WRONGTYPE);
499-
return true;
500-
}
501-
502-
if (command == RespCommand.BLMOVE)
503-
{
504-
arrDstKey = dstKey.ToArray();
505-
var dstStatusOp = storageSession.GET(arrDstKey, out var osDstObject, ref objectLockableContext);
506-
if (dstStatusOp != GarnetStatus.NOTFOUND && osDstObject.GarnetObject is not ListObject)
507-
{
508-
result = new CollectionItemResult(GarnetStatus.WRONGTYPE);
509-
return true;
510-
}
511-
512-
dstStatusOp = storageSession.GET(dstKey, out ArgSlice _, ref lockableContext);
513-
if (dstStatusOp != GarnetStatus.NOTFOUND)
514-
{
515-
result = new CollectionItemResult(GarnetStatus.WRONGTYPE);
516-
return true;
517-
}
502+
return initial;
518503
}
519504

520505
return false;
521506
}
522507

523-
if (command == RespCommand.BLMOVE)
524-
{
525-
arrDstKey = dstKey.ToArray();
526-
var dstStatusOp = storageSession.GET(arrDstKey, out var osDstObject, ref objectLockableContext);
527-
if (dstStatusOp != GarnetStatus.NOTFOUND) dstObj = osDstObject.GarnetObject;
528-
}
529-
530508
// Check for type match between the observer and the actual object type
531509
// If types match, get next item based on item type
532510
switch (osObject.GarnetObject)
@@ -550,21 +528,46 @@ private unsafe bool TryGetResult(byte[] key, StorageSession storageSession,
550528
result = new CollectionItemResult(key, nextItem);
551529
break;
552530
case RespCommand.BLMOVE:
531+
var arrDstKey = dstKey.ToArray();
532+
var dstStatusOp = storageSession.GET(arrDstKey, out var osDstObject, ref objectLockableContext);
533+
553534
ListObject dstList;
554535
var newObj = false;
555-
if (dstObj == null)
556-
{
557-
dstList = new ListObject();
558-
newObj = true;
559-
}
560-
else if (dstObj is ListObject tmpDstList)
536+
537+
if (dstStatusOp != GarnetStatus.NOTFOUND)
561538
{
562-
dstList = tmpDstList;
539+
var dstObj = osDstObject.GarnetObject;
540+
541+
if (dstObj == null)
542+
{
543+
dstList = new ListObject();
544+
newObj = true;
545+
}
546+
else if (dstObj is ListObject tmpDstList)
547+
{
548+
dstList = tmpDstList;
549+
}
550+
else
551+
{
552+
result = new CollectionItemResult(GarnetStatus.WRONGTYPE);
553+
return initial;
554+
}
563555
}
564556
else
565557
{
566-
result = new CollectionItemResult(GarnetStatus.WRONGTYPE);
567-
return initial;
558+
if (initial)
559+
{
560+
// Check string store for wrongtype errors on initial run.
561+
dstStatusOp = storageSession.GET(dstKey, out ArgSlice _, ref lockableContext);
562+
if (dstStatusOp != GarnetStatus.NOTFOUND)
563+
{
564+
result = new CollectionItemResult(GarnetStatus.WRONGTYPE);
565+
return initial;
566+
}
567+
}
568+
569+
dstList = new ListObject();
570+
newObj = true;
568571
}
569572

570573
isSuccessful = TryMoveNextListItem(listObj, dstList, (OperationDirection)cmdArgs[1].ReadOnlySpan[0],

test/Garnet.test/RespBlockingCollectionTests.cs

+3-3
Original file line numberDiff line numberDiff line change
@@ -656,16 +656,16 @@ public void PopWrongTypeTest()
656656
response = lightClientRequest.SendCommand("BLMOVE set foo RIGHT RIGHT 0");
657657
TestUtils.AssertEqualUpToExpectedLength(expectedResponse, response);
658658

659-
response = lightClientRequest.SendCommand("BLMOVE foo key LEFT LEFT 0");
659+
response = lightClientRequest.SendCommand("BLMOVE list set LEFT LEFT 0");
660660
TestUtils.AssertEqualUpToExpectedLength(expectedResponse, response);
661661

662-
response = lightClientRequest.SendCommand("BLMOVE foo set LEFT LEFT 0");
662+
response = lightClientRequest.SendCommand("BLMOVE list key LEFT LEFT 0");
663663
TestUtils.AssertEqualUpToExpectedLength(expectedResponse, response);
664664

665665
response = lightClientRequest.SendCommand("BRPOPLPUSH key foo 0");
666666
TestUtils.AssertEqualUpToExpectedLength(expectedResponse, response);
667667

668-
response = lightClientRequest.SendCommand("BRPOPLPUSH foo key 0");
668+
response = lightClientRequest.SendCommand("BRPOPLPUSH list key 0");
669669
TestUtils.AssertEqualUpToExpectedLength(expectedResponse, response);
670670

671671
response = lightClientRequest.SendCommand("BLPOP key 0");

0 commit comments

Comments
 (0)