Example #1
0
        public async Task ContainerContractTest()
        {
            ClientEncryptionIncludedPath clientEncryptionIncludedPath1 = new ClientEncryptionIncludedPath()
            {
                Path = "/path",
                ClientEncryptionKeyId = "dekId",
                EncryptionAlgorithm   = "AEAD_AES_256_CBC_HMAC_SHA256",
                EncryptionType        = "Randomized"
            };

            Collection <ClientEncryptionIncludedPath> paths = new Collection <ClientEncryptionIncludedPath>()
            {
                clientEncryptionIncludedPath1
            };

            ContainerProperties containerProperties = new ContainerProperties(Guid.NewGuid().ToString(), "/users")
            {
                IndexingPolicy = new IndexingPolicy()
                {
                    Automatic     = true,
                    IndexingMode  = IndexingMode.Consistent,
                    IncludedPaths = new Collection <IncludedPath>()
                    {
                        new IncludedPath()
                        {
                            Path = "/*"
                        }
                    },
                    ExcludedPaths = new Collection <ExcludedPath>()
                    {
                        new ExcludedPath()
                        {
                            Path = "/test/*"
                        }
                    },
                    CompositeIndexes = new Collection <Collection <CompositePath> >()
                    {
                        new Collection <CompositePath>()
                        {
                            new CompositePath()
                            {
                                Path  = "/address/city",
                                Order = CompositePathSortOrder.Ascending
                            },
                            new CompositePath()
                            {
                                Path  = "/address/zipcode",
                                Order = CompositePathSortOrder.Descending
                            }
                        }
                    },
                    SpatialIndexes = new Collection <SpatialPath>()
                    {
                        new SpatialPath()
                        {
                            Path         = "/address/spatial/*",
                            SpatialTypes = new Collection <SpatialType>()
                            {
                                SpatialType.LineString
                            }
                        }
                    }
                },
                ClientEncryptionPolicy = new ClientEncryptionPolicy(paths)
            };

            CosmosJsonDotNetSerializer serializer = new CosmosJsonDotNetSerializer();
            Stream stream = serializer.ToStream(containerProperties);
            ContainerProperties deserialziedTest = serializer.FromStream <ContainerProperties>(stream);

            ContainerResponse response = await this.database.CreateContainerAsync(containerProperties);

            Assert.IsNotNull(response);
            Assert.IsTrue(response.RequestCharge > 0);
            Assert.IsNotNull(response.Headers);
            Assert.IsNotNull(response.Headers.ActivityId);

            ContainerProperties responseProperties = response.Resource;

            Assert.IsNotNull(responseProperties.Id);
            Assert.IsNotNull(responseProperties.ResourceId);
            Assert.IsNotNull(responseProperties.ETag);
            Assert.IsTrue(responseProperties.LastModified.HasValue);

            Assert.IsTrue(responseProperties.LastModified.Value > new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), responseProperties.LastModified.Value.ToString());

            Assert.AreEqual(1, responseProperties.IndexingPolicy.IncludedPaths.Count);
            IncludedPath includedPath = responseProperties.IndexingPolicy.IncludedPaths.First();

            Assert.AreEqual("/*", includedPath.Path);

            Assert.AreEqual("/test/*", responseProperties.IndexingPolicy.ExcludedPaths.First().Path);

            Assert.AreEqual(1, responseProperties.IndexingPolicy.CompositeIndexes.Count);
            Assert.AreEqual(2, responseProperties.IndexingPolicy.CompositeIndexes.First().Count);
            CompositePath compositePath = responseProperties.IndexingPolicy.CompositeIndexes.First().First();

            Assert.AreEqual("/address/city", compositePath.Path);
            Assert.AreEqual(CompositePathSortOrder.Ascending, compositePath.Order);

            Assert.AreEqual(1, responseProperties.IndexingPolicy.SpatialIndexes.Count);
            SpatialPath spatialPath = responseProperties.IndexingPolicy.SpatialIndexes.First();

            Assert.AreEqual("/address/spatial/*", spatialPath.Path);
            Assert.AreEqual(4, spatialPath.SpatialTypes.Count); // All SpatialTypes are returned

            Assert.AreEqual(1, responseProperties.ClientEncryptionPolicy.IncludedPaths.Count());
            Assert.AreEqual(1, responseProperties.ClientEncryptionPolicy.PolicyFormatVersion);
            ClientEncryptionIncludedPath clientEncryptionIncludedPath = responseProperties.ClientEncryptionPolicy.IncludedPaths.First();

            Assert.IsTrue(this.VerifyClientEncryptionIncludedPath(clientEncryptionIncludedPath1, clientEncryptionIncludedPath));
        }
Example #2
0
        private async Task TestGloballyUniqueFieldForPartitionedCollectionHelperAsync(CosmosClient client)
        {
            ContainerProperties collectionSpec = new ContainerProperties
            {
                Id = "TestGloballyUniqueFieldForPartitionedCollection_" + Guid.NewGuid(),
                PartitionKeyPath = defaultPartitionKeyDefinition,
                UniqueKeyPolicy  = new UniqueKeyPolicy
                {
                    UniqueKeys = new Collection <UniqueKey> {
                        new UniqueKey {
                            Paths = new Collection <string> {
                                "/name"
                            }
                        }
                    }
                },
                IndexingPolicy = new IndexingPolicy
                {
                    IndexingMode  = IndexingMode.Consistent,
                    IncludedPaths = new Collection <IncludedPath> {
                        new IncludedPath {
                            Path = "/name/?", Indexes = new Collection <Index> {
                                new HashIndex(DataType.String, 7)
                            }
                        },
                    },
                    ExcludedPaths = new Collection <ExcludedPath> {
                        new ExcludedPath {
                            Path = "/*"
                        }
                    }
                }
            };

            Container collection = await this.database.CreateContainerAsync(
                collectionSpec,
                20000);

            const int     partitionCount     = 50;
            List <string> partitionKeyValues = new List <string>();

            for (int i = 0; i < partitionCount * 3; ++i)
            {
                partitionKeyValues.Add(Guid.NewGuid().ToString());
            }

            string documentTemplate = "{{ \"id\":\"{0}\",  \"pk\":\"{1}\", \"name\":\"{2}\" }}";

            foreach (string partitionKey in partitionKeyValues)
            {
                string document = string.Format(documentTemplate, Guid.NewGuid().ToString(), partitionKey, "Same Name");
                await collection.CreateItemAsync <dynamic>(JObject.Parse(document));
            }

            string conflictDocument = string.Format(documentTemplate, Guid.NewGuid().ToString(), partitionKeyValues[0], "Same Name");

            try
            {
                await collection.CreateItemAsync <dynamic>(JObject.Parse(conflictDocument));

                Assert.Fail("Did not throw due to unique constraint");
            }
            catch (CosmosException ex)
            {
                Assert.AreEqual(HttpStatusCode.Conflict, ex.StatusCode, $"Expected:Conflict, Actual:{ex.StatusCode}; Exception:ex.ToString()");
            }
        }
Example #3
0
        private async Task <Tuple <DocumentFeedResponse <CosmosElement>, string> > ExecuteOnceAsync(
            IDocumentClientRetryPolicy retryPolicyInstance,
            CancellationToken cancellationToken)
        {
            // Don't reuse request, as the rest of client SDK doesn't reuse requests between retries.
            // The code leaves some temporary garbage in request (in RequestContext etc.),
            // which shold be erased during retries.
            using (DocumentServiceRequest request = await this.CreateRequestAsync())
            {
                DocumentFeedResponse <CosmosElement> feedRespose;
                string partitionIdentifier;
                // We need to determine how to execute the request:
                if (LogicalPartitionKeyProvided(request))
                {
                    feedRespose = await this.ExecuteRequestAsync(request, retryPolicyInstance, cancellationToken);

                    partitionIdentifier = $"PKId({request.Headers[HttpConstants.HttpHeaders.PartitionKey]})";
                }
                else if (PhysicalPartitionKeyRangeIdProvided(this))
                {
                    CollectionCache collectionCache = await this.Client.GetCollectionCacheAsync();

                    ContainerProperties collection = await collectionCache.ResolveCollectionAsync(request, CancellationToken.None, NoOpTrace.Singleton);

                    request.RouteTo(new PartitionKeyRangeIdentity(collection.ResourceId, base.PartitionKeyRangeId));
                    feedRespose = await this.ExecuteRequestAsync(request, retryPolicyInstance, cancellationToken);

                    partitionIdentifier = base.PartitionKeyRangeId;
                }
                else
                {
                    // The query is going to become a full fan out, but we go one partition at a time.
                    if (ServiceInteropAvailable())
                    {
                        // Get the routing map provider
                        CollectionCache collectionCache = await this.Client.GetCollectionCacheAsync();

                        ContainerProperties collection = await collectionCache.ResolveCollectionAsync(request, CancellationToken.None, NoOpTrace.Singleton);

                        QueryPartitionProvider queryPartitionProvider = await this.Client.GetQueryPartitionProviderAsync();

                        IRoutingMapProvider routingMapProvider = await this.Client.GetRoutingMapProviderAsync();

                        // Figure out what partition you are going to based on the range from the continuation token
                        // If token is null then just start at partitionKeyRangeId "0"
                        List <CompositeContinuationToken> suppliedTokens;
                        Range <string> rangeFromContinuationToken =
                            this.partitionRoutingHelper.ExtractPartitionKeyRangeFromContinuationToken(
                                request.Headers,
                                out suppliedTokens);
                        Tuple <PartitionRoutingHelper.ResolvedRangeInfo, IReadOnlyList <Range <string> > > queryRoutingInfo =
                            await this.TryGetTargetPartitionKeyRangeAsync(
                                request,
                                collection,
                                queryPartitionProvider,
                                routingMapProvider,
                                rangeFromContinuationToken,
                                suppliedTokens);

                        if (request.IsNameBased && queryRoutingInfo == null)
                        {
                            request.ForceNameCacheRefresh = true;
                            collection = await collectionCache.ResolveCollectionAsync(request, CancellationToken.None, NoOpTrace.Singleton);

                            queryRoutingInfo = await this.TryGetTargetPartitionKeyRangeAsync(
                                request,
                                collection,
                                queryPartitionProvider,
                                routingMapProvider,
                                rangeFromContinuationToken,
                                suppliedTokens);
                        }

                        if (queryRoutingInfo == null)
                        {
                            throw new NotFoundException($"{DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture)}: Was not able to get queryRoutingInfo even after resolve collection async with force name cache refresh to the following collectionRid: {collection.ResourceId} with the supplied tokens: {JsonConvert.SerializeObject(suppliedTokens)}");
                        }

                        request.RouteTo(new PartitionKeyRangeIdentity(collection.ResourceId, queryRoutingInfo.Item1.ResolvedRange.Id));
                        DocumentFeedResponse <CosmosElement> response = await this.ExecuteRequestAsync(request, retryPolicyInstance, cancellationToken);

                        // Form a composite continuation token (range + backend continuation token).
                        // If the backend continuation token was null for the range,
                        // then use the next adjacent range.
                        // This is how the default execution context serially visits every partition.
                        if (!await this.partitionRoutingHelper.TryAddPartitionKeyRangeToContinuationTokenAsync(
                                response.Headers,
                                providedPartitionKeyRanges: queryRoutingInfo.Item2,
                                routingMapProvider: routingMapProvider,
                                collectionRid: collection.ResourceId,
                                resolvedRangeInfo: queryRoutingInfo.Item1,
                                trace: NoOpTrace.Singleton))
                        {
                            // Collection to which this request was resolved doesn't exist.
                            // Retry policy will refresh the cache and return NotFound.
                            throw new NotFoundException($"{DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture)}: Call to TryAddPartitionKeyRangeToContinuationTokenAsync failed to the following collectionRid: {collection.ResourceId} with the supplied tokens: {JsonConvert.SerializeObject(suppliedTokens)}");
                        }

                        feedRespose         = response;
                        partitionIdentifier = queryRoutingInfo.Item1.ResolvedRange.Id;
                    }
                    else
                    {
                        // For non-Windows platforms(like Linux and OSX) in .NET Core SDK, we cannot use ServiceInterop for parsing the query,
                        // so forcing the request through Gateway. We are also now by-passing this for 32-bit host process in NETFX on Windows
                        // as the ServiceInterop dll is only available in 64-bit.

                        request.UseGatewayMode = true;
                        feedRespose            = await this.ExecuteRequestAsync(request, retryPolicyInstance, cancellationToken);

                        partitionIdentifier = "Gateway";
                    }
                }

                return(new Tuple <DocumentFeedResponse <CosmosElement>, string>(feedRespose, partitionIdentifier));
            }
        }
Example #4
0
        public async Task ChangeFeedIteratorCore_WithFullFidelity()
        {
            ContainerProperties properties = new ContainerProperties(id: Guid.NewGuid().ToString(), partitionKeyPath: ChangeFeedIteratorCoreTests.PartitionKey);

            properties.ChangeFeedPolicy.FullFidelityRetention = TimeSpan.FromMinutes(5);
            ContainerResponse response = await this.database.CreateContainerAsync(
                properties,
                cancellationToken : this.cancellationToken);

            ContainerInternal container = (ContainerInternal)response;
            // FF does not work with StartFromBeginning currently, so we capture an initial continuation.
            FeedIterator <ToDoActivityWithMetadata> fullFidelityIterator = container.GetChangeFeedIterator <ToDoActivityWithMetadata>(
                ChangeFeedStartFrom.Now(),
                ChangeFeedMode.FullFidelity);
            string initialContinuation = null;

            while (fullFidelityIterator.HasMoreResults)
            {
                try
                {
                    FeedResponse <ToDoActivityWithMetadata> feedResponse = await fullFidelityIterator.ReadNextAsync(this.cancellationToken);

                    initialContinuation = feedResponse.ContinuationToken;
                }
                catch (CosmosException cosmosException) when(cosmosException.StatusCode == HttpStatusCode.NotModified)
                {
                    initialContinuation = cosmosException.Headers.ContinuationToken;
                    break;
                }
            }

            // Insert documents and then delete them
            int totalDocuments = 50;
            IList <ToDoActivity> createdItems = await this.CreateRandomItems(container, totalDocuments, randomPartitionKey : true);

            foreach (ToDoActivity item in createdItems)
            {
                await container.DeleteItemAsync <ToDoActivity>(item.id, new PartitionKey(item.status));
            }

            // Resume Change Feed and verify we pickup all the events
            fullFidelityIterator = container.GetChangeFeedIterator <ToDoActivityWithMetadata>(
                ChangeFeedStartFrom.ContinuationToken(initialContinuation),
                ChangeFeedMode.FullFidelity);
            int  detectedEvents = 0;
            bool hasInserts     = false;
            bool hasDeletes     = false;

            while (fullFidelityIterator.HasMoreResults)
            {
                try
                {
                    FeedResponse <ToDoActivityWithMetadata> feedResponse = await fullFidelityIterator.ReadNextAsync(this.cancellationToken);

                    foreach (ToDoActivityWithMetadata item in feedResponse)
                    {
                        Assert.IsNotNull(item.metadata, "Metadata not present");
                        Assert.IsNotNull(item.metadata.operationType, "Metadata has no operationType");
                        hasInserts |= item.metadata.operationType == "create";
                        hasDeletes |= item.metadata.operationType == "delete";
                    }

                    detectedEvents += feedResponse.Count;
                }
                catch (CosmosException cosmosException) when(cosmosException.StatusCode == HttpStatusCode.NotModified)
                {
                    break;
                }
            }

            Assert.AreEqual(2 * totalDocuments, detectedEvents, "Full Fidelity should include inserts and delete events.");
            Assert.IsTrue(hasInserts, "No metadata for create operationType found");
            Assert.IsTrue(hasDeletes, "No metadata for delete operationType found");
        }
        public override Task <ContainerResponse> ReplaceContainerAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions = null, CancellationToken cancellationToken = default)
        {
            var returnValue = new CosmosContainerResponseMock();

            return(Task.FromResult((ContainerResponse)returnValue));
        }
Example #6
0
        public void ContainerSettingsWithIndexingPolicyTest()
        {
            string id     = Guid.NewGuid().ToString();
            string pkPath = "/partitionKey";

            // Two equivalent definitions
            ContainerProperties cosmosContainerSettings = new ContainerProperties(id, pkPath);

            cosmosContainerSettings.IndexingPolicy.Automatic = true;
            cosmosContainerSettings.IndexingPolicy.IncludedPaths.Add(new Cosmos.IncludedPath()
            {
                Path = "/id1/*"
            });

            Cosmos.UniqueKey cuk1 = new Cosmos.UniqueKey();
            cuk1.Paths.Add("/u1");
            cosmosContainerSettings.UniqueKeyPolicy.UniqueKeys.Add(cuk1);

            DocumentCollection collection = new DocumentCollection()
            {
                Id           = id,
                PartitionKey = new PartitionKeyDefinition()
                {
                    Paths = new Collection <string>()
                    {
                        pkPath
                    },
                }
            };

            collection.IndexingPolicy.Automatic = true;
            collection.IndexingPolicy.IncludedPaths.Add(new Documents.IncludedPath()
            {
                Path = "/id1/*"
            });

            Documents.UniqueKey duk1 = new Documents.UniqueKey();
            duk1.Paths.Add("/u1");
            collection.UniqueKeyPolicy.UniqueKeys.Add(duk1);

            string cosmosSerialized = SettingsContractTests.CosmosSerialize(cosmosContainerSettings);
            string directSerialized = SettingsContractTests.DirectSerialize(collection);

            // Swap de-serialize and validate
            ContainerProperties containerDeserSettings = SettingsContractTests.CosmosDeserialize <ContainerProperties>(directSerialized);
            DocumentCollection  collectionDeser        = SettingsContractTests.DirectDeSerialize <DocumentCollection>(cosmosSerialized);

            Assert.AreEqual(collection.Id, containerDeserSettings.Id);
            Assert.AreEqual(collection.PartitionKey.Paths[0], containerDeserSettings.PartitionKeyPath);
            Assert.AreEqual(collection.IndexingPolicy.Automatic, containerDeserSettings.IndexingPolicy.Automatic);
            Assert.AreEqual(collection.IndexingPolicy.IncludedPaths.Count, containerDeserSettings.IndexingPolicy.IncludedPaths.Count);
            Assert.AreEqual(collection.IndexingPolicy.IncludedPaths[0].Path, containerDeserSettings.IndexingPolicy.IncludedPaths[0].Path);
            Assert.AreEqual(collection.IndexingPolicy.IncludedPaths[0].Indexes.Count, containerDeserSettings.IndexingPolicy.IncludedPaths[0].Indexes.Count);
            Assert.AreEqual(collection.UniqueKeyPolicy.UniqueKeys.Count, containerDeserSettings.UniqueKeyPolicy.UniqueKeys.Count);
            Assert.AreEqual(collection.UniqueKeyPolicy.UniqueKeys[0].Paths.Count, containerDeserSettings.UniqueKeyPolicy.UniqueKeys[0].Paths.Count);
            Assert.AreEqual(collection.UniqueKeyPolicy.UniqueKeys[0].Paths[0], containerDeserSettings.UniqueKeyPolicy.UniqueKeys[0].Paths[0]);

            Assert.AreEqual(cosmosContainerSettings.Id, collectionDeser.Id);
            Assert.AreEqual(cosmosContainerSettings.PartitionKeyPath, collectionDeser.PartitionKey.Paths[0]);
            Assert.AreEqual(cosmosContainerSettings.IndexingPolicy.Automatic, collectionDeser.IndexingPolicy.Automatic);
            Assert.AreEqual(cosmosContainerSettings.IndexingPolicy.IncludedPaths.Count, collectionDeser.IndexingPolicy.IncludedPaths.Count);
            Assert.AreEqual(cosmosContainerSettings.IndexingPolicy.IncludedPaths[0].Path, collectionDeser.IndexingPolicy.IncludedPaths[0].Path);
            Assert.AreEqual(cosmosContainerSettings.IndexingPolicy.IncludedPaths[0].Indexes.Count, collectionDeser.IndexingPolicy.IncludedPaths[0].Indexes.Count);
            Assert.AreEqual(cosmosContainerSettings.UniqueKeyPolicy.UniqueKeys.Count, collectionDeser.UniqueKeyPolicy.UniqueKeys.Count);
            Assert.AreEqual(cosmosContainerSettings.UniqueKeyPolicy.UniqueKeys[0].Paths.Count, collectionDeser.UniqueKeyPolicy.UniqueKeys[0].Paths.Count);
            Assert.AreEqual(cosmosContainerSettings.UniqueKeyPolicy.UniqueKeys[0].Paths[0], collectionDeser.UniqueKeyPolicy.UniqueKeys[0].Paths[0]);
        }
        public static async Task <IDocumentQueryExecutionContext> CreateDocumentQueryExecutionContextAsync(
            IDocumentQueryClient client,
            ResourceType resourceTypeEnum,
            Type resourceType,
            Expression expression,
            FeedOptions feedOptions,
            string resourceLink,
            bool isContinuationExpected,
            CancellationToken token,
            Guid correlatedActivityId)
        {
            ContainerProperties collection = null;

            if (resourceTypeEnum.IsCollectionChild())
            {
                CollectionCache collectionCache = await client.GetCollectionCacheAsync();

                using (
                    DocumentServiceRequest request = DocumentServiceRequest.Create(
                        OperationType.Query,
                        resourceTypeEnum,
                        resourceLink,
                        AuthorizationTokenType.Invalid)) //this request doesnt actually go to server
                {
                    collection = await collectionCache.ResolveCollectionAsync(request, token, NoOpTrace.Singleton);
                }

                if (feedOptions != null && feedOptions.PartitionKey != null && feedOptions.PartitionKey.Equals(Documents.PartitionKey.None))
                {
                    feedOptions.PartitionKey = Documents.PartitionKey.FromInternalKey(collection.GetNoneValue());
                }
            }

            DocumentQueryExecutionContextBase.InitParams constructorParams = new DocumentQueryExecutionContextBase.InitParams(
                client,
                resourceTypeEnum,
                resourceType,
                expression,
                feedOptions,
                resourceLink,
                false,
                correlatedActivityId);

            // For non-Windows platforms(like Linux and OSX) in .NET Core SDK, we cannot use ServiceInterop, so need to bypass in that case.
            // We are also now bypassing this for 32 bit host process running even on Windows as there are many 32 bit apps that will not work without this
            if (CustomTypeExtensions.ByPassQueryParsing())
            {
                // We create a ProxyDocumentQueryExecutionContext that will be initialized with DefaultDocumentQueryExecutionContext
                // which will be used to send the query to Gateway and on getting 400(bad request) with 1004(cross partition query not servable), we initialize it with
                // PipelinedDocumentQueryExecutionContext by providing the partition query execution info that's needed(which we get from the exception returned from Gateway).
                ProxyDocumentQueryExecutionContext proxyQueryExecutionContext =
                    ProxyDocumentQueryExecutionContext.Create(
                        client,
                        resourceTypeEnum,
                        resourceType,
                        expression,
                        feedOptions,
                        resourceLink,
                        token,
                        collection,
                        isContinuationExpected,
                        correlatedActivityId);

                return(proxyQueryExecutionContext);
            }

            DefaultDocumentQueryExecutionContext queryExecutionContext = await DefaultDocumentQueryExecutionContext.CreateAsync(
                constructorParams, isContinuationExpected, token);

            // If isContinuationExpected is false, we want to check if there are aggregates.
            if (
                resourceTypeEnum.IsCollectionChild() &&
                resourceTypeEnum.IsPartitioned() &&
                (feedOptions.EnableCrossPartitionQuery || !isContinuationExpected))
            {
                //todo:elasticcollections this may rely on information from collection cache which is outdated
                //if collection is deleted/created with same name.
                //need to make it not rely on information from collection cache.
                PartitionedQueryExecutionInfo partitionedQueryExecutionInfo = await queryExecutionContext.GetPartitionedQueryExecutionInfoAsync(
                    partitionKeyDefinition : collection.PartitionKey,
                    requireFormattableOrderByQuery : true,
                    isContinuationExpected : isContinuationExpected,
                    allowNonValueAggregateQuery : true,
                    hasLogicalPartitionKey : feedOptions.PartitionKey != null,
                    allowDCount : true,
                    cancellationToken : token);

                if (DocumentQueryExecutionContextFactory.ShouldCreateSpecializedDocumentQueryExecutionContext(
                        resourceTypeEnum,
                        feedOptions,
                        partitionedQueryExecutionInfo,
                        collection.PartitionKey,
                        isContinuationExpected))
                {
                    List <PartitionKeyRange> targetRanges = await GetTargetPartitionKeyRangesAsync(
                        queryExecutionContext,
                        partitionedQueryExecutionInfo,
                        collection,
                        feedOptions);

                    // Devnote this will get replace by the new v3 to v2 logic
                    throw new NotSupportedException("v2 query excution context is currently not supported.");
                }
            }

            return(queryExecutionContext);
        }
        public async Task ContainerContractTest()
        {
            ContainerProperties containerProperties = new ContainerProperties(Guid.NewGuid().ToString(), "/users")
            {
                IndexingPolicy = new IndexingPolicy()
                {
                    Automatic     = true,
                    IndexingMode  = IndexingMode.Consistent,
                    IncludedPaths = new Collection <IncludedPath>()
                    {
                        new IncludedPath()
                        {
                            Path = "/*"
                        }
                    },
                    ExcludedPaths = new Collection <ExcludedPath>()
                    {
                        new ExcludedPath()
                        {
                            Path = "/test/*"
                        }
                    },
                    CompositeIndexes = new Collection <Collection <CompositePath> >()
                    {
                        new Collection <CompositePath>()
                        {
                            new CompositePath()
                            {
                                Path  = "/address/city",
                                Order = CompositePathSortOrder.Ascending
                            },
                            new CompositePath()
                            {
                                Path  = "/address/zipcode",
                                Order = CompositePathSortOrder.Descending
                            }
                        }
                    },
                    SpatialIndexes = new Collection <SpatialPath>()
                    {
                        new SpatialPath()
                        {
                            Path         = "/address/spatial/*",
                            SpatialTypes = new Collection <SpatialType>()
                            {
                                SpatialType.LineString
                            }
                        }
                    }
                }
            };

            CosmosJsonDotNetSerializer serializer = new CosmosJsonDotNetSerializer();
            Stream stream = serializer.ToStream(containerProperties);
            ContainerProperties deserialziedTest = serializer.FromStream <ContainerProperties>(stream);

            ContainerResponse response = await this.database.CreateContainerAsync(containerProperties);

            Assert.IsNotNull(response);
            Assert.IsTrue(response.RequestCharge > 0);
            Assert.IsNotNull(response.Headers);
            Assert.IsNotNull(response.Headers.ActivityId);

            ContainerProperties responseProperties = response.Resource;

            Assert.IsNotNull(responseProperties.Id);
            Assert.IsNotNull(responseProperties.ResourceId);
            Assert.IsNotNull(responseProperties.ETag);
            Assert.IsTrue(responseProperties.LastModified.HasValue);

            Assert.IsTrue(responseProperties.LastModified.Value > new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc), responseProperties.LastModified.Value.ToString());

            Assert.AreEqual(1, responseProperties.IndexingPolicy.IncludedPaths.Count);
            IncludedPath includedPath = responseProperties.IndexingPolicy.IncludedPaths.First();

            Assert.AreEqual("/*", includedPath.Path);

            Assert.AreEqual("/test/*", responseProperties.IndexingPolicy.ExcludedPaths.First().Path);

            Assert.AreEqual(1, responseProperties.IndexingPolicy.CompositeIndexes.Count);
            Assert.AreEqual(2, responseProperties.IndexingPolicy.CompositeIndexes.First().Count);
            CompositePath compositePath = responseProperties.IndexingPolicy.CompositeIndexes.First().First();

            Assert.AreEqual("/address/city", compositePath.Path);
            Assert.AreEqual(CompositePathSortOrder.Ascending, compositePath.Order);

            Assert.AreEqual(1, responseProperties.IndexingPolicy.SpatialIndexes.Count);
            SpatialPath spatialPath = responseProperties.IndexingPolicy.SpatialIndexes.First();

            Assert.AreEqual("/address/spatial/*", spatialPath.Path);
            Assert.AreEqual(1, spatialPath.SpatialTypes.Count);
            Assert.AreEqual(SpatialType.LineString, spatialPath.SpatialTypes.First());
        }
        private async Task ValidateCollectionIndexProgressHeaders(CosmosClient client)
        {
            Cosmos.Database db = await client.CreateDatabaseAsync(Guid.NewGuid().ToString());

            try
            {
                PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition {
                    Paths = new System.Collections.ObjectModel.Collection <string>(new[] { "/id" }), Kind = PartitionKind.Hash
                };
                var lazyCollection = new ContainerProperties()
                {
                    Id = Guid.NewGuid().ToString(), PartitionKey = partitionKeyDefinition
                };
                lazyCollection.IndexingPolicy.IndexingMode = Cosmos.IndexingMode.Lazy;
                Container lazyContainer = await db.CreateContainerAsync(lazyCollection);

                var consistentCollection = new ContainerProperties()
                {
                    Id = Guid.NewGuid().ToString(), PartitionKey = partitionKeyDefinition
                };
                consistentCollection.IndexingPolicy.IndexingMode = Cosmos.IndexingMode.Consistent;
                Container consistentContainer = await db.CreateContainerAsync(consistentCollection);

                var noneIndexCollection = new ContainerProperties()
                {
                    Id = Guid.NewGuid().ToString(), PartitionKey = partitionKeyDefinition
                };
                noneIndexCollection.IndexingPolicy.Automatic    = false;
                noneIndexCollection.IndexingPolicy.IndexingMode = Cosmos.IndexingMode.None;
                Container noneIndexContainer = await db.CreateContainerAsync(noneIndexCollection);

                var doc = new Document()
                {
                    Id = Guid.NewGuid().ToString()
                };
                await lazyContainer.CreateItemAsync <Document>(doc);

                await consistentContainer.CreateItemAsync <Document>(doc);

                await noneIndexContainer.CreateItemAsync <Document>(doc);


                // Lazy-indexing collection.
                {
                    ContainerResponse collectionResponse = await lazyContainer.ReadAsync(requestOptions : new ContainerRequestOptions {
                        PopulateQuotaInfo = true
                    });

                    Assert.IsTrue(int.Parse(collectionResponse.Headers[HttpConstants.HttpHeaders.CollectionLazyIndexingProgress], CultureInfo.InvariantCulture) >= 0,
                                  "Expect lazy indexer progress when reading lazy collection.");
                    Assert.AreEqual(100, int.Parse(collectionResponse.Headers[HttpConstants.HttpHeaders.CollectionIndexTransformationProgress], CultureInfo.InvariantCulture),
                                    "Expect reindexer progress when reading lazy collection.");
                }

                // Consistent-indexing collection.
                {
                    ContainerResponse collectionResponse = await consistentContainer.ReadAsync(requestOptions : new ContainerRequestOptions {
                        PopulateQuotaInfo = true
                    });

                    Assert.IsFalse(collectionResponse.Headers.AllKeys().Contains(HttpConstants.HttpHeaders.CollectionLazyIndexingProgress),
                                   "No lazy indexer progress when reading consistent collection.");
                    Assert.AreEqual(100, int.Parse(collectionResponse.Headers[HttpConstants.HttpHeaders.CollectionIndexTransformationProgress], CultureInfo.InvariantCulture),
                                    "Expect reindexer progress when reading consistent collection.");
                }

                // None-indexing collection.
                {
                    ContainerResponse collectionResponse = await noneIndexContainer.ReadAsync(requestOptions : new ContainerRequestOptions {
                        PopulateQuotaInfo = true
                    });

                    Assert.IsFalse(collectionResponse.Headers.AllKeys().Contains(HttpConstants.HttpHeaders.CollectionLazyIndexingProgress),
                                   "No lazy indexer progress when reading none-index collection.");
                    Assert.AreEqual(100, int.Parse(collectionResponse.Headers[HttpConstants.HttpHeaders.CollectionIndexTransformationProgress], CultureInfo.InvariantCulture),
                                    "Expect reindexer progress when reading none-index collection.");
                }
            }
            finally
            {
                await db.DeleteAsync();
            }
        }
Example #10
0
        private async Task DataUpdateStepAsync(WaterfallStepContext stepContext, CancellationToken cancellationToken)
        {
            var orderData = await _orderDataAccessor.GetAsync(stepContext.Context, () => new OrderData(), cancellationToken);

            CosmosClient client = new CosmosClient(Startup.CosmosDbEndpoint, Startup.AuthKey);

            database = await client.CreateDatabaseIfNotExistsAsync(databaseId);

            ContainerProperties containerProperties = new ContainerProperties(containerId, partitionKeyPath: Startup.PartitionKey);

            // Create with a throughput of 1000 RU/s
            container = await database.CreateContainerIfNotExistsAsync(
                containerProperties,
                throughput : 1000);

            //orderNum 가져오기
            try
            {
                FeedIterator <DBdata> feedIterator = container.GetItemQueryIterator <DBdata>("SELECT top 1 * FROM c order by c._ts desc");
                {
                    while (feedIterator.HasMoreResults)
                    {
                        FeedResponse <DBdata> result = await feedIterator.ReadNextAsync();

                        foreach (var item in result)
                        {
                            orderData.OrderNum = Int32.Parse(item.id);
                        }
                    }
                }
            }
            catch (System.Exception e)
            {
                orderData.OrderNum = 0;
            }

            //ip
            IPHostEntry host   = Dns.GetHostEntry(Dns.GetHostName());
            string      ipAddr = string.Empty;

            for (int i = 0; i < host.AddressList.Length; i++)
            {
                if (host.AddressList[i].AddressFamily == AddressFamily.InterNetwork)
                {
                    ipAddr = host.AddressList[i].ToString();
                }
            }

            //Order 데이터 삽입
            foreach (Sandwich tempSand in orderData.Sandwiches)
            {
                string sJson = JsonConvert.SerializeObject(tempSand);

                var dbData = new DBdata {
                    id = $"{++orderData.OrderNum}", Contents = tempSand, ETag = "x", AccountNumber = ipAddr
                };

                await container.CreateItemAsync <DBdata>(dbData, new PartitionKey(dbData.AccountNumber));
            }

            //container 변경
            containerProperties = new ContainerProperties(countContainerId, partitionKeyPath: "/AccountNumber");
            // Create with a throughput of 1000 RU/s
            container = await database.CreateContainerIfNotExistsAsync(
                containerProperties,
                throughput : 1000);

            //Count 데이터 삽입
            foreach (Sandwich tempSand in orderData.Sandwiches)
            {
                var    CountId = 0;
                string sauce   = "";
                tempSand.Sauce.Sort();
                foreach (string temp in tempSand.Sauce)
                {
                    sauce += temp + " ";
                }

                //CountId 찾기
                try
                {
                    FeedIterator <DBcount> feedIterator = container.GetItemQueryIterator <DBcount>("SELECT top 1 * FROM c order by c._ts desc");
                    {
                        while (feedIterator.HasMoreResults)
                        {
                            FeedResponse <DBcount> result = await feedIterator.ReadNextAsync();

                            foreach (var item in result)
                            {
                                CountId = Int32.Parse(item.id) + 1;
                            }
                        }
                    }
                }
                catch (System.Exception e)
                {
                    CountId = 0;
                }

                try {
                    FeedIterator <DBcount> feedIterator = container.GetItemQueryIterator <DBcount>("SELECT * FROM c WHERE c.Sauce='" + sauce + "' and c.Bread ='" + tempSand.Bread + "' and c.Menu ='" + tempSand.Menu + "'");
                    {
                        if (feedIterator.HasMoreResults)
                        {
                            FeedResponse <DBcount> result = await feedIterator.ReadNextAsync();

                            DBcount res                 = result.First();
                            var     count               = res.Count + 1;
                            DBcount countData           = new DBcount(); countData.id = res.id; countData.Count = count; countData.Sauce = sauce; countData.Menu = tempSand.Menu; countData.ETag = "x"; countData.AccountNumber = "0"; countData.Bread = tempSand.Bread;
                            ItemResponse <DBcount> item = await container.DeleteItemAsync <DBcount>(partitionKey : new PartitionKey("0"), id : res.id);

                            await container.CreateItemAsync(countData, new PartitionKey("0"));
                        }
                    }
                }
                catch (System.Exception e)
                {
                    var countData = new DBcount {
                        id = $"{CountId}", Count = 1, Bread = $"{tempSand.Bread}", Sauce = sauce, Menu = $"{tempSand.Menu}", ETag = "x", AccountNumber = "0"
                    };
                    await container.CreateItemAsync <DBcount>(countData, new PartitionKey("0"));
                }
            }
        }
        public async Task CreateContainerIfNotExistsAsyncTest()
        {
            string containerName     = Guid.NewGuid().ToString();
            string partitionKeyPath1 = "/users";

            ContainerProperties settings          = new ContainerProperties(containerName, partitionKeyPath1);
            ContainerResponse   containerResponse = await this.cosmosDatabase.CreateContainerIfNotExistsAsync(settings);

            Assert.AreEqual(HttpStatusCode.Created, containerResponse.StatusCode);
            Assert.AreEqual(containerName, containerResponse.Resource.Id);
            Assert.AreEqual(partitionKeyPath1, containerResponse.Resource.PartitionKey.Paths.First());

            //Creating container with same partition key path
            containerResponse = await this.cosmosDatabase.CreateContainerIfNotExistsAsync(settings);

            Assert.AreEqual(HttpStatusCode.OK, containerResponse.StatusCode);
            Assert.AreEqual(containerName, containerResponse.Resource.Id);
            Assert.AreEqual(partitionKeyPath1, containerResponse.Resource.PartitionKey.Paths.First());

            //Creating container with different partition key path
            string partitionKeyPath2 = "/users2";

            try
            {
                settings          = new ContainerProperties(containerName, partitionKeyPath2);
                containerResponse = await this.cosmosDatabase.CreateContainerIfNotExistsAsync(settings);

                Assert.Fail("Should through ArgumentException on partition key path");
            }
            catch (ArgumentException ex)
            {
                Assert.AreEqual(nameof(settings.PartitionKey), ex.ParamName);
                Assert.IsTrue(ex.Message.Contains(string.Format(
                                                      ClientResources.PartitionKeyPathConflict,
                                                      partitionKeyPath2,
                                                      containerName,
                                                      partitionKeyPath1)));
            }

            containerResponse = await containerResponse.Container.DeleteContainerAsync();

            Assert.AreEqual(HttpStatusCode.NoContent, containerResponse.StatusCode);


            //Creating existing container with partition key having value for SystemKey
            //https://github.com/Azure/azure-cosmos-dotnet-v3/issues/623
            string v2ContainerName = "V2Container";
            PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition();

            partitionKeyDefinition.Paths.Add("/test");
            partitionKeyDefinition.IsSystemKey = false;
            ContainerProperties containerPropertiesWithSystemKey = new ContainerProperties()
            {
                Id           = v2ContainerName,
                PartitionKey = partitionKeyDefinition,
            };

            await this.cosmosDatabase.CreateContainerAsync(containerPropertiesWithSystemKey);

            ContainerProperties containerProperties = new ContainerProperties(v2ContainerName, "/test");

            containerResponse = await this.cosmosDatabase.CreateContainerIfNotExistsAsync(containerProperties);

            Assert.AreEqual(HttpStatusCode.OK, containerResponse.StatusCode);
            Assert.AreEqual(v2ContainerName, containerResponse.Resource.Id);
            Assert.AreEqual("/test", containerResponse.Resource.PartitionKey.Paths.First());

            containerResponse = await containerResponse.Container.DeleteContainerAsync();

            Assert.AreEqual(HttpStatusCode.NoContent, containerResponse.StatusCode);

            containerPropertiesWithSystemKey.PartitionKey.IsSystemKey = true;
            await this.cosmosDatabase.CreateContainerAsync(containerPropertiesWithSystemKey);

            containerProperties = new ContainerProperties(v2ContainerName, "/test");
            containerResponse   = await this.cosmosDatabase.CreateContainerIfNotExistsAsync(containerProperties);

            Assert.AreEqual(HttpStatusCode.OK, containerResponse.StatusCode);
            Assert.AreEqual(v2ContainerName, containerResponse.Resource.Id);
            Assert.AreEqual("/test", containerResponse.Resource.PartitionKey.Paths.First());

            containerResponse = await containerResponse.Container.DeleteContainerAsync();

            Assert.AreEqual(HttpStatusCode.NoContent, containerResponse.StatusCode);
        }
Example #12
0
        /// <summary>
        /// Creates a container with the current fluent definition.
        /// </summary>
        /// <param name="throughput">Desired throughput for the container expressed in Request Units per second.</param>
        /// <returns>An asynchronous Task representing the creation of a <see cref="Container"/> based on the Fluent definition.</returns>
        /// <remarks>
        /// <seealso href="https://docs.microsoft.com/azure/cosmos-db/request-units"/> for details on provision throughput.
        /// </remarks>
        public virtual async Task <ContainerResponse> CreateAsync(int?throughput = null)
        {
            ContainerProperties containerProperties = this.Build();

            return(await this.cosmosContainers.CreateContainerAsync(containerProperties, throughput));
        }
Example #13
0
        /// <summary>
        /// Resolves a request to a collection in a sticky manner.
        /// Unless request.ForceNameCacheRefresh is equal to true, it will return the same collection.
        /// </summary>
        /// <param name="request">Request to resolve.</param>
        /// <param name="cancellationToken">Cancellation token.</param>
        /// <param name="trace">The trace.</param>
        /// <returns>Instance of <see cref="ContainerProperties"/>.</returns>
        public virtual async Task <ContainerProperties> ResolveCollectionAsync(
            DocumentServiceRequest request,
            CancellationToken cancellationToken,
            ITrace trace)
        {
            IClientSideRequestStatistics clientSideRequestStatistics = request.RequestContext?.ClientRequestStatistics;

            if (request.IsNameBased)
            {
                if (request.ForceNameCacheRefresh)
                {
                    await this.RefreshAsync(request, trace, clientSideRequestStatistics, cancellationToken);

                    request.ForceNameCacheRefresh = false;
                }

                ContainerProperties collectionInfo = await this.ResolveByPartitionKeyRangeIdentityAsync(
                    request.Headers[HttpConstants.HttpHeaders.Version],
                    request.PartitionKeyRangeIdentity,
                    trace,
                    clientSideRequestStatistics,
                    cancellationToken);

                if (collectionInfo != null)
                {
                    return(collectionInfo);
                }

                if (request.RequestContext.ResolvedCollectionRid == null)
                {
                    collectionInfo =
                        await this.ResolveByNameAsync(
                            apiVersion : request.Headers[HttpConstants.HttpHeaders.Version],
                            resourceAddress : request.ResourceAddress,
                            forceRefesh : false,
                            trace : trace,
                            clientSideRequestStatistics : clientSideRequestStatistics,
                            cancellationToken : cancellationToken);

                    if (collectionInfo != null)
                    {
                        DefaultTrace.TraceVerbose(
                            "Mapped resourceName {0} to resourceId {1}. '{2}'",
                            request.ResourceAddress,
                            collectionInfo.ResourceId,
                            System.Diagnostics.Trace.CorrelationManager.ActivityId);

                        request.ResourceId = collectionInfo.ResourceId;
                        request.RequestContext.ResolvedCollectionRid = collectionInfo.ResourceId;
                    }
                    else
                    {
                        DefaultTrace.TraceVerbose(
                            "Collection with resourceName {0} not found. '{1}'",
                            request.ResourceAddress,
                            System.Diagnostics.Trace.CorrelationManager.ActivityId);
                    }

                    return(collectionInfo);
                }
                else
                {
                    return(await this.ResolveByRidAsync(request.Headers[HttpConstants.HttpHeaders.Version], request.RequestContext.ResolvedCollectionRid, trace, clientSideRequestStatistics, cancellationToken));
                }
            }
            else
            {
                return(await this.ResolveByPartitionKeyRangeIdentityAsync(request.Headers[HttpConstants.HttpHeaders.Version], request.PartitionKeyRangeIdentity, trace, clientSideRequestStatistics, cancellationToken) ??
                       await this.ResolveByRidAsync(request.Headers[HttpConstants.HttpHeaders.Version], request.ResourceAddress, trace, clientSideRequestStatistics, cancellationToken));
            }
        }
Example #14
0
        public async Task InsertWithUniqueIndex()
        {
            ContainerProperties collectionSpec = new ContainerProperties
            {
                Id = "InsertWithUniqueIndexConstraint_" + Guid.NewGuid(),
                PartitionKeyPath = defaultPartitionKeyDefinition,
                UniqueKeyPolicy  = new UniqueKeyPolicy
                {
                    UniqueKeys = new Collection <UniqueKey> {
                        new UniqueKey {
                            Paths = new Collection <string> {
                                "/name", "/address"
                            }
                        }
                    }
                },
                IndexingPolicy = new IndexingPolicy
                {
                    IndexingMode  = IndexingMode.Consistent,
                    IncludedPaths = new Collection <IncludedPath> {
                        new IncludedPath {
                            Path = "/name/?", Indexes = new Collection <Index> {
                                new HashIndex(DataType.String, 7)
                            }
                        },
                        new IncludedPath {
                            Path = "/address/?", Indexes = new Collection <Index> {
                                new HashIndex(DataType.String, 7)
                            }
                        },
                    },
                    ExcludedPaths = new Collection <ExcludedPath> {
                        new ExcludedPath {
                            Path = "/*"
                        }
                    }
                }
            };

            Func <Container, Task> testFunction = async(Container container) =>
            {
                dynamic doc1          = new { id = Guid.NewGuid().ToString(), name = "Alexander Pushkin", pk = "test", address = "Russia 630090" };
                dynamic doc1Conflict  = new { id = Guid.NewGuid().ToString(), name = doc1.name, pk = doc1.pk, address = doc1.address };
                dynamic doc1Conflict2 = new { id = Guid.NewGuid().ToString(), name = doc1.name, pk = doc1.pk, address = doc1.address };
                dynamic doc2          = new { id = Guid.NewGuid().ToString(), name = "Alexander Pushkin", pk = "test", address = "Russia 640000" };
                dynamic doc3          = new { id = Guid.NewGuid().ToString(), name = "Mihkail Lermontov", pk = "test", address = "Russia 630090" };

                await container.CreateItemAsync <dynamic>(doc1);

                try
                {
                    await container.CreateItemAsync <dynamic>(doc1Conflict);

                    Assert.Fail("Did not throw due to unique constraint (create)");
                }
                catch (CosmosException ex)
                {
                    Assert.AreEqual(HttpStatusCode.Conflict, ex.StatusCode, $"Expected:Conflict, Actual:{ex.StatusCode}; Exception:ex.ToString()");
                }

                try
                {
                    await container.UpsertItemAsync <dynamic>(doc1Conflict2);

                    Assert.Fail("Did not throw due to unique constraint (upsert)");
                }
                catch (CosmosException ex)
                {
                    // Search for: L"For upsert insert, if it failed with E_RESOURCE_ALREADY_EXISTS, return E_CONCURRENCY_VIOLATION so that client will retry"
                    Assert.AreEqual(HttpStatusCode.Conflict, ex.StatusCode, $"Expected:Conflict, Actual:{ex.StatusCode}; Exception:ex.ToString()");
                }

                await container.CreateItemAsync <dynamic>(doc2);

                await container.CreateItemAsync <dynamic>(doc3);
            };

            await this.TestForEachClient(collectionSpec, testFunction, "InsertWithUniqueIndex");
        }
        public void ValidateResponseFactoryJsonSerializer()
        {
            ResponseMessage databaseResponse  = this.CreateResponse();
            ResponseMessage containerResponse = this.CreateResponse();
            ResponseMessage storedProcedureExecuteResponse = this.CreateResponse();
            ResponseMessage storedProcedureResponse        = this.CreateResponse();
            ResponseMessage triggerResponse = this.CreateResponse();
            ResponseMessage udfResponse     = this.CreateResponse();
            ResponseMessage itemResponse    = this.CreateResponse();


            Mock <CosmosSerializer>       mockUserJsonSerializer = new Mock <CosmosSerializer>();
            CosmosSerializerCore          serializerCore         = new CosmosSerializerCore(mockUserJsonSerializer.Object);
            CosmosResponseFactoryInternal cosmosResponseFactory  = new CosmosResponseFactoryCore(
                serializerCore);

            // Test the user specified response
            mockUserJsonSerializer.Setup(x => x.FromStream <ToDoActivity>(itemResponse.Content)).Callback <Stream>(input => input.Dispose()).Returns(new ToDoActivity());
            mockUserJsonSerializer.Setup(x => x.FromStream <ToDoActivity>(storedProcedureExecuteResponse.Content)).Callback <Stream>(input => input.Dispose()).Returns(new ToDoActivity());

            // Verify all the user types use the user specified version
            cosmosResponseFactory.CreateItemResponse <ToDoActivity>(itemResponse);
            cosmosResponseFactory.CreateStoredProcedureExecuteResponse <ToDoActivity>(storedProcedureExecuteResponse);

            // Throw if the setups were not called
            mockUserJsonSerializer.VerifyAll();

            // Test read feed scenario
            ResponseMessage readFeedResponse = this.CreateReadFeedResponse();

            mockUserJsonSerializer.Setup(x => x.FromStream <ToDoActivity[]>(It.IsAny <Stream>()))
            .Callback <Stream>(input => input.Dispose())
            .Returns(new ToDoActivity[] { new ToDoActivity() });
            FeedResponse <ToDoActivity> feedResponse = cosmosResponseFactory.CreateItemFeedResponse <ToDoActivity>(readFeedResponse);

            foreach (ToDoActivity toDoActivity in feedResponse)
            {
                Assert.IsNotNull(toDoActivity);
            }

            mockUserJsonSerializer.VerifyAll();

            ResponseMessage changeFeedResponseMessage = this.CreateChangeFeedNotModifiedResponse();

            try
            {
                cosmosResponseFactory.CreateItemFeedResponse <ToDoActivity>(changeFeedResponseMessage);
                Assert.Fail();
            }
            catch (CosmosException cosmosException)
            {
                Assert.AreEqual(HttpStatusCode.NotModified, cosmosException.StatusCode);
            }

            ResponseMessage queryResponse = this.CreateReadFeedResponse();

            mockUserJsonSerializer.Setup(x => x.FromStream <ToDoActivity[]>(It.IsAny <Stream>())).Callback <Stream>(input => input.Dispose()).Returns(new ToDoActivity[] { new ToDoActivity() });
            FeedResponse <ToDoActivity> queryFeedResponse = cosmosResponseFactory.CreateItemFeedResponse <ToDoActivity>(queryResponse);

            foreach (ToDoActivity toDoActivity in queryFeedResponse)
            {
                Assert.IsNotNull(toDoActivity);
            }

            mockUserJsonSerializer.VerifyAll();

            // Test the system specified response
            ContainerProperties containerSettings = new ContainerProperties("mockId", "/pk");
            DatabaseProperties  databaseSettings  = new DatabaseProperties()
            {
                Id = "mock"
            };

            StoredProcedureProperties cosmosStoredProcedureSettings = new StoredProcedureProperties()
            {
                Id = "mock"
            };

            TriggerProperties cosmosTriggerSettings = new TriggerProperties()
            {
                Id = "mock"
            };

            UserDefinedFunctionProperties cosmosUserDefinedFunctionSettings = new UserDefinedFunctionProperties()
            {
                Id = "mock"
            };

            Mock <Container> mockContainer = new Mock <Container>();
            Mock <Database>  mockDatabase  = new Mock <Database>();

            // Verify all the system types that should always use default
            cosmosResponseFactory.CreateContainerResponse(mockContainer.Object, containerResponse);
            cosmosResponseFactory.CreateDatabaseResponse(mockDatabase.Object, databaseResponse);
            cosmosResponseFactory.CreateStoredProcedureResponse(storedProcedureResponse);
            cosmosResponseFactory.CreateTriggerResponse(triggerResponse);
            cosmosResponseFactory.CreateUserDefinedFunctionResponse(udfResponse);
        }
        public async Task ContainerMigrationTest()
        {
            string containerName = "MigrationIndexTest";

            Documents.Index index1 = new Documents.RangeIndex(Documents.DataType.String, -1);
            Documents.Index index2 = new Documents.RangeIndex(Documents.DataType.Number, -1);
            Documents.DocumentCollection documentCollection = new Microsoft.Azure.Documents.DocumentCollection()
            {
                Id             = containerName,
                IndexingPolicy = new Documents.IndexingPolicy()
                {
                    IncludedPaths = new Collection <Documents.IncludedPath>()
                    {
                        new Documents.IncludedPath()
                        {
                            Path    = "/*",
                            Indexes = new Collection <Documents.Index>()
                            {
                                index1,
                                index2
                            }
                        }
                    }
                }
            };

            Documents.DocumentCollection createResponse = await NonPartitionedContainerHelper.CreateNonPartitionedContainer(this.database, documentCollection);

            // Verify the collection was created with deprecated Index objects
            Assert.AreEqual(2, createResponse.IndexingPolicy.IncludedPaths.First().Indexes.Count);
            Documents.Index createIndex = createResponse.IndexingPolicy.IncludedPaths.First().Indexes.First();
            Assert.AreEqual(index1.Kind, createIndex.Kind);

            // Verify v3 can add composite indexes and update the container
            Container           container           = this.database.GetContainer(containerName);
            ContainerProperties containerProperties = await container.ReadContainerAsync();

            string cPath0 = "/address/city";
            string cPath1 = "/address/state";

            containerProperties.IndexingPolicy.CompositeIndexes.Add(new Collection <CompositePath>()
            {
                new CompositePath()
                {
                    Path  = cPath0,
                    Order = CompositePathSortOrder.Descending
                },
                new CompositePath()
                {
                    Path  = cPath1,
                    Order = CompositePathSortOrder.Ascending
                }
            });

            containerProperties.IndexingPolicy.SpatialIndexes.Add(
                new SpatialPath()
            {
                Path         = "/address/test/*",
                SpatialTypes = new Collection <SpatialType>()
                {
                    SpatialType.Point
                }
            });

            ContainerProperties propertiesAfterReplace = await container.ReplaceContainerAsync(containerProperties);

            Assert.AreEqual(0, propertiesAfterReplace.IndexingPolicy.IncludedPaths.First().Indexes.Count);
            Assert.AreEqual(1, propertiesAfterReplace.IndexingPolicy.CompositeIndexes.Count);
            Collection <CompositePath> compositePaths = propertiesAfterReplace.IndexingPolicy.CompositeIndexes.First();

            Assert.AreEqual(2, compositePaths.Count);
            CompositePath compositePath0 = compositePaths.ElementAt(0);
            CompositePath compositePath1 = compositePaths.ElementAt(1);

            Assert.IsTrue(string.Equals(cPath0, compositePath0.Path) || string.Equals(cPath1, compositePath0.Path));
            Assert.IsTrue(string.Equals(cPath0, compositePath1.Path) || string.Equals(cPath1, compositePath1.Path));

            Assert.AreEqual(1, propertiesAfterReplace.IndexingPolicy.SpatialIndexes.Count);
            Assert.AreEqual("/address/test/*", propertiesAfterReplace.IndexingPolicy.SpatialIndexes.First().Path);
        }
        public async Task NoPartitionedCreateFail()
        {
            string containerName = Guid.NewGuid().ToString();

            try
            {
                new ContainerProperties(id: containerName, partitionKeyPath: null);
                Assert.Fail("Create should throw null ref exception");
            }
            catch (ArgumentNullException ae)
            {
                Assert.IsNotNull(ae);
            }

            try
            {
                new ContainerProperties(id: containerName, partitionKeyDefinition: null);
                Assert.Fail("Create should throw null ref exception");
            }
            catch (ArgumentNullException ae)
            {
                Assert.IsNotNull(ae);
            }

            ContainerProperties settings = new ContainerProperties()
            {
                Id = containerName
            };

            try
            {
                ContainerResponse containerResponse = await this.cosmosDatabase.CreateContainerAsync(settings);

                Assert.Fail("Create should throw null ref exception");
            }
            catch (ArgumentNullException ae)
            {
                Assert.IsNotNull(ae);
            }

            try
            {
                ContainerResponse containerResponse = await this.cosmosDatabase.CreateContainerIfNotExistsAsync(settings);

                Assert.Fail("Create should throw null ref exception");
            }
            catch (ArgumentNullException ae)
            {
                Assert.IsNotNull(ae);
            }

            try
            {
                ContainerResponse containerResponse = await this.cosmosDatabase.CreateContainerAsync(id : containerName, partitionKeyPath : null);

                Assert.Fail("Create should throw null ref exception");
            }
            catch (ArgumentNullException ae)
            {
                Assert.IsNotNull(ae);
            }

            try
            {
                ContainerResponse containerResponse = await this.cosmosDatabase.CreateContainerIfNotExistsAsync(id : containerName, partitionKeyPath : null);

                Assert.Fail("Create should throw null ref exception");
            }
            catch (ArgumentNullException ae)
            {
                Assert.IsNotNull(ae);
            }
        }
        public DefaultCosmosContainerProvider(
            ICosmosClientProvider cosmosClientProvider,
            ICosmosPartitionKeyPathProvider cosmosPartitionKeyPathProvider,
            IOptions <RepositoryOptions> options,
            ILogger <DefaultCosmosContainerProvider <TItem> > logger)
        {
            _cosmosClientProvider = cosmosClientProvider
                                    ?? throw new ArgumentNullException(
                                              nameof(cosmosClientProvider), "Cosmos client provider is required.");

            _cosmosPartitionKeyPathProvider = cosmosPartitionKeyPathProvider
                                              ?? throw new ArgumentNullException(
                                                        nameof(cosmosPartitionKeyPathProvider), "Cosmos partition key name provider is required.");

            _options = options?.Value
                       ?? throw new ArgumentNullException(
                                 nameof(options), "Repository options are required.");

            if (_options.CosmosConnectionString is null)
            {
                throw new ArgumentNullException($"The {nameof(_options.CosmosConnectionString)} is required.");
            }
            if (_options.DatabaseId is null)
            {
                throw new ArgumentNullException($"The {nameof(_options.DatabaseId)} is required.");
            }
            if (_options.ContainerId is null)
            {
                throw new ArgumentNullException($"The {nameof(_options.ContainerId)} is required.");
            }
            if (logger is null)
            {
                throw new ArgumentNullException($"The {nameof(logger)} is required.");
            }

            _logger        = logger;
            _lazyContainer = new Lazy <Task <Container> >(async() =>
            {
                try
                {
                    Database database =
                        await _cosmosClientProvider.UseClientAsync(
                            client => client.CreateDatabaseIfNotExistsAsync(_options.DatabaseId));

                    ContainerProperties containerProperties = new ContainerProperties
                    {
                        Id = _options.ContainerPerItemType ? typeof(TItem).Name : _options.ContainerId,
                        PartitionKeyPath = _cosmosPartitionKeyPathProvider.GetPartitionKeyPath <TItem>()
                    };

                    Container container =
                        await database.CreateContainerIfNotExistsAsync(
                            containerProperties);

                    return(container);
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex.Message, ex);

                    throw;
                }
            });
        }
        public async Task TimeToLivePropertyPath()
        {
            string containerName    = Guid.NewGuid().ToString();
            string partitionKeyPath = "/user";
            int    timeToLivetimeToLiveInSeconds = 10;
            ContainerProperties setting          = new ContainerProperties()
            {
                Id           = containerName,
                PartitionKey = new PartitionKeyDefinition()
                {
                    Paths = new Collection <string> {
                        partitionKeyPath
                    }, Kind = PartitionKind.Hash
                },
                TimeToLivePropertyPath = "/creationDate",
            };

            ContainerResponse containerResponse = null;

            try
            {
                containerResponse = await this.cosmosDatabase.CreateContainerIfNotExistsAsync(setting);

                Assert.Fail("CreateColleciton with TtlPropertyPath and with no DefaultTimeToLive should have failed.");
            }
            catch (CosmosException exeption)
            {
                // expected because DefaultTimeToLive was not specified
                Assert.AreEqual(HttpStatusCode.BadRequest, exeption.StatusCode);
            }

            // Verify the container content.
            setting.DefaultTimeToLive = timeToLivetimeToLiveInSeconds;
            containerResponse         = await this.cosmosDatabase.CreateContainerIfNotExistsAsync(setting);

            Container container = containerResponse;

            Assert.AreEqual(timeToLivetimeToLiveInSeconds, containerResponse.Resource.DefaultTimeToLive);
            Assert.AreEqual("/creationDate", containerResponse.Resource.TimeToLivePropertyPath);

            //verify removing the ttl property path
            setting.TimeToLivePropertyPath = null;
            containerResponse = await container.ReplaceContainerAsync(setting);

            container = containerResponse;
            Assert.AreEqual(timeToLivetimeToLiveInSeconds, containerResponse.Resource.DefaultTimeToLive);
            Assert.IsNull(containerResponse.Resource.TimeToLivePropertyPath);

            //adding back the ttl property path
            setting.TimeToLivePropertyPath = "/creationDate";
            containerResponse = await container.ReplaceContainerAsync(setting);

            container = containerResponse;
            Assert.AreEqual(containerResponse.Resource.TimeToLivePropertyPath, "/creationDate");

            //Creating an item and reading before expiration
            var payload = new { id = "testId", user = "******", creationDate = ToEpoch(DateTime.UtcNow) };
            ItemResponse <dynamic> createItemResponse = await container.CreateItemAsync <dynamic>(payload);

            Assert.IsNotNull(createItemResponse.Resource);
            Assert.AreEqual(createItemResponse.StatusCode, HttpStatusCode.Created);
            ItemResponse <dynamic> readItemResponse = await container.ReadItemAsync <dynamic>(payload.id, new Cosmos.PartitionKey(payload.user));

            Assert.IsNotNull(readItemResponse.Resource);
            Assert.AreEqual(readItemResponse.StatusCode, HttpStatusCode.OK);

            containerResponse = await container.DeleteContainerAsync();

            Assert.AreEqual(HttpStatusCode.NoContent, containerResponse.StatusCode);
        }
        public override Task <ResponseMessage> ReplaceContainerStreamAsync(ContainerProperties containerProperties, ContainerRequestOptions requestOptions = null, CancellationToken cancellationToken = default)
        {
            var returnValue = new ResponseMessage();

            return(Task.FromResult(returnValue));
        }
        private void Init()
        {
            this.collectionCache = new Mock <ClientCollectionCache>(new SessionContainer("testhost"), new ServerStoreModel(null), null, null);
            const string pkPath = "/pk";

            this.collectionCache.Setup
                (m =>
                m.ResolveCollectionAsync(
                    It.IsAny <DocumentServiceRequest>(),
                    It.IsAny <CancellationToken>()
                    )
                ).Returns(() =>
            {
                ContainerProperties cosmosContainerSetting = ContainerProperties.CreateWithResourceId("test");
                cosmosContainerSetting.PartitionKey        = new PartitionKeyDefinition()
                {
                    Kind  = PartitionKind.Hash,
                    Paths = new Collection <string>()
                    {
                        pkPath
                    }
                };

                return(Task.FromResult(cosmosContainerSetting));
            });
            this.collectionCache.Setup
                (m =>
                m.ResolveByNameAsync(
                    It.IsAny <string>(),
                    It.IsAny <string>(),
                    It.IsAny <CancellationToken>()
                    )
                ).Returns(() => {
                ContainerProperties containerSettings = ContainerProperties.CreateWithResourceId("test");
                containerSettings.PartitionKey.Paths  = new Collection <string>()
                {
                    pkPath
                };
                return(Task.FromResult(containerSettings));
            });

            this.collectionCache.Setup
                (m =>
                m.ResolveByNameAsync(
                    It.IsAny <string>(),
                    It.IsAny <string>(),
                    It.IsAny <CancellationToken>()
                    )
                ).Returns(() =>
            {
                ContainerProperties cosmosContainerSetting = ContainerProperties.CreateWithResourceId("test");
                cosmosContainerSetting.PartitionKey        = new PartitionKeyDefinition()
                {
                    Kind  = PartitionKind.Hash,
                    Paths = new Collection <string>()
                    {
                        pkPath
                    }
                };

                return(Task.FromResult(cosmosContainerSetting));
            });

            this.partitionKeyRangeCache = new Mock <PartitionKeyRangeCache>(null, null, null);
            this.partitionKeyRangeCache.Setup(
                m => m.TryLookupAsync(
                    It.IsAny <string>(),
                    It.IsAny <CollectionRoutingMap>(),
                    It.IsAny <DocumentServiceRequest>(),
                    It.IsAny <CancellationToken>()
                    )
                ).Returns(Task.FromResult <CollectionRoutingMap>(null));
            this.partitionKeyRangeCache.Setup(
                m => m.TryGetOverlappingRangesAsync(
                    It.IsAny <string>(),
                    It.IsAny <Documents.Routing.Range <string> >(),
                    It.IsAny <bool>()
                    )
                ).Returns((string collectionRid, Documents.Routing.Range <string> range, bool forceRefresh) =>
            {
                return(Task.FromResult <IReadOnlyList <PartitionKeyRange> >(this.ResolveOverlapingPartitionKeyRanges(collectionRid, range, forceRefresh)));
            });

            this.globalEndpointManager = new Mock <GlobalEndpointManager>(this, new ConnectionPolicy());

            SessionContainer sessionContainer = new SessionContainer(this.ServiceEndpoint.Host);

            this.sessionContainer = sessionContainer;
        }
Example #22
0
        public async Task ContainerV2CompatTest()
        {
            string             containerId        = "SerializeContainerTest";
            DocumentCollection documentCollection = new DocumentCollection()
            {
                Id           = containerId,
                PartitionKey = new PartitionKeyDefinition()
                {
                    Paths = new Collection <string>()
                    {
                        "/pkPath"
                    }
                },
                IndexingPolicy = new IndexingPolicy()
                {
                    IncludedPaths = new Collection <IncludedPath>()
                    {
                        new IncludedPath()
                        {
                            Path = "/*"
                        }
                    },
                    CompositeIndexes = new Collection <Collection <CompositePath> >()
                    {
                        new Collection <CompositePath>()
                        {
                            new CompositePath()
                            {
                                Path  = "/address/test/*",
                                Order = CompositePathSortOrder.Ascending
                            },
                            new CompositePath()
                            {
                                Path  = "/address/test2/*",
                                Order = CompositePathSortOrder.Ascending
                            }
                        }
                    },
                    SpatialIndexes = new Collection <SpatialSpec>()
                    {
                        new SpatialSpec()
                        {
                            Path         = "/name/first/*",
                            SpatialTypes = new Collection <SpatialType>()
                            {
                                SpatialType.LineString
                            }
                        }
                    }
                },
            };


            string documentJsonString = null;

            using (MemoryStream memoryStream = new MemoryStream())
            {
                documentCollection.SaveTo(memoryStream);
                memoryStream.Position = 0;
                using (StreamReader sr = new StreamReader(memoryStream))
                {
                    documentJsonString = await sr.ReadToEndAsync();
                }
            }

            Assert.IsNotNull(documentJsonString);

            string cosmosJsonString = null;

            using (MemoryStream memoryStream = new MemoryStream())
            {
                documentCollection.SaveTo(memoryStream);
                memoryStream.Position = 0;

                CosmosJsonDotNetSerializer cosmosSerializer    = new CosmosJsonDotNetSerializer();
                ContainerProperties        containerProperties = cosmosSerializer.FromStream <ContainerProperties>(memoryStream);

                Assert.IsNotNull(containerProperties);
                Assert.AreEqual(containerId, containerProperties.Id);

                using (Stream stream = cosmosSerializer.ToStream <ContainerProperties>(containerProperties))
                {
                    using (StreamReader sr = new StreamReader(stream))
                    {
                        cosmosJsonString = await sr.ReadToEndAsync();
                    }
                }
            }

            JObject jObjectDocumentCollection = JObject.Parse(documentJsonString);
            JObject jObjectContainer          = JObject.Parse(cosmosJsonString);

            Assert.IsTrue(JToken.DeepEquals(jObjectDocumentCollection, jObjectContainer));
        }
        public async Task ValidateResponseFactoryJsonSerializer()
        {
            ResponseMessage databaseResponse  = this.CreateResponse();
            ResponseMessage containerResponse = this.CreateResponse();
            ResponseMessage storedProcedureExecuteResponse = this.CreateResponse();
            ResponseMessage storedProcedureResponse        = this.CreateResponse();
            ResponseMessage triggerResponse = this.CreateResponse();
            ResponseMessage udfResponse     = this.CreateResponse();
            ResponseMessage itemResponse    = this.CreateResponse();
            ResponseMessage feedResponse    = this.CreateResponse();

            Mock <CosmosSerializer> mockUserJsonSerializer    = new Mock <CosmosSerializer>();
            Mock <CosmosSerializer> mockDefaultJsonSerializer = new Mock <CosmosSerializer>();
            CosmosResponseFactory   cosmosResponseFactory     = new CosmosResponseFactory(
                defaultJsonSerializer: mockDefaultJsonSerializer.Object,
                userJsonSerializer: mockUserJsonSerializer.Object);

            // Test the user specified response
            mockUserJsonSerializer.Setup(x => x.FromStream <ToDoActivity>(itemResponse.Content)).Returns(new ToDoActivity());
            mockUserJsonSerializer.Setup(x => x.FromStream <ToDoActivity>(storedProcedureExecuteResponse.Content)).Returns(new ToDoActivity());
            mockUserJsonSerializer.Setup(x => x.FromStream <CosmosFeedResponseUtil <ToDoActivity> >(feedResponse.Content)).Returns(new CosmosFeedResponseUtil <ToDoActivity>()
            {
                Data = new Collection <ToDoActivity>()
            });

            // Verify all the user types use the user specified version
            await cosmosResponseFactory.CreateItemResponseAsync <ToDoActivity>(Task.FromResult(itemResponse));

            await cosmosResponseFactory.CreateStoredProcedureExecuteResponseAsync <ToDoActivity>(Task.FromResult(storedProcedureExecuteResponse));

            cosmosResponseFactory.CreateQueryFeedResponse <ToDoActivity>(feedResponse);

            // Throw if the setups were not called
            mockUserJsonSerializer.VerifyAll();

            // Test the system specified response
            ContainerProperties containerSettings = new ContainerProperties("mockId", "/pk");
            DatabaseProperties  databaseSettings  = new DatabaseProperties()
            {
                Id = "mock"
            };

            StoredProcedureProperties cosmosStoredProcedureSettings = new StoredProcedureProperties()
            {
                Id = "mock"
            };

            TriggerProperties cosmosTriggerSettings = new TriggerProperties()
            {
                Id = "mock"
            };

            UserDefinedFunctionProperties cosmosUserDefinedFunctionSettings = new UserDefinedFunctionProperties()
            {
                Id = "mock"
            };

            mockDefaultJsonSerializer.Setup(x => x.FromStream <DatabaseProperties>(databaseResponse.Content)).Returns(databaseSettings);
            mockDefaultJsonSerializer.Setup(x => x.FromStream <ContainerProperties>(containerResponse.Content)).Returns(containerSettings);
            mockDefaultJsonSerializer.Setup(x => x.FromStream <StoredProcedureProperties>(storedProcedureResponse.Content)).Returns(cosmosStoredProcedureSettings);
            mockDefaultJsonSerializer.Setup(x => x.FromStream <TriggerProperties>(triggerResponse.Content)).Returns(cosmosTriggerSettings);
            mockDefaultJsonSerializer.Setup(x => x.FromStream <UserDefinedFunctionProperties>(udfResponse.Content)).Returns(cosmosUserDefinedFunctionSettings);

            Mock <Container> mockContainer = new Mock <Container>();
            Mock <Database>  mockDatabase  = new Mock <Database>();

            // Verify all the system types that should always use default
            await cosmosResponseFactory.CreateContainerResponseAsync(mockContainer.Object, Task.FromResult(containerResponse));

            await cosmosResponseFactory.CreateDatabaseResponseAsync(mockDatabase.Object, Task.FromResult(databaseResponse));

            await cosmosResponseFactory.CreateStoredProcedureResponseAsync(Task.FromResult(storedProcedureResponse));

            await cosmosResponseFactory.CreateTriggerResponseAsync(Task.FromResult(triggerResponse));

            await cosmosResponseFactory.CreateUserDefinedFunctionResponseAsync(Task.FromResult(udfResponse));

            // Throw if the setups were not called
            mockDefaultJsonSerializer.VerifyAll();
        }
Example #24
0
        private async Task <Tuple <PartitionRoutingHelper.ResolvedRangeInfo, IReadOnlyList <Range <string> > > > TryGetTargetPartitionKeyRangeAsync(
            DocumentServiceRequest request,
            ContainerProperties collection,
            QueryPartitionProvider queryPartitionProvider,
            IRoutingMapProvider routingMapProvider,
            Range <string> rangeFromContinuationToken,
            List <CompositeContinuationToken> suppliedTokens)
        {
            string version = request.Headers[HttpConstants.HttpHeaders.Version];

            version = string.IsNullOrEmpty(version) ? HttpConstants.Versions.CurrentVersion : version;

            bool enableCrossPartitionQuery = false;

            string enableCrossPartitionQueryHeader = request.Headers[HttpConstants.HttpHeaders.EnableCrossPartitionQuery];

            if (enableCrossPartitionQueryHeader != null)
            {
                if (!bool.TryParse(enableCrossPartitionQueryHeader, out enableCrossPartitionQuery))
                {
                    throw new BadRequestException(
                              string.Format(
                                  CultureInfo.InvariantCulture,
                                  RMResources.InvalidHeaderValue,
                                  enableCrossPartitionQueryHeader,
                                  HttpConstants.HttpHeaders.EnableCrossPartitionQuery));
                }
            }

            IReadOnlyList <Range <string> > providedRanges;

            if (!this.providedRangesCache.TryGetValue(collection.ResourceId, out providedRanges))
            {
                if (this.ShouldExecuteQueryRequest)
                {
                    FeedOptions            feedOptions = this.GetFeedOptions(null);
                    PartitionKeyDefinition partitionKeyDefinition;
                    if ((feedOptions.Properties != null) && feedOptions.Properties.TryGetValue(
                            DefaultDocumentQueryExecutionContext.InternalPartitionKeyDefinitionProperty,
                            out object partitionKeyDefinitionObject))
                    {
                        if (partitionKeyDefinitionObject is PartitionKeyDefinition definition)
                        {
                            partitionKeyDefinition = definition;
                        }
                        else
                        {
                            throw new ArgumentException(
                                      "partitionkeydefinition has invalid type",
                                      nameof(partitionKeyDefinitionObject));
                        }
                    }
                    else
                    {
                        partitionKeyDefinition = collection.PartitionKey;
                    }

                    providedRanges = PartitionRoutingHelper.GetProvidedPartitionKeyRanges(
                        querySpecJsonString: JsonConvert.SerializeObject(this.QuerySpec),
                        enableCrossPartitionQuery: enableCrossPartitionQuery,
                        parallelizeCrossPartitionQuery: false,
                        isContinuationExpected: this.isContinuationExpected,
                        hasLogicalPartitionKey: false,
                        allowDCount: false,
                        allowNonValueAggregates: false,
                        useSystemPrefix: false,
                        partitionKeyDefinition: partitionKeyDefinition,
                        queryPartitionProvider: queryPartitionProvider,
                        clientApiVersion: version,
                        out QueryInfo _);
                }
                else if (request.Properties != null && request.Properties.TryGetValue(
                             WFConstants.BackendHeaders.EffectivePartitionKeyString,
                             out object effectivePartitionKey))
                {
                    if (effectivePartitionKey is string effectivePartitionKeyString)
                    {
                        providedRanges = new List <Range <string> >()
                        {
                            Range <string> .GetPointRange(effectivePartitionKeyString),
                        };
                    }
                    else
                    {
                        throw new ArgumentException(
                                  "EffectivePartitionKey must be a string",
                                  WFConstants.BackendHeaders.EffectivePartitionKeyString);
                    }
                }
                else
                {
                    providedRanges = new List <Range <string> >
                    {
                        new Range <string>(
                            PartitionKeyInternal.MinimumInclusiveEffectivePartitionKey,
                            PartitionKeyInternal.MaximumExclusiveEffectivePartitionKey,
                            true,
                            false)
                    };
                }

                this.providedRangesCache[collection.ResourceId] = providedRanges;
            }

            PartitionRoutingHelper.ResolvedRangeInfo resolvedRangeInfo = await this.partitionRoutingHelper.TryGetTargetRangeFromContinuationTokenRangeAsync(
                providedRanges,
                routingMapProvider,
                collection.ResourceId,
                rangeFromContinuationToken,
                suppliedTokens,
                NoOpTrace.Singleton);

            if (resolvedRangeInfo.ResolvedRange == null)
            {
                return(null);
            }
            else
            {
                return(Tuple.Create(resolvedRangeInfo, providedRanges));
            }
        }
Example #25
0
        /// <summary>
        /// Replaces (deletes and creates) the <b>Cosmos</b> container (and optionally created the database if it does not exist).
        /// </summary>
        /// <param name="client">The <see cref="CosmosClient"/>.</param>
        /// <param name="databaseId">The database identifier.</param>
        /// <param name="containerProperties">The <see cref="ContainerProperties"/> used for the create.</param>
        /// <param name="throughput">The throughput (RU/S).</param>
        /// <param name="createDatabaseIfNotExists">Indicates whether the database shoould be created if it does not exist.</param>
        /// <returns>The <see cref="CosmosDbContainerSetUp"/>.</returns>
        public static async Task <CosmosDbContainerSetUp> ReplaceAndOpenAsync(CosmosClient client, string databaseId, ContainerProperties containerProperties, int?throughput = 400, bool createDatabaseIfNotExists = true)
        {
            Logger.Default.Info($"COSMOS > Database '{databaseId}' Container '{containerProperties.Id}' Replace and Open.");

            Check.NotNull(client, nameof(client));
            Check.NotNull(containerProperties, nameof(containerProperties));

            var database = client.GetDatabase(Check.NotEmpty(databaseId, nameof(databaseId)));

            if (createDatabaseIfNotExists)
            {
                database = (await client.CreateDatabaseIfNotExistsAsync(databaseId, throughput)).Database;
            }

            var container = database.GetContainer(containerProperties.Id);

            // Remove existing container if it already exists.
            try
            {
                await container.DeleteContainerAsync();
            }
            catch (CosmosException cex)
            {
                if (cex.StatusCode != HttpStatusCode.NotFound)
                {
                    throw;
                }
            }

            // Create the container as specified.
            await database.CreateContainerIfNotExistsAsync(containerProperties, throughput);

            return(new CosmosDbContainerSetUp(database, container));
        }
Example #26
0
        /// <summary>
        /// The default behavior is for DocumentDB to index every attribute in every document automatically.
        /// There are times when a document contains large amounts of information, in deeply nested structures
        /// that you know you will never search on. In extreme cases like this, you can exclude paths from the
        /// index to save on storage cost, improve write performance and also improve read performance because the index is smaller
        ///
        /// This method demonstrates how to set IndexingPolicy.ExcludedPaths
        /// </summary>
        private static async Task ExcludePathsFromIndex()
        {
            string containerId = $"{Program.containerId}-ExcludePathsFromIndex";

            Console.WriteLine("\n3. Exclude specified paths from document index");

            ContainerProperties containerProperties = new ContainerProperties(containerId, Program.partitionKey);

            containerProperties.IndexingPolicy.IncludedPaths.Add(new IncludedPath {
                Path = "/*"
            });                                                                                      // Special manadatory path of "/*" required to denote include entire tree
            containerProperties.IndexingPolicy.ExcludedPaths.Add(new ExcludedPath {
                Path = "/metaData/*"
            });                                                                                                // exclude metaData node, and anything under it
            containerProperties.IndexingPolicy.ExcludedPaths.Add(new ExcludedPath {
                Path = "/subDoc/nonSearchable/*"
            });                                                                                                           // exclude ONLY a part of subDoc
            containerProperties.IndexingPolicy.ExcludedPaths.Add(new ExcludedPath {
                Path = "/\"excludedNode\"/*"
            });                                                                                                      // exclude excludedNode node, and anything under it

            // The effect of the above IndexingPolicy is that only id, foo, and the subDoc/searchable are indexed

            ContainerResponse response = await Program.database.CreateContainerAsync(containerProperties);

            Console.WriteLine("Container {0} created with index policy \n{1}", containerId, JsonConvert.SerializeObject(response.Resource.IndexingPolicy));
            Container container = (Container)response;

            try
            {
                int numDocs = 250;
                Console.WriteLine("Creating {0} documents", numDocs);
                for (int docIndex = 0; docIndex < numDocs; docIndex++)
                {
                    dynamic dyn = new
                    {
                        id           = "doc" + docIndex,
                        partitionKey = "doc" + docIndex,
                        foo          = "bar" + docIndex,
                        metaData     = "meta" + docIndex,
                        subDoc       = new { searchable = "searchable" + docIndex, nonSearchable = "value" + docIndex },
                        excludedNode = new { subExcluded = "something" + docIndex, subExcludedNode = new { someProperty = "value" + docIndex } }
                    };
                    ItemResponse <dynamic> created = await container.CreateItemAsync <dynamic>(dyn, new PartitionKey("doc" + docIndex));

                    Console.WriteLine("Creating document with id {0}", created.Resource.id);
                }

                // Querying for a document on either metaData or /subDoc/subSubDoc/someProperty will be expensive since they do not utilize the index,
                // but instead are served from scan automatically.
                int        queryDocId = numDocs / 2;
                QueryStats queryStats = await Program.GetQueryResult(container, string.Format(CultureInfo.InvariantCulture, "SELECT * FROM root r WHERE r.metaData='meta{0}'", queryDocId));

                Console.WriteLine("Query on metaData returned {0} results", queryStats.Count);
                Console.WriteLine("Query on metaData consumed {0} RUs", queryStats.RequestCharge);

                queryStats = await Program.GetQueryResult(container, string.Format(CultureInfo.InvariantCulture, "SELECT * FROM root r WHERE r.subDoc.nonSearchable='value{0}'", queryDocId));

                Console.WriteLine("Query on /subDoc/nonSearchable returned {0} results", queryStats.Count);
                Console.WriteLine("Query on /subDoc/nonSearchable consumed {0} RUs", queryStats.RequestCharge);

                queryStats = await Program.GetQueryResult(container, string.Format(CultureInfo.InvariantCulture, "SELECT * FROM root r WHERE r.excludedNode.subExcludedNode.someProperty='value{0}'", queryDocId));

                Console.WriteLine("Query on /excludedNode/subExcludedNode/someProperty returned {0} results", queryStats.Count);
                Console.WriteLine("Query on /excludedNode/subExcludedNode/someProperty cost {0} RUs", queryStats.RequestCharge);

                // Querying for a document using foo, or even subDoc/searchable > consume less RUs because they were not excluded
                queryStats = await Program.GetQueryResult(container, string.Format(CultureInfo.InvariantCulture, "SELECT * FROM root r WHERE r.foo='bar{0}'", queryDocId));

                Console.WriteLine("Query on /foo returned {0} results", queryStats.Count);
                Console.WriteLine("Query on /foo cost {0} RUs", queryStats.RequestCharge);

                queryStats = await Program.GetQueryResult(container, string.Format(CultureInfo.InvariantCulture, "SELECT * FROM root r WHERE r.subDoc.searchable='searchable{0}'", queryDocId));

                Console.WriteLine("Query on /subDoc/searchable returned {0} results", queryStats.Count);
                Console.WriteLine("Query on /subDoc/searchable cost {0} RUs", queryStats.RequestCharge);
            }
            finally
            {
                // Cleanup
                await container.DeleteContainerAsync();
            }
        }
Example #27
0
        public static Func <bool, IQueryable <Family> > GenerateFamilyCosmosData(
            Cosmos.Database cosmosDatabase, out Container container)
        {
            // The test collection should have range index on string properties
            // for the orderby tests
            PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition {
                Paths = new System.Collections.ObjectModel.Collection <string>(new[] { "/Pk" }), Kind = PartitionKind.Hash
            };
            ContainerProperties newCol = new ContainerProperties()
            {
                Id             = Guid.NewGuid().ToString(),
                PartitionKey   = partitionKeyDefinition,
                IndexingPolicy = new Microsoft.Azure.Cosmos.IndexingPolicy()
                {
                    IncludedPaths = new Collection <Cosmos.IncludedPath>()
                    {
                        new Cosmos.IncludedPath()
                        {
                            Path    = "/*",
                            Indexes = new System.Collections.ObjectModel.Collection <Microsoft.Azure.Cosmos.Index>()
                            {
                                Microsoft.Azure.Cosmos.Index.Range(Microsoft.Azure.Cosmos.DataType.Number, -1),
                                Microsoft.Azure.Cosmos.Index.Range(Microsoft.Azure.Cosmos.DataType.String, -1)
                            }
                        }
                    },
                    CompositeIndexes = new Collection <Collection <Cosmos.CompositePath> >()
                    {
                        new Collection <Cosmos.CompositePath>()
                        {
                            new Cosmos.CompositePath()
                            {
                                Path = "/FamilyId", Order = Cosmos.CompositePathSortOrder.Ascending
                            },
                            new Cosmos.CompositePath()
                            {
                                Path = "/Int", Order = Cosmos.CompositePathSortOrder.Ascending
                            }
                        },
                        new Collection <Cosmos.CompositePath>()
                        {
                            new Cosmos.CompositePath()
                            {
                                Path = "/FamilyId", Order = Cosmos.CompositePathSortOrder.Ascending
                            },
                            new Cosmos.CompositePath()
                            {
                                Path = "/Int", Order = Cosmos.CompositePathSortOrder.Descending
                            }
                        },
                        new Collection <Cosmos.CompositePath>()
                        {
                            new Cosmos.CompositePath()
                            {
                                Path = "/FamilyId", Order = Cosmos.CompositePathSortOrder.Ascending
                            },
                            new Cosmos.CompositePath()
                            {
                                Path = "/Int", Order = Cosmos.CompositePathSortOrder.Ascending
                            },
                            new Cosmos.CompositePath()
                            {
                                Path = "/IsRegistered", Order = Cosmos.CompositePathSortOrder.Descending
                            }
                        },
                        new Collection <Cosmos.CompositePath>()
                        {
                            new Cosmos.CompositePath()
                            {
                                Path = "/Int", Order = Cosmos.CompositePathSortOrder.Ascending
                            },
                            new Cosmos.CompositePath()
                            {
                                Path = "/IsRegistered", Order = Cosmos.CompositePathSortOrder.Descending
                            }
                        },
                        new Collection <Cosmos.CompositePath>()
                        {
                            new Cosmos.CompositePath()
                            {
                                Path = "/IsRegistered", Order = Cosmos.CompositePathSortOrder.Ascending
                            },
                            new Cosmos.CompositePath()
                            {
                                Path = "/Int", Order = Cosmos.CompositePathSortOrder.Descending
                            }
                        }
                    }
                }
            };

            container = cosmosDatabase.CreateContainerAsync(newCol).Result;
            const int Records                   = 100;
            const int MaxNameLength             = 100;
            const int MaxThingStringLength      = 50;
            const int MaxChild                  = 5;
            const int MaxPets                   = MaxChild;
            const int MaxThings                 = MaxChild;
            const int MaxGrade                  = 101;
            const int MaxTransaction            = 20;
            const int MaxTransactionMinuteRange = 200;
            int       MaxTransactionType        = Enum.GetValues(typeof(TransactionType)).Length;

            Family createDataObj(Random random)
            {
                Family obj = new Family
                {
                    FamilyId     = random.NextDouble() < 0.05 ? "some id" : Guid.NewGuid().ToString(),
                    IsRegistered = random.NextDouble() < 0.5,
                    NullableInt  = random.NextDouble() < 0.5 ? (int?)random.Next() : null,
                    Int          = random.NextDouble() < 0.5 ? 5 : random.Next(),
                    Id           = Guid.NewGuid().ToString(),
                    Pk           = "Test",
                    Parents      = new Parent[random.Next(2) + 1]
                };

                for (int i = 0; i < obj.Parents.Length; ++i)
                {
                    obj.Parents[i] = new Parent()
                    {
                        FamilyName = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)),
                        GivenName  = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength))
                    };
                }

                obj.Tags = new string[random.Next(MaxChild)];
                for (int i = 0; i < obj.Tags.Length; ++i)
                {
                    obj.Tags[i] = (i + random.Next(30, 36)).ToString();
                }

                obj.Children = new Child[random.Next(MaxChild)];
                for (int i = 0; i < obj.Children.Length; ++i)
                {
                    obj.Children[i] = new Child()
                    {
                        Gender     = random.NextDouble() < 0.5 ? "male" : "female",
                        FamilyName = obj.Parents[random.Next(obj.Parents.Length)].FamilyName,
                        GivenName  = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)),
                        Grade      = random.Next(MaxGrade)
                    };

                    obj.Children[i].Pets = new List <Pet>();
                    for (int j = 0; j < random.Next(MaxPets); ++j)
                    {
                        obj.Children[i].Pets.Add(new Pet()
                        {
                            GivenName = random.NextDouble() < 0.5 ?
                                        LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)) :
                                        "Fluffy"
                        });
                    }

                    obj.Children[i].Things = new Dictionary <string, string>();
                    for (int j = 0; j < random.Next(MaxThings) + 1; ++j)
                    {
                        obj.Children[i].Things.Add(
                            j == 0 ? "A" : $"{j}-{random.Next().ToString()}",
                            LinqTestsCommon.RandomString(random, random.Next(MaxThingStringLength)));
                    }
                }

                obj.Records = new Logs
                {
                    LogId        = LinqTestsCommon.RandomString(random, random.Next(MaxNameLength)),
                    Transactions = new Transaction[random.Next(MaxTransaction)]
                };
                for (int i = 0; i < obj.Records.Transactions.Length; ++i)
                {
                    Transaction transaction = new Transaction()
                    {
                        Amount = random.Next(),
                        Date   = DateTime.Now.AddMinutes(random.Next(MaxTransactionMinuteRange)),
                        Type   = (TransactionType)random.Next(MaxTransactionType)
                    };
                    obj.Records.Transactions[i] = transaction;
                }

                return(obj);
            }

            Func <bool, IQueryable <Family> > getQuery = LinqTestsCommon.GenerateTestCosmosData(createDataObj, Records, container);

            return(getQuery);
        }