Esempio n. 1
0
        public static async Task <HttpResponseMessage> GetAsync(this HttpClient client,
                                                                Uri uri,
                                                                INameValueCollection additionalHeaders = null,
                                                                CancellationToken cancellationToken    = default(CancellationToken))
        {
            if (uri == null)
            {
                throw new ArgumentNullException("uri");
            }

            // GetAsync doesn't let clients to pass in additional headers. So, we are
            // internally using SendAsync and add the additional headers to requestMessage.
            using (HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, uri))
            {
                if (additionalHeaders != null)
                {
                    foreach (string header in additionalHeaders)
                    {
                        if (GatewayStoreModel.IsAllowedRequestHeader(header))
                        {
                            requestMessage.Headers.TryAddWithoutValidation(header, additionalHeaders[header]);
                        }
                    }
                }
                return(await client.SendHttpAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead, cancellationToken));
            }
        }
        private async Task GatewayStoreModel_Exception_UpdateSessionTokenOnKnownException(Exception ex)
        {
            const string originalSessionToken = "0:1#100#1=20#2=5#3=30";
            const string updatedSessionToken  = "0:1#100#1=20#2=5#3=31";

            Func <HttpRequestMessage, Task <HttpResponseMessage> > sendFunc = request =>
            {
                throw ex;
            };

            Mock <IDocumentClientInternal> mockDocumentClient = new Mock <IDocumentClientInternal>();

            mockDocumentClient.Setup(client => client.ServiceEndpoint).Returns(new Uri("https://foo"));

            GlobalEndpointManager     endpointManager  = new GlobalEndpointManager(mockDocumentClient.Object, new ConnectionPolicy());
            SessionContainer          sessionContainer = new SessionContainer(string.Empty);
            DocumentClientEventSource eventSource      = DocumentClientEventSource.Instance;
            HttpMessageHandler        messageHandler   = new MockMessageHandler(sendFunc);
            GatewayStoreModel         storeModel       = new GatewayStoreModel(
                endpointManager,
                sessionContainer,
                TimeSpan.FromSeconds(5),
                ConsistencyLevel.Eventual,
                eventSource,
                null,
                new UserAgentContainer(),
                ApiType.None,
                messageHandler);

            INameValueCollection headers = new DictionaryNameValueCollection();

            headers.Set(HttpConstants.HttpHeaders.ConsistencyLevel, ConsistencyLevel.Session.ToString());
            headers.Set(HttpConstants.HttpHeaders.SessionToken, originalSessionToken);
            headers.Set(WFConstants.BackendHeaders.PartitionKeyRangeId, "0");

            using (new ActivityScope(Guid.NewGuid()))
            {
                using (DocumentServiceRequest request = DocumentServiceRequest.Create(
                           OperationType.Read,
                           ResourceType.Document,
                           "dbs/OVJwAA==/colls/OVJwAOcMtA0=/docs/OVJwAOcMtA0BAAAAAAAAAA==/",
                           AuthorizationTokenType.PrimaryMasterKey,
                           headers))
                {
                    request.UseStatusCodeFor429      = true;
                    request.UseStatusCodeForFailures = true;
                    try
                    {
                        DocumentServiceResponse response = await storeModel.ProcessMessageAsync(request);

                        Assert.Fail("Should had thrown exception");
                    }
                    catch (Exception)
                    {
                        // Expecting exception
                    }
                    Assert.AreEqual(updatedSessionToken, sessionContainer.GetSessionToken("dbs/OVJwAA==/colls/OVJwAOcMtA0="));
                }
            }
        }
        public void GatewayStoreModel_HttpClientFactory_IfNull()
        {
            HttpClient staticHttpClient = null;

            Mock <Func <HttpClient> > mockFactory = new Mock <Func <HttpClient> >();

            mockFactory.Setup(f => f()).Returns(staticHttpClient);

            Mock <IDocumentClientInternal> mockDocumentClient = new Mock <IDocumentClientInternal>();

            mockDocumentClient.Setup(client => client.ServiceEndpoint).Returns(new Uri("https://foo"));

            GlobalEndpointManager     endpointManager  = new GlobalEndpointManager(mockDocumentClient.Object, new ConnectionPolicy());
            SessionContainer          sessionContainer = new SessionContainer(string.Empty);
            DocumentClientEventSource eventSource      = DocumentClientEventSource.Instance;
            GatewayStoreModel         storeModel       = new GatewayStoreModel(
                endpointManager,
                sessionContainer,
                TimeSpan.FromSeconds(5),
                ConsistencyLevel.Eventual,
                eventSource,
                null,
                new UserAgentContainer(),
                ApiType.None,
                mockFactory.Object);
        }
        public async Task TestSessionTokenAvailability()
        {
            GatewayStoreModel storeModel = GetGatewayStoreModelForConsistencyTest();

            using (DocumentServiceRequest request =
                       DocumentServiceRequest.Create(
                           Documents.OperationType.Read,
                           Documents.ResourceType.Collection,
                           new Uri("https://foo.com/dbs/db1/colls/coll1", UriKind.Absolute),
                           new MemoryStream(Encoding.UTF8.GetBytes("collection")),
                           AuthorizationTokenType.PrimaryMasterKey,
                           null))
            {
                await TestGatewayStoreModelProcessMessageAsync(storeModel, request);
            }

            using (DocumentServiceRequest request =
                       DocumentServiceRequest.Create(
                           Documents.OperationType.Query,
                           Documents.ResourceType.Document,
                           new Uri("https://foo.com/dbs/db1/colls/coll1", UriKind.Absolute),
                           new MemoryStream(Encoding.UTF8.GetBytes("document")),
                           AuthorizationTokenType.PrimaryMasterKey,
                           null))
            {
                await TestGatewayStoreModelProcessMessageAsync(storeModel, request);
            }
        }
Esempio n. 5
0
        public virtual async Task <DocumentServiceResponse> ProcessMessageAsync(DocumentServiceRequest request, CancellationToken cancellationToken = default(CancellationToken))
        {
            GatewayStoreModel.ApplySessionToken(
                request,
                this.defaultConsistencyLevel,
                this.sessionContainer);

            DocumentServiceResponse response;

            try
            {
                Uri physicalAddress = GatewayStoreClient.IsFeedRequest(request.OperationType) ? this.GetFeedUri(request) : this.GetEntityUri(request);
                response = await this.gatewayStoreClient.InvokeAsync(request, request.ResourceType, physicalAddress, cancellationToken);
            }
            catch (DocumentClientException exception)
            {
                if ((!ReplicatedResourceClient.IsMasterResource(request.ResourceType)) &&
                    (exception.StatusCode == HttpStatusCode.PreconditionFailed || exception.StatusCode == HttpStatusCode.Conflict ||
                     (exception.StatusCode == HttpStatusCode.NotFound && exception.GetSubStatus() != SubStatusCodes.ReadSessionNotAvailable)))
                {
                    this.CaptureSessionToken(exception.StatusCode, exception.GetSubStatus(), request, exception.Headers);
                }

                throw;
            }

            this.CaptureSessionToken(response.StatusCode, response.SubStatusCode, request, response.Headers);
            return(response);
        }
Esempio n. 6
0
        private GatewayStoreModel GetGatewayStoreModelForConsistencyTest()
        {
            Func <HttpRequestMessage, Task <HttpResponseMessage> > messageHandler = async request =>
            {
                String content = await request.Content.ReadAsStringAsync();

                if (content.Equals("document"))
                {
                    IEnumerable <string> sessionTokens = request.Headers.GetValues("x-ms-session-token");
                    string sessionToken = "";
                    foreach (string singleToken in sessionTokens)
                    {
                        sessionToken = singleToken;
                        break;
                    }
                    Assert.AreEqual(sessionToken, "0:1#100#1=20#2=5#3=30");
                }
                else
                {
                    IEnumerable <string> enumerable;
                    Assert.IsFalse(request.Headers.TryGetValues("x-ms-session-token", out enumerable));
                }
                return(new HttpResponseMessage(HttpStatusCode.OK)
                {
                    Content = new StringContent("Response")
                });
            };

            Mock <IDocumentClientInternal> mockDocumentClient = new Mock <IDocumentClientInternal>();

            mockDocumentClient.Setup(client => client.ServiceEndpoint).Returns(new Uri("https://foo"));
            mockDocumentClient.Setup(client => client.ConsistencyLevel).Returns(Documents.ConsistencyLevel.Session);

            GlobalEndpointManager endpointManager = new GlobalEndpointManager(mockDocumentClient.Object, new ConnectionPolicy());

            SessionContainer sessionContainer = new SessionContainer(string.Empty);

            sessionContainer.SetSessionToken(
                ResourceId.NewDocumentCollectionId(42, 129).DocumentCollectionId.ToString(),
                "dbs/db1/colls/coll1",
                new DictionaryNameValueCollection()
            {
                { HttpConstants.HttpHeaders.SessionToken, "0:1#100#1=20#2=5#3=30" }
            });

            DocumentClientEventSource eventSource        = new DocumentClientEventSource();
            HttpMessageHandler        httpMessageHandler = new MockMessageHandler(messageHandler);

            GatewayStoreModel storeModel = new GatewayStoreModel(
                endpointManager,
                sessionContainer,
                TimeSpan.FromSeconds(50),
                ConsistencyLevel.Session,
                eventSource,
                new UserAgentContainer(),
                ApiType.None,
                httpMessageHandler);

            return(storeModel);
        }
Esempio n. 7
0
        internal static async Task ApplySessionTokenAsync(
            DocumentServiceRequest request,
            ConsistencyLevel defaultConsistencyLevel,
            ISessionContainer sessionContainer,
            PartitionKeyRangeCache partitionKeyRangeCache,
            CollectionCache clientCollectionCache,
            IGlobalEndpointManager globalEndpointManager)
        {
            if (request.Headers == null)
            {
                Debug.Fail("DocumentServiceRequest does not have headers.");
                return;
            }

            // Master resource operations don't require session token.
            if (GatewayStoreModel.IsMasterOperation(request.ResourceType, request.OperationType))
            {
                if (!string.IsNullOrEmpty(request.Headers[HttpConstants.HttpHeaders.SessionToken]))
                {
                    request.Headers.Remove(HttpConstants.HttpHeaders.SessionToken);
                }

                return;
            }

            if (!string.IsNullOrEmpty(request.Headers[HttpConstants.HttpHeaders.SessionToken]))
            {
                return; // User is explicitly controlling the session.
            }

            string requestConsistencyLevel  = request.Headers[HttpConstants.HttpHeaders.ConsistencyLevel];
            bool   isReadOrBatchRequest     = request.IsReadOnlyRequest || request.OperationType == OperationType.Batch;
            bool   requestHasConsistencySet = !string.IsNullOrEmpty(requestConsistencyLevel) && isReadOrBatchRequest; // Only read requests can have their consistency modified

            bool sessionConsistencyApplies =
                (!requestHasConsistencySet && defaultConsistencyLevel == ConsistencyLevel.Session) ||
                (requestHasConsistencySet &&
                 string.Equals(requestConsistencyLevel, GatewayStoreModel.sessionConsistencyAsString, StringComparison.OrdinalIgnoreCase));

            bool isMultiMasterEnabledForRequest = globalEndpointManager.CanUseMultipleWriteLocations(request);

            if (!sessionConsistencyApplies ||
                (!isReadOrBatchRequest &&
                 !isMultiMasterEnabledForRequest))
            {
                return; // Only apply the session token in case of session consistency and the request is read only or read/write on multimaster
            }

            (bool isSuccess, string sessionToken) = await GatewayStoreModel.TryResolveSessionTokenAsync(
                request,
                sessionContainer,
                partitionKeyRangeCache,
                clientCollectionCache);

            if (isSuccess && !string.IsNullOrEmpty(sessionToken))
            {
                request.Headers[HttpConstants.HttpHeaders.SessionToken] = sessionToken;
            }
        }
        public async Task TestRetries()
        {
            int run = 0;
            Func <HttpRequestMessage, Task <HttpResponseMessage> > sendFunc = async request =>
            {
                string content = await request.Content.ReadAsStringAsync();

                Assert.AreEqual("content1", content);

                if (run == 0)
                {
                    run++;
                    throw new WebException("", WebExceptionStatus.ConnectFailure);
                }
                else
                {
                    return(new HttpResponseMessage(HttpStatusCode.OK)
                    {
                        Content = new StringContent("Response")
                    });
                }
            };

            Mock <IDocumentClientInternal> mockDocumentClient = new Mock <IDocumentClientInternal>();

            mockDocumentClient.Setup(client => client.ServiceEndpoint).Returns(new Uri("https://foo"));

            GlobalEndpointManager     endpointManager  = new GlobalEndpointManager(mockDocumentClient.Object, new ConnectionPolicy());
            ISessionContainer         sessionContainer = new SessionContainer(string.Empty);
            DocumentClientEventSource eventSource      = DocumentClientEventSource.Instance;
            HttpMessageHandler        messageHandler   = new MockMessageHandler(sendFunc);
            GatewayStoreModel         storeModel       = new GatewayStoreModel(
                endpointManager,
                sessionContainer,
                TimeSpan.FromSeconds(5),
                ConsistencyLevel.Eventual,
                eventSource,
                null,
                new UserAgentContainer(),
                ApiType.None,
                messageHandler);

            using (new ActivityScope(Guid.NewGuid()))
            {
                using (DocumentServiceRequest request =
                           DocumentServiceRequest.Create(
                               Documents.OperationType.Query,
                               Documents.ResourceType.Document,
                               new Uri("https://foo.com/dbs/db1/colls/coll1", UriKind.Absolute),
                               new MemoryStream(Encoding.UTF8.GetBytes("content1")),
                               AuthorizationTokenType.PrimaryMasterKey,
                               null))
                {
                    await storeModel.ProcessMessageAsync(request);
                }
            }

            Assert.IsTrue(run > 0);
        }
        public async Task GatewayProcessMessageAsyncCancels()
        {
            using (CancellationTokenSource source = new CancellationTokenSource())
            {
                CancellationToken cancellationToken = source.Token;

                int run = 0;
                Func <HttpRequestMessage, Task <HttpResponseMessage> > sendFunc = async request =>
                {
                    string content = await request.Content.ReadAsStringAsync();

                    Assert.AreEqual("content1", content);

                    if (run == 0)
                    {
                        // We force a retry but cancel the token to verify if the retry mechanism cancels inbetween
                        source.Cancel();
                        throw new WebException("", WebExceptionStatus.ConnectFailure);
                    }

                    return(new HttpResponseMessage(HttpStatusCode.OK)
                    {
                        Content = new StringContent("Response")
                    });
                };

                Mock <IDocumentClientInternal> mockDocumentClient = new Mock <IDocumentClientInternal>();
                mockDocumentClient.Setup(client => client.ServiceEndpoint).Returns(new Uri("https://foo"));

                GlobalEndpointManager     endpointManager  = new GlobalEndpointManager(mockDocumentClient.Object, new ConnectionPolicy());
                ISessionContainer         sessionContainer = new SessionContainer(string.Empty);
                DocumentClientEventSource eventSource      = DocumentClientEventSource.Instance;
                HttpMessageHandler        messageHandler   = new MockMessageHandler(sendFunc);
                GatewayStoreModel         storeModel       = new GatewayStoreModel(
                    endpointManager,
                    sessionContainer,
                    ConsistencyLevel.Eventual,
                    eventSource,
                    null,
                    new HttpClient(messageHandler));

                using (new ActivityScope(Guid.NewGuid()))
                {
                    using (DocumentServiceRequest request =
                               DocumentServiceRequest.Create(
                                   Documents.OperationType.Query,
                                   Documents.ResourceType.Document,
                                   new Uri("https://foo.com/dbs/db1/colls/coll1", UriKind.Absolute),
                                   new MemoryStream(Encoding.UTF8.GetBytes("content1")),
                                   AuthorizationTokenType.PrimaryMasterKey,
                                   null))
                    {
                        await storeModel.ProcessMessageAsync(request, cancellationToken);
                    }
                }

                Assert.Fail();
            }
        }
Esempio n. 10
0
        private GatewayStoreModel GetGatewayStoreModelForConsistencyTest()
        {
            Func <HttpRequestMessage, Task <HttpResponseMessage> > messageHandler = async request =>
            {
                String content = await request.Content.ReadAsStringAsync();

                if (content.Equals("document"))
                {
                    IEnumerable <string> sessionTokens = request.Headers.GetValues("x-ms-session-token");
                    string sessionToken = "";
                    foreach (string singleToken in sessionTokens)
                    {
                        sessionToken = singleToken;
                        break;
                    }
                    Assert.AreEqual(sessionToken, "0:9");
                }
                else
                {
                    IEnumerable <string> enumerable;
                    Assert.IsFalse(request.Headers.TryGetValues("x-ms-session-token", out enumerable));
                }
                return(new HttpResponseMessage(HttpStatusCode.OK)
                {
                    Content = new StringContent("Response")
                });
            };

            Mock <IDocumentClientInternal> mockDocumentClient = new Mock <IDocumentClientInternal>();

            mockDocumentClient.Setup(client => client.ServiceEndpoint).Returns(new Uri("https://foo"));
            mockDocumentClient.Setup(client => client.ConsistencyLevel).Returns(ConsistencyLevel.Session);

            GlobalEndpointManager endpointManager = new GlobalEndpointManager(mockDocumentClient.Object, new ConnectionPolicy());

            ConcurrentDictionary <string, ISessionToken> token = new ConcurrentDictionary <string, ISessionToken>();

            token["0"] = new SimpleSessionToken(9);
            ConcurrentDictionary <string, ConcurrentDictionary <string, ISessionToken> > sessionTokensNameBased = new ConcurrentDictionary <string, ConcurrentDictionary <string, ISessionToken> >();

            sessionTokensNameBased["dbs/db1/colls/coll1"] = token;

            ISessionContainer         sessionContainer   = new SessionContainer(string.Empty, null, sessionTokensNameBased);
            DocumentClientEventSource eventSource        = new DocumentClientEventSource();
            HttpMessageHandler        httpMessageHandler = new MockMessageHandler(messageHandler);

            GatewayStoreModel storeModel = new GatewayStoreModel(
                endpointManager,
                sessionContainer,
                TimeSpan.FromSeconds(50),
                ConsistencyLevel.Session,
                eventSource,
                new UserAgentContainer(),
                ApiType.None,
                httpMessageHandler);

            return(storeModel);
        }
Esempio n. 11
0
        private async Task TestGatewayStoreModelProcessMessageAsync(GatewayStoreModel storeModel, DocumentServiceRequest request)
        {
            request.Headers["x-ms-session-token"] = "0:9";
            await storeModel.ProcessMessageAsync(request);

            request.Headers.Remove("x-ms-session-token");
            request.Headers["x-ms-consistency-level"] = "Session";
            await storeModel.ProcessMessageAsync(request);
        }
Esempio n. 12
0
        internal static async Task ApplySessionTokenAsync(
            DocumentServiceRequest request,
            ConsistencyLevel defaultConsistencyLevel,
            ISessionContainer sessionContainer,
            PartitionKeyRangeCache partitionKeyRangeCache,
            CollectionCache clientCollectionCache)
        {
            if (request.Headers == null)
            {
                Debug.Fail("DocumentServiceRequest does not have headers.");
                return;
            }

            // Master resource operations don't require session token.
            if (GatewayStoreModel.IsMasterOperation(request.ResourceType, request.OperationType))
            {
                if (!string.IsNullOrEmpty(request.Headers[HttpConstants.HttpHeaders.SessionToken]))
                {
                    request.Headers.Remove(HttpConstants.HttpHeaders.SessionToken);
                }

                return;
            }

            if (!string.IsNullOrEmpty(request.Headers[HttpConstants.HttpHeaders.SessionToken]))
            {
                return; // User is explicitly controlling the session.
            }

            string requestConsistencyLevel = request.Headers[HttpConstants.HttpHeaders.ConsistencyLevel];

            bool sessionConsistency =
                defaultConsistencyLevel == ConsistencyLevel.Session ||
                (!string.IsNullOrEmpty(requestConsistencyLevel) &&
                 string.Equals(requestConsistencyLevel, ConsistencyLevel.Session.ToString(), StringComparison.OrdinalIgnoreCase));

            if (!sessionConsistency || (!request.IsReadOnlyRequest && request.OperationType != OperationType.Batch))
            {
                return; // Only apply the session token in case of session consistency and the request is read only
            }

            (bool isSuccess, string sessionToken) = await GatewayStoreModel.TryResolveSessionTokenAsync(
                request,
                sessionContainer,
                partitionKeyRangeCache,
                clientCollectionCache);

            if (!isSuccess)
            {
                sessionToken = sessionContainer.ResolveGlobalSessionToken(request);
            }

            if (!string.IsNullOrEmpty(sessionToken))
            {
                request.Headers[HttpConstants.HttpHeaders.SessionToken] = sessionToken;
            }
        }
Esempio n. 13
0
        public async Task GatewayProcessMessageAsyncCancelsOnDeadline()
        {
            // Cancellation deadline is before Request timeout
            using (CancellationTokenSource source = new CancellationTokenSource(TimeSpan.FromSeconds(2)))
            {
                CancellationToken cancellationToken = source.Token;

                Func <HttpRequestMessage, Task <HttpResponseMessage> > sendFunc = async request =>
                {
                    string content = await request.Content.ReadAsStringAsync();

                    Assert.AreEqual("content1", content);

                    // Wait until CancellationTokenSource deadline expires
                    Thread.Sleep(2000);
                    // Force retries
                    throw new WebException("", WebExceptionStatus.ConnectFailure);
                };

                Mock <IDocumentClientInternal> mockDocumentClient = new Mock <IDocumentClientInternal>();
                mockDocumentClient.Setup(client => client.ServiceEndpoint).Returns(new Uri("https://foo"));

                GlobalEndpointManager     endpointManager  = new GlobalEndpointManager(mockDocumentClient.Object, new ConnectionPolicy());
                ISessionContainer         sessionContainer = new SessionContainer(string.Empty);
                DocumentClientEventSource eventSource      = DocumentClientEventSource.Instance;
                HttpMessageHandler        messageHandler   = new MockMessageHandler(sendFunc);
                GatewayStoreModel         storeModel       = new GatewayStoreModel(
                    endpointManager,
                    sessionContainer,
                    TimeSpan.FromSeconds(5),
                    ConsistencyLevel.Eventual,
                    eventSource,
                    null,
                    new UserAgentContainer(),
                    ApiType.None,
                    messageHandler);

                using (new ActivityScope(Guid.NewGuid()))
                {
                    using (DocumentServiceRequest request =
                               DocumentServiceRequest.Create(
                                   Documents.OperationType.Query,
                                   Documents.ResourceType.Document,
                                   new Uri("https://foo.com/dbs/db1/colls/coll1", UriKind.Absolute),
                                   new MemoryStream(Encoding.UTF8.GetBytes("content1")),
                                   AuthorizationTokenType.PrimaryMasterKey,
                                   null))
                    {
                        await storeModel.ProcessMessageAsync(request, cancellationToken);
                    }
                }
                Assert.Fail();
            }
        }
        public async Task TestErrorResponsesProvideBody()
        {
            string testContent = "Content";
            Func <HttpRequestMessage, Task <HttpResponseMessage> > sendFunc = request =>
            {
                return(Task.FromResult(new HttpResponseMessage(HttpStatusCode.Conflict)
                {
                    Content = new StringContent(testContent)
                }));
            };

            Mock <IDocumentClientInternal> mockDocumentClient = new Mock <IDocumentClientInternal>();

            mockDocumentClient.Setup(client => client.ServiceEndpoint).Returns(new Uri("https://foo"));

            GlobalEndpointManager     endpointManager  = new GlobalEndpointManager(mockDocumentClient.Object, new ConnectionPolicy());
            ISessionContainer         sessionContainer = new SessionContainer(string.Empty);
            DocumentClientEventSource eventSource      = DocumentClientEventSource.Instance;
            HttpMessageHandler        messageHandler   = new MockMessageHandler(sendFunc);
            GatewayStoreModel         storeModel       = new GatewayStoreModel(
                endpointManager,
                sessionContainer,
                TimeSpan.FromSeconds(5),
                ConsistencyLevel.Eventual,
                eventSource,
                null,
                new UserAgentContainer(),
                ApiType.None,
                messageHandler);

            using (new ActivityScope(Guid.NewGuid()))
            {
                using (DocumentServiceRequest request =
                           DocumentServiceRequest.Create(
                               Documents.OperationType.Query,
                               Documents.ResourceType.Document,
                               new Uri("https://foo.com/dbs/db1/colls/coll1", UriKind.Absolute),
                               new MemoryStream(Encoding.UTF8.GetBytes("content1")),
                               AuthorizationTokenType.PrimaryMasterKey,
                               null))
                {
                    request.UseStatusCodeForFailures = true;
                    request.UseStatusCodeFor429      = true;

                    DocumentServiceResponse response = await storeModel.ProcessMessageAsync(request);

                    Assert.IsNotNull(response.ResponseBody);
                    using (StreamReader reader = new StreamReader(response.ResponseBody))
                    {
                        Assert.AreEqual(testContent, await reader.ReadToEndAsync());
                    }
                }
            }
        }
        private async Task TestGatewayStoreModelProcessMessageAsync(GatewayStoreModel storeModel, DocumentServiceRequest request)
        {
            using (new ActivityScope(Guid.NewGuid()))
            {
                request.Headers["x-ms-session-token"] = "range_0:1#9#4=8#5=7";
                await storeModel.ProcessMessageAsync(request);

                request.Headers.Remove("x-ms-session-token");
                request.Headers["x-ms-consistency-level"] = "Session";
                await storeModel.ProcessMessageAsync(request);
            }
        }
Esempio n. 16
0
 // DEVNOTE: This can be replace with ReplicatedResourceClient.IsMasterOperation on next Direct sync
 internal static bool IsMasterOperation(
     ResourceType resourceType,
     OperationType operationType)
 {
     // Stored procedures, trigger, and user defined functions CRUD operations are done on
     // master so they do not require the session token. Stored procedures execute is not a master operation
     return(ReplicatedResourceClient.IsMasterResource(resourceType) ||
            GatewayStoreModel.IsStoredProcedureCrudOperation(resourceType, operationType) ||
            resourceType == ResourceType.Trigger ||
            resourceType == ResourceType.UserDefinedFunction ||
            operationType == OperationType.QueryPlan);
 }
Esempio n. 17
0
        private async Task GatewayStoreModel_Exceptionless_NotUpdateSessionTokenOnKnownResponses(ResourceType resourceType, HttpStatusCode httpStatusCode, SubStatusCodes subStatusCode = SubStatusCodes.Unknown)
        {
            const string originalSessionToken = "0:1#100#1=20#2=5#3=30";
            const string updatedSessionToken  = "0:1#100#1=20#2=5#3=31";

            Func <HttpRequestMessage, Task <HttpResponseMessage> > sendFunc = request =>
            {
                HttpResponseMessage response = new HttpResponseMessage(httpStatusCode);
                response.Headers.Add(HttpConstants.HttpHeaders.SessionToken, updatedSessionToken);
                response.Headers.Add(WFConstants.BackendHeaders.SubStatus, subStatusCode.ToString());
                return(Task.FromResult(response));
            };

            Mock <IDocumentClientInternal> mockDocumentClient = new Mock <IDocumentClientInternal>();

            mockDocumentClient.Setup(client => client.ServiceEndpoint).Returns(new Uri("https://foo"));

            using GlobalEndpointManager endpointManager = new GlobalEndpointManager(mockDocumentClient.Object, new ConnectionPolicy());
            SessionContainer          sessionContainer = new SessionContainer(string.Empty);
            DocumentClientEventSource eventSource      = DocumentClientEventSource.Instance;
            HttpMessageHandler        messageHandler   = new MockMessageHandler(sendFunc);

            using GatewayStoreModel storeModel = new GatewayStoreModel(
                      endpointManager,
                      sessionContainer,
                      ConsistencyLevel.Eventual,
                      eventSource,
                      null,
                      MockCosmosUtil.CreateCosmosHttpClient(() => new HttpClient(messageHandler)));

            INameValueCollection headers = new StoreRequestNameValueCollection();

            headers.Set(HttpConstants.HttpHeaders.ConsistencyLevel, ConsistencyLevel.Session.ToString());
            headers.Set(HttpConstants.HttpHeaders.SessionToken, originalSessionToken);
            headers.Set(WFConstants.BackendHeaders.PartitionKeyRangeId, "0");

            using (new ActivityScope(Guid.NewGuid()))
            {
                using (DocumentServiceRequest request = DocumentServiceRequest.Create(
                           OperationType.Read,
                           resourceType,
                           "dbs/OVJwAA==/colls/OVJwAOcMtA0=/docs/OVJwAOcMtA0BAAAAAAAAAA==/",
                           AuthorizationTokenType.PrimaryMasterKey,
                           headers))
                {
                    request.UseStatusCodeFor429      = true;
                    request.UseStatusCodeForFailures = true;
                    DocumentServiceResponse response = await storeModel.ProcessMessageAsync(request);

                    Assert.AreEqual(string.Empty, sessionContainer.GetSessionToken("dbs/OVJwAA==/colls/OVJwAOcMtA0="));
                }
            }
        }
Esempio n. 18
0
        /// <summary>
        /// Sends a request with a particular response status code through the GatewayStoreModel
        /// </summary>
        private static async Task GatewayStoreClientRunScenario(
            DocumentServiceRequest request,
            int responseStatusCode)
        {
            Func <HttpRequestMessage, Task <HttpResponseMessage> > sendFunc = async httpRequest => await Task.FromResult(new HttpResponseMessage((HttpStatusCode)responseStatusCode));

            GatewayStoreModel storeModel = MockGatewayStoreModel(sendFunc);

            using (new ActivityScope(Guid.NewGuid()))
            {
                await storeModel.ProcessMessageAsync(request);
            }
        }
Esempio n. 19
0
        internal static void ApplySessionToken(
            DocumentServiceRequest request,
            ConsistencyLevel defaultConsistencyLevel,
            ISessionContainer sessionContainer)
        {
            if (request.Headers == null)
            {
                Debug.Fail("DocumentServiceRequest does not have headers.");
                return;
            }

            // Master resource operations don't require session token.
            if (GatewayStoreModel.IsMasterOperation(request.ResourceType, request.OperationType))
            {
                if (!string.IsNullOrEmpty(request.Headers[HttpConstants.HttpHeaders.SessionToken]))
                {
                    request.Headers.Remove(HttpConstants.HttpHeaders.SessionToken);
                }

                return;
            }

            if (!string.IsNullOrEmpty(request.Headers[HttpConstants.HttpHeaders.SessionToken]))
            {
                return; // User is explicitly controlling the session.
            }

            string requestConsistencyLevel = request.Headers[HttpConstants.HttpHeaders.ConsistencyLevel];

            bool sessionConsistency =
                defaultConsistencyLevel == ConsistencyLevel.Session ||
                (!string.IsNullOrEmpty(requestConsistencyLevel) &&
                 string.Equals(requestConsistencyLevel, ConsistencyLevel.Session.ToString(), StringComparison.OrdinalIgnoreCase));

            if (!sessionConsistency)
            {
                return; // Only apply the session token in case of session consistency
            }

            //Apply the ambient session.
            string sessionToken = sessionContainer.ResolveGlobalSessionToken(request);

            if (!string.IsNullOrEmpty(sessionToken))
            {
                request.Headers[HttpConstants.HttpHeaders.SessionToken] = sessionToken;
            }
        }
Esempio n. 20
0
        public virtual async Task <DocumentServiceResponse> ProcessMessageAsync(DocumentServiceRequest request, CancellationToken cancellationToken = default)
        {
            await GatewayStoreModel.ApplySessionTokenAsync(
                request,
                this.defaultConsistencyLevel,
                this.sessionContainer,
                this.partitionKeyRangeCache,
                this.clientCollectionCache,
                this.endpointManager);

            DocumentServiceResponse response;

            try
            {
                Uri physicalAddress = GatewayStoreClient.IsFeedRequest(request.OperationType) ? this.GetFeedUri(request) : this.GetEntityUri(request);
                // Collect region name only for document resources
                if (request.ResourceType.Equals(ResourceType.Document) && this.endpointManager.TryGetLocationForGatewayDiagnostics(request.RequestContext.LocationEndpointToRoute, out string regionName))
                {
                    request.RequestContext.RegionName = regionName;
                }
                response = await this.gatewayStoreClient.InvokeAsync(request, request.ResourceType, physicalAddress, cancellationToken);
            }
            catch (DocumentClientException exception)
            {
                if ((!ReplicatedResourceClient.IsMasterResource(request.ResourceType)) &&
                    (exception.StatusCode == HttpStatusCode.PreconditionFailed || exception.StatusCode == HttpStatusCode.Conflict ||
                     (exception.StatusCode == HttpStatusCode.NotFound && exception.GetSubStatus() != SubStatusCodes.ReadSessionNotAvailable)))
                {
                    await this.CaptureSessionTokenAndHandleSplitAsync(exception.StatusCode, exception.GetSubStatus(), request, exception.Headers);
                }

                throw;
            }

            await this.CaptureSessionTokenAndHandleSplitAsync(response.StatusCode, response.SubStatusCode, request, response.Headers);

            return(response);
        }
        private async Task <HttpRequestMessage> PrepareRequestMessageAsync(DocumentServiceRequest request)
        {
            HttpMethod httpMethod = HttpMethod.Head;

            if (request.OperationType == OperationType.Create ||
                request.OperationType == OperationType.Upsert ||
                request.OperationType == OperationType.Query ||
                request.OperationType == OperationType.SqlQuery ||
                request.OperationType == OperationType.ExecuteJavaScript)
            {
                httpMethod = HttpMethod.Post;
            }
            else if (request.OperationType == OperationType.Read ||
                     request.OperationType == OperationType.ReadFeed)
            {
                httpMethod = HttpMethod.Get;
            }
            else if (request.OperationType == OperationType.Replace)
            {
                httpMethod = HttpMethod.Put;
            }
            else if (request.OperationType == OperationType.Delete)
            {
                httpMethod = HttpMethod.Delete;
            }
            else
            {
                throw new NotImplementedException();
            }

            HttpRequestMessage requestMessage = new HttpRequestMessage(httpMethod,
                                                                       GatewayStoreModel.IsFeedRequest(request.OperationType) ? this.GetFeedUri(request) : this.GetEntityUri(request));

            // The StreamContent created below will own and dispose its underlying stream, but we may need to reuse the stream on the
            // DocumentServiceRequest for future requests. Hence we need to clone without incurring copy cost, so that when
            // HttpRequestMessage -> StreamContent -> MemoryStream all get disposed, the original stream will be left open.
            if (request.Body != null)
            {
                await request.EnsureBufferedBodyAsync();

                MemoryStream clonedStream = new MemoryStream();
                // WriteTo doesn't use and update Position of source stream. No point in setting/restoring it.
                request.CloneableBody.WriteTo(clonedStream);
                clonedStream.Position = 0;

                requestMessage.Content = new StreamContent(clonedStream);
            }
            if (request.Headers != null)
            {
                foreach (string key in request.Headers)
                {
                    if (GatewayStoreModel.IsAllowedRequestHeader(key))
                    {
                        if (key.Equals(HttpConstants.HttpHeaders.ContentType, StringComparison.OrdinalIgnoreCase))
                        {
                            requestMessage.Content.Headers.ContentType = new MediaTypeHeaderValue(request.Headers[key]);
                        }
                        else
                        {
                            requestMessage.Headers.TryAddWithoutValidation(key, request.Headers[key]);
                        }
                    }
                }
            }
            return(requestMessage);
        }
Esempio n. 22
0
        public async Task TestApplySessionForDataOperation()
        {
            List <ResourceType> resourceTypes = new List <ResourceType>()
            {
                ResourceType.Document,
                ResourceType.Conflict,
                ResourceType.Batch
            };

            List <OperationType> operationTypes = new List <OperationType>()
            {
                OperationType.Create,
                OperationType.Delete,
                OperationType.Read,
                OperationType.Upsert,
                OperationType.Replace
            };

            foreach (ResourceType resourceType in resourceTypes)
            {
                foreach (OperationType operationType in operationTypes)
                {
                    Assert.IsFalse(GatewayStoreModel.IsMasterOperation(
                                       resourceType,
                                       operationType),
                                   $"{resourceType}, {operationType}");

                    // Verify when user does set session token
                    DocumentServiceRequest dsr = DocumentServiceRequest.CreateFromName(
                        operationType,
                        "Test",
                        resourceType,
                        AuthorizationTokenType.PrimaryMasterKey);

                    string dsrSessionToken = Guid.NewGuid().ToString();
                    dsr.Headers.Add(HttpConstants.HttpHeaders.SessionToken, dsrSessionToken);

                    await GatewayStoreModel.ApplySessionTokenAsync(
                        dsr,
                        ConsistencyLevel.Session,
                        new Mock <ISessionContainer>().Object,
                        partitionKeyRangeCache : new Mock <PartitionKeyRangeCache>(null, null, null).Object,
                        clientCollectionCache : new Mock <ClientCollectionCache>(new SessionContainer("testhost"), this.GetGatewayStoreModelForConsistencyTest(), null, null).Object);


                    Assert.AreEqual(dsrSessionToken, dsr.Headers[HttpConstants.HttpHeaders.SessionToken]);

                    // Verify when user does not set session token
                    DocumentServiceRequest dsrNoSessionToken = DocumentServiceRequest.CreateFromName(
                        operationType,
                        "Test",
                        resourceType,
                        AuthorizationTokenType.PrimaryMasterKey);

                    Mock <ISessionContainer> sMock = new Mock <ISessionContainer>();
                    sMock.Setup(x => x.ResolveGlobalSessionToken(dsrNoSessionToken)).Returns(dsrSessionToken);

                    await GatewayStoreModel.ApplySessionTokenAsync(
                        dsrNoSessionToken,
                        ConsistencyLevel.Session,
                        sMock.Object,
                        partitionKeyRangeCache : new Mock <PartitionKeyRangeCache>(null, null, null).Object,
                        clientCollectionCache : new Mock <ClientCollectionCache>(new SessionContainer("testhost"), this.GetGatewayStoreModelForConsistencyTest(), null, null).Object);


                    if (dsrNoSessionToken.IsReadOnlyRequest || dsrNoSessionToken.OperationType == OperationType.Batch)
                    {
                        Assert.AreEqual(dsrSessionToken, dsrNoSessionToken.Headers[HttpConstants.HttpHeaders.SessionToken]);
                    }
                    else
                    {
                        Assert.IsNull(dsrNoSessionToken.Headers[HttpConstants.HttpHeaders.SessionToken]);
                    }
                }
            }

            // Verify stored procedure execute
            Assert.IsFalse(GatewayStoreModel.IsMasterOperation(
                               ResourceType.StoredProcedure,
                               OperationType.ExecuteJavaScript));

            DocumentServiceRequest dsrSprocExecute = DocumentServiceRequest.CreateFromName(
                OperationType.ExecuteJavaScript,
                "Test",
                ResourceType.StoredProcedure,
                AuthorizationTokenType.PrimaryMasterKey);

            string sessionToken = Guid.NewGuid().ToString();

            dsrSprocExecute.Headers.Add(HttpConstants.HttpHeaders.SessionToken, sessionToken);

            await GatewayStoreModel.ApplySessionTokenAsync(
                dsrSprocExecute,
                ConsistencyLevel.Session,
                new Mock <ISessionContainer>().Object,
                partitionKeyRangeCache : new Mock <PartitionKeyRangeCache>(null, null, null).Object,
                clientCollectionCache : new Mock <ClientCollectionCache>(new SessionContainer("testhost"), this.GetGatewayStoreModelForConsistencyTest(), null, null).Object);


            Assert.AreEqual(sessionToken, dsrSprocExecute.Headers[HttpConstants.HttpHeaders.SessionToken]);
        }
Esempio n. 23
0
        public async Task TestApplySessionForMasterOperation()
        {
            List <ResourceType> resourceTypes = new List <ResourceType>()
            {
                ResourceType.Database,
                ResourceType.Collection,
                ResourceType.User,
                ResourceType.Permission,
                ResourceType.StoredProcedure,
                ResourceType.Trigger,
                ResourceType.UserDefinedFunction,
                ResourceType.Offer,
                ResourceType.DatabaseAccount,
                ResourceType.PartitionKeyRange,
                ResourceType.UserDefinedType,
            };

            List <OperationType> operationTypes = new List <OperationType>()
            {
                OperationType.Create,
                OperationType.Delete,
                OperationType.Read,
                OperationType.Upsert,
                OperationType.Replace
            };

            foreach (ResourceType resourceType in resourceTypes)
            {
                foreach (OperationType operationType in operationTypes)
                {
                    Assert.IsTrue(GatewayStoreModel.IsMasterOperation(
                                      resourceType,
                                      operationType),
                                  $"{resourceType}, {operationType}");

                    DocumentServiceRequest dsr = DocumentServiceRequest.CreateFromName(
                        operationType,
                        "Test",
                        resourceType,
                        AuthorizationTokenType.PrimaryMasterKey);

                    dsr.Headers.Add(HttpConstants.HttpHeaders.SessionToken, Guid.NewGuid().ToString());

                    await GatewayStoreModel.ApplySessionTokenAsync(
                        dsr,
                        ConsistencyLevel.Session,
                        new Mock <ISessionContainer>().Object,
                        partitionKeyRangeCache : new Mock <PartitionKeyRangeCache>(null, null, null).Object,
                        clientCollectionCache : new Mock <ClientCollectionCache>(new SessionContainer("testhost"), this.GetGatewayStoreModelForConsistencyTest(), null, null).Object);

                    Assert.IsNull(dsr.Headers[HttpConstants.HttpHeaders.SessionToken]);
                }
            }

            Assert.IsTrue(GatewayStoreModel.IsMasterOperation(
                              ResourceType.Document,
                              OperationType.QueryPlan));

            DocumentServiceRequest dsrQueryPlan = DocumentServiceRequest.CreateFromName(
                OperationType.QueryPlan,
                "Test",
                ResourceType.Document,
                AuthorizationTokenType.PrimaryMasterKey);

            dsrQueryPlan.Headers.Add(HttpConstants.HttpHeaders.SessionToken, Guid.NewGuid().ToString());

            await GatewayStoreModel.ApplySessionTokenAsync(
                dsrQueryPlan,
                ConsistencyLevel.Session,
                new Mock <ISessionContainer>().Object,
                partitionKeyRangeCache : new Mock <PartitionKeyRangeCache>(null, null, null).Object,
                clientCollectionCache : new Mock <ClientCollectionCache>(new SessionContainer("testhost"), this.GetGatewayStoreModelForConsistencyTest(), null, null).Object);


            Assert.IsNull(dsrQueryPlan.Headers[HttpConstants.HttpHeaders.SessionToken]);
        }
Esempio n. 24
0
        public void TestApplySessionForDataOperation()
        {
            List <ResourceType> resourceTypes = new List <ResourceType>()
            {
                ResourceType.Document,
                ResourceType.Conflict,
                ResourceType.Batch
            };

            List <OperationType> operationTypes = new List <OperationType>()
            {
                OperationType.Create,
                OperationType.Delete,
                OperationType.Read,
                OperationType.Upsert,
                OperationType.Replace
            };

            foreach (ResourceType resourceType in resourceTypes)
            {
                foreach (OperationType operationType in operationTypes)
                {
                    Assert.IsFalse(GatewayStoreModel.IsMasterOperation(
                                       resourceType,
                                       operationType),
                                   $"{resourceType}, {operationType}");

                    // Verify when user does set session token
                    DocumentServiceRequest dsr = DocumentServiceRequest.CreateFromName(
                        operationType,
                        "Test",
                        resourceType,
                        AuthorizationTokenType.PrimaryMasterKey);

                    string dsrSessionToken = Guid.NewGuid().ToString();
                    dsr.Headers.Add(HttpConstants.HttpHeaders.SessionToken, dsrSessionToken);

                    GatewayStoreModel.ApplySessionToken(
                        dsr,
                        ConsistencyLevel.Session,
                        new Mock <ISessionContainer>().Object);

                    Assert.AreEqual(dsrSessionToken, dsr.Headers[HttpConstants.HttpHeaders.SessionToken]);

                    // Verify when user does not set session token
                    DocumentServiceRequest dsrNoSessionToken = DocumentServiceRequest.CreateFromName(
                        operationType,
                        "Test",
                        resourceType,
                        AuthorizationTokenType.PrimaryMasterKey);

                    Mock <ISessionContainer> sMock = new Mock <ISessionContainer>();
                    sMock.Setup(x => x.ResolveGlobalSessionToken(dsrNoSessionToken)).Returns(dsrSessionToken);

                    GatewayStoreModel.ApplySessionToken(
                        dsrNoSessionToken,
                        ConsistencyLevel.Session,
                        sMock.Object);

                    Assert.AreEqual(dsrSessionToken, dsrNoSessionToken.Headers[HttpConstants.HttpHeaders.SessionToken]);
                }
            }

            // Verify stored procedure execute
            Assert.IsFalse(GatewayStoreModel.IsMasterOperation(
                               ResourceType.StoredProcedure,
                               OperationType.ExecuteJavaScript));

            DocumentServiceRequest dsrSprocExecute = DocumentServiceRequest.CreateFromName(
                OperationType.ExecuteJavaScript,
                "Test",
                ResourceType.StoredProcedure,
                AuthorizationTokenType.PrimaryMasterKey);

            string sessionToken = Guid.NewGuid().ToString();

            dsrSprocExecute.Headers.Add(HttpConstants.HttpHeaders.SessionToken, sessionToken);

            GatewayStoreModel.ApplySessionToken(
                dsrSprocExecute,
                ConsistencyLevel.Session,
                new Mock <ISessionContainer>().Object);

            Assert.AreEqual(sessionToken, dsrSprocExecute.Headers[HttpConstants.HttpHeaders.SessionToken]);
        }
Esempio n. 25
0
        public async Task TestApplySessionForDataOperation()
        {
            List <ResourceType> resourceTypes = new List <ResourceType>()
            {
                ResourceType.Document,
                ResourceType.Conflict,
                ResourceType.Batch
            };

            List <OperationType> operationTypes = new List <OperationType>()
            {
                OperationType.Create,
                OperationType.Delete,
                OperationType.Read,
                OperationType.Upsert,
                OperationType.Replace
            };

            foreach (ResourceType resourceType in resourceTypes)
            {
                foreach (OperationType operationType in operationTypes)
                {
                    Assert.IsFalse(GatewayStoreModel.IsMasterOperation(
                                       resourceType,
                                       operationType),
                                   $"{resourceType}, {operationType}");
                    {
                        // Verify when user does set session token
                        DocumentServiceRequest dsr = DocumentServiceRequest.CreateFromName(
                            operationType,
                            "Test",
                            resourceType,
                            AuthorizationTokenType.PrimaryMasterKey);

                        string dsrSessionToken = Guid.NewGuid().ToString();
                        dsr.Headers.Add(HttpConstants.HttpHeaders.SessionToken, dsrSessionToken);

                        await GatewayStoreModel.ApplySessionTokenAsync(
                            dsr,
                            ConsistencyLevel.Session,
                            new Mock <ISessionContainer>().Object,
                            partitionKeyRangeCache : new Mock <PartitionKeyRangeCache>(null, null, null).Object,
                            clientCollectionCache : new Mock <ClientCollectionCache>(new SessionContainer("testhost"), this.GetGatewayStoreModelForConsistencyTest(), null, null).Object);


                        Assert.AreEqual(dsrSessionToken, dsr.Headers[HttpConstants.HttpHeaders.SessionToken]);
                    }

                    {
                        // Verify when user does not set session token
                        DocumentServiceRequest dsrNoSessionToken = DocumentServiceRequest.CreateFromName(
                            operationType,
                            "Test",
                            resourceType,
                            AuthorizationTokenType.PrimaryMasterKey);

                        string dsrSessionToken         = Guid.NewGuid().ToString();
                        Mock <ISessionContainer> sMock = new Mock <ISessionContainer>();
                        sMock.Setup(x => x.ResolveGlobalSessionToken(dsrNoSessionToken)).Returns(dsrSessionToken);

                        await GatewayStoreModel.ApplySessionTokenAsync(
                            dsrNoSessionToken,
                            ConsistencyLevel.Session,
                            sMock.Object,
                            partitionKeyRangeCache : new Mock <PartitionKeyRangeCache>(null, null, null).Object,
                            clientCollectionCache : new Mock <ClientCollectionCache>(new SessionContainer("testhost"), this.GetGatewayStoreModelForConsistencyTest(), null, null).Object);


                        if (dsrNoSessionToken.IsReadOnlyRequest || dsrNoSessionToken.OperationType == OperationType.Batch)
                        {
                            Assert.AreEqual(dsrSessionToken, dsrNoSessionToken.Headers[HttpConstants.HttpHeaders.SessionToken]);
                        }
                        else
                        {
                            Assert.IsNull(dsrNoSessionToken.Headers[HttpConstants.HttpHeaders.SessionToken]);
                        }
                    }

                    {
                        // Verify when partition key range is configured
                        DocumentServiceRequest dsr = DocumentServiceRequest.CreateFromName(
                            operationType,
                            "Test",
                            resourceType,
                            AuthorizationTokenType.PrimaryMasterKey);

                        string partitionKeyRangeId = "1";
                        dsr.Headers[WFConstants.BackendHeaders.PartitionKeyRangeId] = new PartitionKeyRangeIdentity(partitionKeyRangeId).ToHeader();

                        string dsrSessionToken         = Guid.NewGuid().ToString();
                        Mock <ISessionContainer> sMock = new Mock <ISessionContainer>();
                        sMock.Setup(x => x.ResolveGlobalSessionToken(dsr)).Returns(dsrSessionToken);

                        ContainerProperties containerProperties = ContainerProperties.CreateWithResourceId("ccZ1ANCszwk=");
                        containerProperties.Id = "TestId";
                        containerProperties.PartitionKeyPath = "/pk";

                        Mock <CollectionCache> mockCollectionCahce = new Mock <CollectionCache>(MockBehavior.Strict);
                        mockCollectionCahce.Setup(x => x.ResolveCollectionAsync(
                                                      dsr,
                                                      It.IsAny <CancellationToken>(),
                                                      NoOpTrace.Singleton)).Returns(Task.FromResult(containerProperties));

                        Mock <PartitionKeyRangeCache> mockPartitionKeyRangeCache = new Mock <PartitionKeyRangeCache>(MockBehavior.Strict, null, null, null);
                        mockPartitionKeyRangeCache.Setup(x => x.TryGetPartitionKeyRangeByIdAsync(
                                                             containerProperties.ResourceId,
                                                             partitionKeyRangeId,
                                                             It.IsAny <ITrace>(),
                                                             false)).Returns(Task.FromResult(new PartitionKeyRange()));

                        await GatewayStoreModel.ApplySessionTokenAsync(
                            dsr,
                            ConsistencyLevel.Session,
                            sMock.Object,
                            partitionKeyRangeCache : mockPartitionKeyRangeCache.Object,
                            clientCollectionCache : mockCollectionCahce.Object);

                        if (dsr.IsReadOnlyRequest || dsr.OperationType == OperationType.Batch)
                        {
                            Assert.AreEqual(dsrSessionToken, dsr.Headers[HttpConstants.HttpHeaders.SessionToken]);
                        }
                        else
                        {
                            Assert.IsNull(dsr.Headers[HttpConstants.HttpHeaders.SessionToken]);
                        }
                    }
                }
            }

            // Verify stored procedure execute
            Assert.IsFalse(GatewayStoreModel.IsMasterOperation(
                               ResourceType.StoredProcedure,
                               OperationType.ExecuteJavaScript));

            DocumentServiceRequest dsrSprocExecute = DocumentServiceRequest.CreateFromName(
                OperationType.ExecuteJavaScript,
                "Test",
                ResourceType.StoredProcedure,
                AuthorizationTokenType.PrimaryMasterKey);

            string sessionToken = Guid.NewGuid().ToString();

            dsrSprocExecute.Headers.Add(HttpConstants.HttpHeaders.SessionToken, sessionToken);

            await GatewayStoreModel.ApplySessionTokenAsync(
                dsrSprocExecute,
                ConsistencyLevel.Session,
                new Mock <ISessionContainer>().Object,
                partitionKeyRangeCache : new Mock <PartitionKeyRangeCache>(null, null, null).Object,
                clientCollectionCache : new Mock <ClientCollectionCache>(new SessionContainer("testhost"), this.GetGatewayStoreModelForConsistencyTest(), null, null).Object);


            Assert.AreEqual(sessionToken, dsrSprocExecute.Headers[HttpConstants.HttpHeaders.SessionToken]);
        }
        private static async Task <Tuple <bool, PartitionKeyRange> > TryResolvePartitionKeyRangeAsync(DocumentServiceRequest request,
                                                                                                      ISessionContainer sessionContainer,
                                                                                                      PartitionKeyRangeCache partitionKeyRangeCache,
                                                                                                      ClientCollectionCache clientCollectionCache,
                                                                                                      bool refreshCache)
        {
            if (refreshCache)
            {
                request.ForceMasterRefresh    = true;
                request.ForceNameCacheRefresh = true;
            }

            PartitionKeyRange   partitonKeyRange = null;
            ContainerProperties collection       = await clientCollectionCache.ResolveCollectionAsync(request, CancellationToken.None, NoOpTrace.Singleton);

            string partitionKeyString = request.Headers[HttpConstants.HttpHeaders.PartitionKey];

            if (partitionKeyString != null)
            {
                CollectionRoutingMap collectionRoutingMap = await partitionKeyRangeCache.TryLookupAsync(collectionRid : collection.ResourceId,
                                                                                                        previousValue : null,
                                                                                                        request : request,
                                                                                                        cancellationToken : CancellationToken.None,
                                                                                                        NoOpTrace.Singleton);

                if (refreshCache && collectionRoutingMap != null)
                {
                    collectionRoutingMap = await partitionKeyRangeCache.TryLookupAsync(collectionRid : collection.ResourceId,
                                                                                       previousValue : collectionRoutingMap,
                                                                                       request : request,
                                                                                       cancellationToken : CancellationToken.None,
                                                                                       NoOpTrace.Singleton);
                }

                partitonKeyRange = AddressResolver.TryResolveServerPartitionByPartitionKey(request: request,
                                                                                           partitionKeyString: partitionKeyString,
                                                                                           collectionCacheUptoDate: false,
                                                                                           collection: collection,
                                                                                           routingMap: collectionRoutingMap);
            }
            else if (request.PartitionKeyRangeIdentity != null)
            {
                PartitionKeyRangeIdentity partitionKeyRangeId = request.PartitionKeyRangeIdentity;
                partitonKeyRange = await partitionKeyRangeCache.TryGetPartitionKeyRangeByIdAsync(collection.ResourceId,
                                                                                                 partitionKeyRangeId.ToString(),
                                                                                                 NoOpTrace.Singleton,
                                                                                                 refreshCache);
            }

            if (partitonKeyRange == null)
            {
                if (refreshCache)
                {
                    return(new Tuple <bool, PartitionKeyRange>(false, null));
                }

                // need to refresh cache. Maybe split happened.
                return(await GatewayStoreModel.TryResolvePartitionKeyRangeAsync(request : request,
                                                                                sessionContainer : sessionContainer,
                                                                                partitionKeyRangeCache : partitionKeyRangeCache,
                                                                                clientCollectionCache : clientCollectionCache,
                                                                                refreshCache : true));
            }

            return(new Tuple <bool, PartitionKeyRange>(true, partitonKeyRange));
        }
Esempio n. 27
0
        private GatewayStoreModel GetGatewayStoreModelForConsistencyTest()
        {
            Func <HttpRequestMessage, Task <HttpResponseMessage> > messageHandler = async request =>
            {
                String content = await request.Content.ReadAsStringAsync();

                if (content.Equals("document"))
                {
                    IEnumerable <string> sessionTokens = request.Headers.GetValues("x-ms-session-token");
                    string sessionToken = "";
                    foreach (string singleToken in sessionTokens)
                    {
                        sessionToken = singleToken;
                        break;
                    }
                    Assert.AreEqual(sessionToken, "range_0:1#9#4=8#5=7");
                }
                else
                {
                    IEnumerable <string> enumerable;
                    Assert.IsFalse(request.Headers.TryGetValues("x-ms-session-token", out enumerable));
                }
                return(new HttpResponseMessage(HttpStatusCode.OK)
                {
                    Content = new StringContent("Response")
                });
            };

            Mock <IDocumentClientInternal> mockDocumentClient = new Mock <IDocumentClientInternal>();

            mockDocumentClient.Setup(client => client.ServiceEndpoint).Returns(new Uri("https://foo"));
            mockDocumentClient.Setup(client => client.ConsistencyLevel).Returns(Documents.ConsistencyLevel.Session);

            GlobalEndpointManager endpointManager = new GlobalEndpointManager(mockDocumentClient.Object, new ConnectionPolicy());

            SessionContainer sessionContainer = new SessionContainer(string.Empty);

            sessionContainer.SetSessionToken(
                ResourceId.NewDocumentCollectionId(42, 129).DocumentCollectionId.ToString(),
                "dbs/db1/colls/coll1",
                new StoreRequestNameValueCollection()
            {
                { HttpConstants.HttpHeaders.SessionToken, "range_0:1#9#4=8#5=7" }
            });

            DocumentClientEventSource eventSource        = DocumentClientEventSource.Instance;
            HttpMessageHandler        httpMessageHandler = new MockMessageHandler(messageHandler);

            GatewayStoreModel storeModel = new GatewayStoreModel(
                endpointManager,
                sessionContainer,
                ConsistencyLevel.Eventual,
                eventSource,
                null,
                MockCosmosUtil.CreateCosmosHttpClient(() => new HttpClient(httpMessageHandler)));

            ClientCollectionCache  clientCollectionCache  = new Mock <ClientCollectionCache>(new SessionContainer("testhost"), storeModel, null, null).Object;
            PartitionKeyRangeCache partitionKeyRangeCache = new Mock <PartitionKeyRangeCache>(null, storeModel, clientCollectionCache).Object;

            storeModel.SetCaches(partitionKeyRangeCache, clientCollectionCache);

            return(storeModel);
        }