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()); DocumentClientEventSource envetSource = new DocumentClientEventSource(); ISessionContainer sessionContainer = new SessionContainer(string.Empty); DocumentClientEventSource eventSource = new DocumentClientEventSource(); HttpMessageHandler messageHandler = new MockMessageHandler(sendFunc); GatewayStoreModel storeModel = new GatewayStoreModel( endpointManager, sessionContainer, TimeSpan.FromSeconds(5), ConsistencyLevel.Eventual, eventSource, new UserAgentContainer(), ApiType.None, messageHandler); using (DocumentServiceRequest request = DocumentServiceRequest.Create( Cosmos.Internal.OperationType.Query, Cosmos.Internal.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); }
private async Task GatewayStoreModel_Exception_NotUpdateSessionTokenOnKnownException(Exception ex) { const string originalSessionToken = "0:1#100#1=20#2=5#3=30"; 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, 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.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(string.Empty, sessionContainer.GetSessionToken("dbs/OVJwAA==/colls/OVJwAOcMtA0=")); } } }
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")); 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, "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=")); } } }
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()); } } } }
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(); } }
private GatewayStoreModel( GlobalEndpointManager endpointManager, ISessionContainer sessionContainer, ConsistencyLevel defaultConsistencyLevel, DocumentClientEventSource eventSource) { // CookieContainer is not really required, but is helpful in debugging. this.cookieJar = new CookieContainer(); this.endpointManager = endpointManager; this.sessionContainer = sessionContainer; this.defaultConsistencyLevel = defaultConsistencyLevel; this.eventSource = eventSource; }
public GatewayStoreModel( GlobalEndpointManager endpointManager, ISessionContainer sessionContainer, TimeSpan requestTimeout, ConsistencyLevel defaultConsistencyLevel, DocumentClientEventSource eventSource, JsonSerializerSettings serializerSettings, UserAgentContainer userAgent, ApiType apiType = ApiType.None, HttpMessageHandler messageHandler = null) { // CookieContainer is not really required, but is helpful in debugging. this.cookieJar = new CookieContainer(); this.endpointManager = endpointManager; HttpClient httpClient = new HttpClient(messageHandler ?? new HttpClientHandler { CookieContainer = this.cookieJar }); this.sessionContainer = sessionContainer; this.defaultConsistencyLevel = defaultConsistencyLevel; // Use max of client specified and our own request timeout value when sending // requests to gateway. Otherwise, we will have gateway's transient // error hiding retries are of no use. httpClient.Timeout = (requestTimeout > this.requestTimeout) ? requestTimeout : this.requestTimeout; httpClient.DefaultRequestHeaders.CacheControl = new CacheControlHeaderValue { NoCache = true }; httpClient.AddUserAgentHeader(userAgent); httpClient.AddApiTypeHeader(apiType); // Set requested API version header that can be used for // version enforcement. httpClient.DefaultRequestHeaders.Add(HttpConstants.HttpHeaders.Version, HttpConstants.Versions.CurrentVersion); httpClient.DefaultRequestHeaders.Add(HttpConstants.HttpHeaders.Accept, RuntimeConstants.MediaTypes.Json); this.eventSource = eventSource; this.gatewayStoreClient = new GatewayStoreClient( httpClient, this.eventSource, serializerSettings); }
public GatewayStoreModel( GlobalEndpointManager endpointManager, ISessionContainer sessionContainer, ConsistencyLevel defaultConsistencyLevel, DocumentClientEventSource eventSource, JsonSerializerSettings serializerSettings, HttpClient httpClient) { this.endpointManager = endpointManager; this.sessionContainer = sessionContainer; this.defaultConsistencyLevel = defaultConsistencyLevel; this.eventSource = eventSource; this.gatewayStoreClient = new GatewayStoreClient( httpClient, this.eventSource, serializerSettings); }
public GatewayStoreModel( GlobalEndpointManager endpointManager, ISessionContainer sessionContainer, TimeSpan requestTimeout, ConsistencyLevel defaultConsistencyLevel, DocumentClientEventSource eventSource, JsonSerializerSettings serializerSettings, UserAgentContainer userAgent, ApiType apiType, HttpMessageHandler messageHandler) : this(endpointManager, sessionContainer, defaultConsistencyLevel, eventSource) { this.InitializeGatewayStoreClient( requestTimeout, serializerSettings, userAgent, apiType, new HttpClient(messageHandler ?? new HttpClientHandler { CookieContainer = this.cookieJar })); }
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 DictionaryNameValueCollection() { { 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, TimeSpan.FromSeconds(50), ConsistencyLevel.Session, eventSource, null, new UserAgentContainer(), ApiType.None, httpMessageHandler); return(storeModel); }
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, MockCosmosUtil.CreateCosmosHttpClient( () => new HttpClient(messageHandler), eventSource)); 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(); } }