internal async Task <List <PartitionKeyRange> > GetTargetPartitionKeyRangesAsync(string collectionResourceId, List <Range <string> > providedRanges) { if (string.IsNullOrEmpty(nameof(collectionResourceId))) { throw new ArgumentNullException(); } if (providedRanges == null || !providedRanges.Any()) { throw new ArgumentNullException(nameof(providedRanges)); } IRoutingMapProvider routingMapProvider = await this.Client.GetRoutingMapProviderAsync(); List <PartitionKeyRange> ranges = await routingMapProvider.TryGetOverlappingRangesAsync(collectionResourceId, providedRanges); if (ranges == null && PathsHelper.IsNameBased(this.ResourceLink)) { // Refresh the cache and don't try to re-resolve collection as it is not clear what already // happened based on previously resolved collection rid. // Return NotFoundException this time. Next query will succeed. // This can only happen if collection is deleted/created with same name and client was not restarted // in between. CollectionCache collectionCache = await this.Client.GetCollectionCacheAsync(); collectionCache.Refresh(this.ResourceLink); } if (ranges == null) { throw new NotFoundException($"{DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture)}: GetTargetPartitionKeyRanges(collectionResourceId:{collectionResourceId}, providedRanges: {string.Join(",", providedRanges)} failed due to stale cache"); } return(ranges); }
public async Task <PartitionKeyRange> GetTargetPartitionKeyRangeByIdAsync(string collectionResourceId, string partitionKeyRangeId) { IRoutingMapProvider routingMapProvider = await this.Client.GetRoutingMapProviderAsync(); PartitionKeyRange range = await routingMapProvider.TryGetPartitionKeyRangeByIdAsync(collectionResourceId, partitionKeyRangeId); if (range == null && PathsHelper.IsNameBased(this.ResourceLink)) { // Refresh the cache and don't try to reresolve collection as it is not clear what already // happened based on previously resolved collection rid. // Return NotFoundException this time. Next query will succeed. // This can only happen if collection is deleted/created with same name and client was not restarted // inbetween. CollectionCache collectionCache = await this.Client.GetCollectionCacheAsync(); collectionCache.Refresh(this.ResourceLink); } if (range == null) { throw new NotFoundException($"{DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture)}: GetTargetPartitionKeyRangeById(collectionResourceId:{collectionResourceId}, partitionKeyRangeId: {partitionKeyRangeId}) failed due to stale cache"); } return(range); }
/// <summary> /// This method is only used in client SDK in retry policy as it doesn't have request handy. /// </summary> public void Refresh(string resourceAddress, string apiVersion = null) { InternalCache cache = this.GetCache(apiVersion); if (PathsHelper.IsNameBased(resourceAddress)) { string resourceFullName = PathsHelper.GetCollectionPath(resourceAddress); cache.collectionInfoByName.TryRemoveIfCompleted(resourceFullName); } }
internal static string GetAuthorizationResourceIdOrFullName(string resourceType, string resourceIdOrFullName) { if (string.IsNullOrEmpty(resourceType) || string.IsNullOrEmpty(resourceIdOrFullName)) { return(resourceIdOrFullName); } if (PathsHelper.IsNameBased(resourceIdOrFullName)) { // resource fullname is always end with name (not type segment like docs/colls). return(resourceIdOrFullName); } if (resourceType.Equals(Paths.OffersPathSegment, StringComparison.OrdinalIgnoreCase) || resourceType.Equals(Paths.PartitionsPathSegment, StringComparison.OrdinalIgnoreCase) || resourceType.Equals(Paths.TopologyPathSegment, StringComparison.OrdinalIgnoreCase) || resourceType.Equals(Paths.RidRangePathSegment, StringComparison.OrdinalIgnoreCase) || resourceType.Equals(Paths.SnapshotsPathSegment, StringComparison.OrdinalIgnoreCase)) { return(resourceIdOrFullName); } ResourceId parsedRId = ResourceId.Parse(resourceIdOrFullName); if (resourceType.Equals(Paths.DatabasesPathSegment, StringComparison.OrdinalIgnoreCase)) { return(parsedRId.DatabaseId.ToString()); } else if (resourceType.Equals(Paths.UsersPathSegment, StringComparison.OrdinalIgnoreCase)) { return(parsedRId.UserId.ToString()); } else if (resourceType.Equals(Paths.UserDefinedTypesPathSegment, StringComparison.OrdinalIgnoreCase)) { return(parsedRId.UserDefinedTypeId.ToString()); } else if (resourceType.Equals(Paths.CollectionsPathSegment, StringComparison.OrdinalIgnoreCase)) { return(parsedRId.DocumentCollectionId.ToString()); } else if (resourceType.Equals(Paths.ClientEncryptionKeysPathSegment, StringComparison.OrdinalIgnoreCase)) { return(parsedRId.ClientEncryptionKeyId.ToString()); } else if (resourceType.Equals(Paths.DocumentsPathSegment, StringComparison.OrdinalIgnoreCase)) { return(parsedRId.DocumentId.ToString()); } else { // leaf node return(resourceIdOrFullName); } }
public static void SerializeMessagePayload( MemoryStream stream, string verb, string resourceId, string resourceType, INameValueCollection headers, bool bUseUtcNowForMissingXDate = false) { string xDate = AuthorizationHelper.GetHeaderValue(headers, HttpConstants.HttpHeaders.XDate); string date = AuthorizationHelper.GetHeaderValue(headers, HttpConstants.HttpHeaders.HttpDate); // At-least one of date header should present // https://docs.microsoft.com/en-us/rest/api/documentdb/access-control-on-documentdb-resources if (string.IsNullOrEmpty(xDate) && string.IsNullOrWhiteSpace(date)) { if (!bUseUtcNowForMissingXDate) { throw new UnauthorizedException(RMResources.InvalidDateHeader); } headers[HttpConstants.HttpHeaders.XDate] = DateTime.UtcNow.ToString("r", CultureInfo.InvariantCulture); xDate = AuthorizationHelper.GetHeaderValue(headers, HttpConstants.HttpHeaders.XDate); } // for name based, it is case sensitive, we won't use the lower case if (!PathsHelper.IsNameBased(resourceId)) { resourceId = resourceId.ToLowerInvariant(); } stream.Write(verb.ToLowerInvariant()); stream.Write("\n"); stream.Write(resourceType.ToLowerInvariant()); stream.Write("\n"); stream.Write(resourceId); stream.Write("\n"); stream.Write(xDate.ToLowerInvariant()); stream.Write("\n"); stream.Write(xDate.Equals(string.Empty, StringComparison.OrdinalIgnoreCase) ? date.ToLowerInvariant() : string.Empty); stream.Write("\n"); }
/// <summary> /// This method is only used in client SDK in retry policy as it doesn't have request handy. /// </summary> public void Refresh(string resourceAddress) { if (PathsHelper.IsNameBased(resourceAddress)) { string resourceFullName = PathsHelper.GetCollectionPath(resourceAddress); this.collectionInfoByNameCache.Refresh( resourceFullName, async() => { CosmosContainerSettings collection = await this.GetByNameAsync(resourceFullName, CancellationToken.None); if (collection != null) { this.collectionInfoByIdCache.Set(collection.ResourceId, collection); } return(collection); }, CancellationToken.None); } }