Skip to content

Commit

Permalink
PartitionRoutingHelper: Fix ReadFeed ArgumentNullException due to con…
Browse files Browse the repository at this point in the history
…tainer cache miss (#1512)

* Test commit to treat null as missing info.

* UT asserting the resolvedRangeInfo with null values

* Marking missing routing map as warning

* reverting unnecessary change

* Using named parameters
  • Loading branch information
kirankumarkolli authored May 15, 2020
1 parent 3900d22 commit 46e8aca
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public virtual async Task<IReadOnlyList<PartitionKeyRange>> TryGetOverlappingRan

if (routingMap == null)
{
DefaultTrace.TraceInformation(string.Format("Routing Map Null for collection: {0} for range: {1}, forceRefresh:{2}", collectionRid, range.ToString(), forceRefresh));
DefaultTrace.TraceWarning(string.Format("Routing Map Null for collection: {0} for range: {1}, forceRefresh:{2}", collectionRid, range.ToString(), forceRefresh));
return null;
}

Expand Down
8 changes: 6 additions & 2 deletions Microsoft.Azure.Cosmos/src/Routing/PartitionRoutingHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace Microsoft.Azure.Cosmos.Routing
{
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
Expand Down Expand Up @@ -228,7 +229,10 @@ await routingMapProvider.TryGetRangeByEffectivePartitionKeyAsync(collectionRid,
if (!rangeFromContinuationToken.Equals(targetPartitionKeyRange.ToRange()))
{
// Cannot find target range. Either collection was resolved incorrectly or the range was split
List<PartitionKeyRange> replacedRanges = (await routingMapProvider.TryGetOverlappingRangesAsync(collectionRid, rangeFromContinuationToken, true)).ToList();
IReadOnlyList<PartitionKeyRange> replacedRanges = await routingMapProvider.TryGetOverlappingRangesAsync(
collectionResourceId: collectionRid,
range: rangeFromContinuationToken,
forceRefresh: true);

if (replacedRanges == null || replacedRanges.Count < 1)
{
Expand All @@ -244,7 +248,7 @@ await routingMapProvider.TryGetRangeByEffectivePartitionKeyAsync(collectionRid,

if (direction == RntdbEnumerationDirection.Reverse)
{
replacedRanges.Reverse();
replacedRanges = new ReadOnlyCollection<PartitionKeyRange>(replacedRanges.Reverse().ToList());
}

List<CompositeContinuationToken> continuationTokensToBePersisted = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,52 @@ public async Task GetTargetRangeFromContinuationTokenWhenNotEmpty()
routingMapProvider.Verify();
}

[TestMethod]
public async Task GetTargetRangeFromContinuationTokenNonExistentContainer()
{
List<Range<string>> providedRanges = new List<Range<string>> {
new Range<string>(
PartitionKeyInternal.MinimumInclusiveEffectivePartitionKey,
PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey,
isMinInclusive: true,
isMaxInclusive: false)
};

//Not empty
Range<string> range = new Range<string>("A", "B", true, false);
List<CompositeContinuationToken> suppliedTokens = new List<CompositeContinuationToken>
{
new CompositeContinuationToken{ Range = range }
};

IReadOnlyList<PartitionKeyRange> overlappingRanges = new List<PartitionKeyRange> {
new PartitionKeyRange { Id = "0", MinInclusive = "A", MaxExclusive = "B" },
new PartitionKeyRange { Id = "1", MinInclusive = "B", MaxExclusive = "C" }
}.AsReadOnly();

Mock<IRoutingMapProvider> routingMapProvider = new Mock<IRoutingMapProvider>();
routingMapProvider
.SetupSequence(m => m.TryGetOverlappingRangesAsync(
It.IsAny<string>(),
It.Is<Range<string>>(x => x.Min == range.Min),
It.IsAny<bool>()))
.Returns(Task.FromResult((IReadOnlyList<PartitionKeyRange>)overlappingRanges.Skip(1).ToList()))
.Returns(Task.FromResult((IReadOnlyList<PartitionKeyRange>)null));

PartitionRoutingHelper partitionRoutingHelper = new PartitionRoutingHelper();
ResolvedRangeInfo resolvedRangeInfo = await partitionRoutingHelper.TryGetTargetRangeFromContinuationTokenRangeAsync(
providedRanges,
routingMapProvider.Object,
CollectionId,
range,
suppliedTokens,
RntdbEnumerationDirection.Reverse);

Assert.IsNotNull(resolvedRangeInfo);
Assert.IsNull(resolvedRangeInfo.ResolvedRange);
Assert.IsNull(resolvedRangeInfo.ContinuationTokens);
}

[TestMethod]
public async Task GetTargetRangeFromContinuationTokenOnSplit()
{
Expand Down

0 comments on commit 46e8aca

Please sign in to comment.