Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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);
        }
Ejemplo n.º 3
0
        /// <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);
            }
        }