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); } }
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); }
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); }
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(); } }
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); }
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); }
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; } }
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); } }
// 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); }
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=")); } } }
/// <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); } }
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; } }
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); }
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]); }
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]); }
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]); }
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)); }
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); }