private async Task <CosmosContainerSettings> GetContainerSettingsAsync(CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); CosmosContainerSettings containerSettings = null; if (this.cosmosQueryContext.ResourceTypeEnum.IsCollectionChild()) { CollectionCache collectionCache = await this.cosmosQueryContext.QueryClient.GetCollectionCacheAsync(); using ( DocumentServiceRequest request = DocumentServiceRequest.Create( OperationType.Query, this.cosmosQueryContext.ResourceTypeEnum, this.cosmosQueryContext.ResourceLink.OriginalString, AuthorizationTokenType.Invalid)) //this request doesn't actually go to server { containerSettings = await collectionCache.ResolveCollectionAsync(request, cancellationToken); } } if (containerSettings == null) { throw new ArgumentException($"The container was not found for resource: {this.cosmosQueryContext.ResourceLink.OriginalString} "); } return(containerSettings); }
private DocumentServiceResponse ReadDatabaseFeedRequest(DocumentClient client, INameValueCollection headers) { DocumentServiceRequest request = DocumentServiceRequest.Create(OperationType.ReadFeed, null, ResourceType.Database, AuthorizationTokenType.PrimaryMasterKey, headers); var response = client.ReadFeedAsync(request, null).Result; return(response); }
public void TestSetSessionTokenDoesntWorkForMasterQueries() { SessionContainer sessionContainer = new SessionContainer("127.0.0.1"); var collectionResourceId1 = ResourceId.NewDocumentCollectionId(42, 129).DocumentCollectionId.ToString(); string collectionFullname1 = "dbs/db1/colls/collName1"; using (DocumentServiceRequest request = DocumentServiceRequest.Create(OperationType.ReadFeed, collectionFullname1 + "/docs/42", ResourceType.Collection, AuthorizationTokenType.PrimaryMasterKey, null)) { request.ResourceId = collectionResourceId1; sessionContainer.SetSessionToken(request, new StoreRequestNameValueCollection() { { HttpConstants.HttpHeaders.SessionToken, "range_0:1" } }); } using (DocumentServiceRequest request = DocumentServiceRequest.Create(OperationType.Read, collectionResourceId1, ResourceType.Document, AuthorizationTokenType.PrimaryMasterKey, null)) { ISessionToken token = sessionContainer.ResolvePartitionLocalSessionToken(request, "range_0"); Assert.AreEqual(null, token); } using (DocumentServiceRequest request = DocumentServiceRequest.CreateFromName(OperationType.Read, collectionFullname1 + "/docs/42", ResourceType.Document, AuthorizationTokenType.PrimaryMasterKey, null)) { ISessionToken token = sessionContainer.ResolvePartitionLocalSessionToken(request, "range_0"); Assert.AreEqual(null, token); } }
private DocumentServiceResponse CreateDocumentRequest(DocumentClient client, INameValueCollection headers) { Database database = client.CreateDatabaseAsync(new Database { Id = Guid.NewGuid().ToString() }).Result; PartitionKeyDefinition partitionKeyDefinition = new PartitionKeyDefinition { Paths = new System.Collections.ObjectModel.Collection <string>(new[] { "/id" }), Kind = PartitionKind.Hash }; DocumentCollection collection = client.CreateDocumentCollectionAsync(database.SelfLink, new DocumentCollection { Id = Guid.NewGuid().ToString(), PartitionKey = partitionKeyDefinition }).Result; var document = new Document() { Id = Guid.NewGuid().ToString() }; DocumentServiceRequest request = DocumentServiceRequest.Create(OperationType.Create, collection.SelfLink, document, ResourceType.Document, AuthorizationTokenType.Invalid, headers, SerializationFormattingPolicy.None); PartitionKey partitionKey = new PartitionKey(document.Id); request.Headers.Set(HttpConstants.HttpHeaders.PartitionKey, partitionKey.InternalKey.ToJsonString()); var response = client.CreateAsync(request, null).Result; return(response); }
public void AddressCacheMockTest() { // create a real document service request DocumentServiceRequest entity = DocumentServiceRequest.Create(OperationType.Read, ResourceType.Document, AuthorizationTokenType.PrimaryMasterKey); // setup mocks for address information AddressInformation[] addressInformation = new AddressInformation[3]; for (int i = 0; i < 3; i++) { addressInformation[i] = new AddressInformation { PhysicalUri = "http://replica-" + i.ToString("G", CultureInfo.CurrentCulture) }; } // Address Selector is an internal sealed class that can't be mocked, but its dependency // AddressCache can be mocked. Mock <IAddressResolver> mockAddressCache = new Mock <IAddressResolver>(); mockAddressCache.Setup( cache => cache.ResolveAsync( It.IsAny <DocumentServiceRequest>(), false /*forceRefresh*/, new CancellationToken())) .ReturnsAsync(new PartitionAddressInformation(addressInformation, null, null)); // validate that the mock works PartitionAddressInformation addressInfo = mockAddressCache.Object.ResolveAsync(entity, false, new CancellationToken()).Result; Assert.IsTrue(addressInfo.AllAddresses[0] == addressInformation[0]); }
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 void TransportClient_DoesThrowFor404WithReadSessionNotAvailable_WithUseStatusCodeForFailures() { using (DocumentServiceRequest request = DocumentServiceRequest.Create( OperationType.Query, ResourceType.Document, ExceptionlessTests.resourceUri, new MemoryStream(Encoding.UTF8.GetBytes("content1")), AuthorizationTokenType.PrimaryMasterKey, null)) { request.UseStatusCodeForFailures = true; StoreResponse mockStoreResponse404 = new StoreResponse(); mockStoreResponse404.ResponseHeaderNames = new string[1] { WFConstants.BackendHeaders.SubStatus }; mockStoreResponse404.ResponseHeaderValues = new string[1] { ((int)SubStatusCodes.ReadSessionNotAvailable).ToString() }; mockStoreResponse404.Status = (int)HttpStatusCode.NotFound; TransportClient.ThrowServerException( string.Empty, mockStoreResponse404, ExceptionlessTests.resourceUri, Guid.NewGuid(), request); } }
public void TestSetSessionTokenOverwritesLowerLSN() { SessionContainer sessionContainer = new SessionContainer("127.0.0.1"); var collectionResourceId1 = ResourceId.NewDocumentCollectionId(42, 129).DocumentCollectionId.ToString(); string collectionFullname1 = "dbs/db1/colls/collName1"; using (DocumentServiceRequest request = DocumentServiceRequest.Create(OperationType.Read, collectionFullname1 + "/docs/42", ResourceType.Document, AuthorizationTokenType.PrimaryMasterKey, null)) { request.ResourceId = collectionResourceId1; sessionContainer.SetSessionToken(request, new DictionaryNameValueCollection() { { HttpConstants.HttpHeaders.SessionToken, "range_0:1#100#4=90#5=1" } }); } using (DocumentServiceRequest request = DocumentServiceRequest.Create(OperationType.Read, collectionFullname1 + "/docs/42", ResourceType.Document, AuthorizationTokenType.PrimaryMasterKey, null)) { request.ResourceId = collectionResourceId1; sessionContainer.SetSessionToken(request, new DictionaryNameValueCollection() { { HttpConstants.HttpHeaders.SessionToken, "range_0:1#105#4=90#5=1" } }); } using (DocumentServiceRequest request = DocumentServiceRequest.Create(OperationType.Read, collectionResourceId1, ResourceType.Document, AuthorizationTokenType.PrimaryMasterKey, null)) { ISessionToken token = sessionContainer.ResolvePartitionLocalSessionToken(request, "range_0"); Assert.AreEqual(105, token.LSN); } }
private Uri ResolveEndpointForReadRequest(bool masterResourceType) { using (DocumentServiceRequest request = DocumentServiceRequest.Create(OperationType.Read, masterResourceType ? ResourceType.Database : ResourceType.Document, AuthorizationTokenType.PrimaryMasterKey)) { return(this.cache.ResolveServiceEndpoint(request)); } }
private async Task <ContainerProperties> ReadCollectionAsync( string collectionLink, IDocumentClientRetryPolicy retryPolicyInstance, ITrace trace, IClientSideRequestStatistics clientSideRequestStatistics, CancellationToken cancellationToken) { using (ITrace childTrace = trace.StartChild("Read Collection", TraceComponent.Transport, TraceLevel.Info)) { cancellationToken.ThrowIfCancellationRequested(); RequestNameValueCollection headers = new RequestNameValueCollection(); using (DocumentServiceRequest request = DocumentServiceRequest.Create( OperationType.Read, ResourceType.Collection, collectionLink, AuthorizationTokenType.PrimaryMasterKey, headers)) { headers.XDate = Rfc1123DateTimeCache.UtcNow(); request.RequestContext.ClientRequestStatistics = clientSideRequestStatistics ?? new ClientSideRequestStatisticsTraceDatum(DateTime.UtcNow, trace.Summary); if (clientSideRequestStatistics == null) { childTrace.AddDatum( "Client Side Request Stats", request.RequestContext.ClientRequestStatistics); } string authorizationToken = await this.tokenProvider.GetUserAuthorizationTokenAsync( request.ResourceAddress, PathsHelper.GetResourcePath(request.ResourceType), HttpConstants.HttpMethods.Get, request.Headers, AuthorizationTokenType.PrimaryMasterKey, childTrace); headers.Authorization = authorizationToken; using (new ActivityScope(Guid.NewGuid())) { retryPolicyInstance?.OnBeforeSendRequest(request); try { using (DocumentServiceResponse response = await this.storeModel.ProcessMessageAsync(request)) { return(CosmosResource.FromStream <ContainerProperties>(response)); } } catch (DocumentClientException ex) { childTrace.AddDatum("Exception Message", ex.Message); throw; } } } } }
public void TestGatewayAddressCacheAutoRefreshOnSuboptimalPartition() { FakeMessageHandler messageHandler = new FakeMessageHandler(); HttpClient httpClient = new HttpClient(messageHandler); httpClient.Timeout = TimeSpan.FromSeconds(120); GatewayAddressCache cache = new GatewayAddressCache( new Uri(GatewayAddressCacheTests.DatabaseAccountApiEndpoint), Documents.Client.Protocol.Https, this.mockTokenProvider.Object, this.mockServiceConfigReader.Object, MockCosmosUtil.CreateCosmosHttpClient(() => httpClient), suboptimalPartitionForceRefreshIntervalInSeconds: 2); int initialAddressesCount = cache.TryGetAddressesAsync( DocumentServiceRequest.Create(OperationType.Invalid, ResourceType.Address, AuthorizationTokenType.Invalid), this.testPartitionKeyRangeIdentity, this.serviceIdentity, false, CancellationToken.None).Result.AllAddresses.Count(); Assert.IsTrue(initialAddressesCount < this.targetReplicaSetSize); Task.Delay(3000).Wait(); int finalAddressCount = cache.TryGetAddressesAsync( DocumentServiceRequest.Create(OperationType.Invalid, ResourceType.Address, AuthorizationTokenType.Invalid), this.testPartitionKeyRangeIdentity, this.serviceIdentity, false, CancellationToken.None).Result.AllAddresses.Count(); Assert.IsTrue(finalAddressCount == this.targetReplicaSetSize); }
public async Task TestGatewayModelSession() { ContainerProperties containerProperties = await this.Container.GetCachedContainerPropertiesAsync( false, Trace.GetRootTrace("Test"), CancellationToken.None); ISessionContainer sessionContainer = this.cosmosClient.DocumentClient.sessionContainer; string docLink = "dbs/" + this.database.Id + "/colls/" + containerProperties.Id + "/docs/3"; Documents.Collections.INameValueCollection headers = new StoreRequestNameValueCollection(); headers.Set(HttpConstants.HttpHeaders.PartitionKey, "[\"Status3\"]"); DocumentServiceRequest request = DocumentServiceRequest.Create(OperationType.Read, ResourceType.Document, docLink, AuthorizationTokenType.PrimaryMasterKey, headers); string globalSessionToken = sessionContainer.ResolveGlobalSessionToken(request); Assert.IsTrue(globalSessionToken.Split(',').Length > 1); await GatewayStoreModel.ApplySessionTokenAsync(request, Cosmos.ConsistencyLevel.Session, sessionContainer, await this.cosmosClient.DocumentClient.GetPartitionKeyRangeCacheAsync(NoOpTrace.Singleton), await this.cosmosClient.DocumentClient.GetCollectionCacheAsync(NoOpTrace.Singleton)); string sessionToken = request.Headers[HttpConstants.HttpHeaders.SessionToken]; Assert.IsTrue(!string.IsNullOrEmpty(sessionToken) && sessionToken.Split(',').Length == 1); }
public void TransportClient_DoesNotThrowFor429_WithUseStatusCodeFor429() { using (DocumentServiceRequest request = DocumentServiceRequest.Create( OperationType.Query, ResourceType.Document, ExceptionlessTests.resourceUri, new MemoryStream(Encoding.UTF8.GetBytes("content1")), AuthorizationTokenType.PrimaryMasterKey, null)) { request.UseStatusCodeFor429 = true; StoreResponse mockStoreResponse429 = new StoreResponse { Status = (int)StatusCodes.TooManyRequests }; TransportClient.ThrowServerException( string.Empty, mockStoreResponse429, ExceptionlessTests.resourceUri, Guid.NewGuid(), request); } }
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 TestResolvePartitionLocalSessionTokenReturnsNullOnCollectionMiss() { SessionContainer sessionContainer = new SessionContainer("127.0.0.1"); var collectionResourceId1 = ResourceId.NewDocumentCollectionId(42, 129).DocumentCollectionId.ToString(); string collectionFullname = "dbs/db1/colls/collName"; sessionContainer.SetSessionToken( collectionResourceId1, collectionFullname, new DictionaryNameValueCollection() { { HttpConstants.HttpHeaders.SessionToken, "range_0:1#100#4=90#5=1" } } ); sessionContainer.SetSessionToken( collectionResourceId1, collectionFullname, new DictionaryNameValueCollection() { { HttpConstants.HttpHeaders.SessionToken, "range_1:1#101#4=90#5=1" } } ); var collectionResourceId2 = ResourceId.NewDocumentCollectionId(42, 130).DocumentCollectionId.ToString(); using (DocumentServiceRequest request = DocumentServiceRequest.Create(OperationType.Read, collectionResourceId2, ResourceType.Document, AuthorizationTokenType.PrimaryMasterKey, null)) { ISessionToken token = sessionContainer.ResolvePartitionLocalSessionToken(request, "range_1"); Assert.AreEqual(null, token); } }
private async Task <DocumentServiceResponse> ExecutePartitionKeyRangeReadChangeFeedAsync(string collectionRid, INameValueCollection headers, ITrace trace) { using (ITrace childTrace = trace.StartChild("Read PartitionKeyRange Change Feed", TraceComponent.Transport, Tracing.TraceLevel.Info)) { using (DocumentServiceRequest request = DocumentServiceRequest.Create( OperationType.ReadFeed, collectionRid, ResourceType.PartitionKeyRange, AuthorizationTokenType.PrimaryMasterKey, headers)) { string authorizationToken = null; try { authorizationToken = (await this.authorizationTokenProvider.GetUserAuthorizationAsync( request.ResourceAddress, PathsHelper.GetResourcePath(request.ResourceType), HttpConstants.HttpMethods.Get, request.Headers, AuthorizationTokenType.PrimaryMasterKey)).token; } catch (UnauthorizedException) { } if (authorizationToken == null) { // User doesn't have rid based resource token. Maybe he has name based. throw new NotSupportedException("Resource tokens are not supported"); ////CosmosContainerSettings collection = await this.collectionCache.ResolveCollectionAsync(request, CancellationToken.None); ////authorizationToken = //// this.authorizationTokenProvider.GetUserAuthorizationTokenAsync( //// collection.AltLink, //// PathsHelper.GetResourcePath(request.ResourceType), //// HttpConstants.HttpMethods.Get, //// request.Headers, //// AuthorizationTokenType.PrimaryMasterKey); } request.Headers[HttpConstants.HttpHeaders.Authorization] = authorizationToken; using (new ActivityScope(Guid.NewGuid())) { try { return(await this.storeModel.ProcessMessageAsync(request)); } catch (DocumentClientException ex) { childTrace.AddDatum("Exception Message", ex.Message); throw; } } } } }
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(); } }
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); }
private Uri ResolveEndpointForWriteRequest(ResourceType resourceType, bool useAlternateWriteEndpoint) { using (DocumentServiceRequest request = DocumentServiceRequest.Create(OperationType.Create, resourceType, AuthorizationTokenType.PrimaryMasterKey)) { request.RequestContext.RouteToLocation(useAlternateWriteEndpoint ? 1 : 0, resourceType.IsCollectionChild()); return(this.cache.ResolveServiceEndpoint(request)); } }
private DocumentServiceResponse ReadDocumentRequest(DocumentClient client, Document doc, INameValueCollection headers) { DocumentServiceRequest request = DocumentServiceRequest.Create(OperationType.Read, ResourceType.Document, doc.SelfLink, AuthorizationTokenType.PrimaryMasterKey, headers); request.Headers.Set(HttpConstants.HttpHeaders.PartitionKey, (new PartitionKey(doc.Id)).InternalKey.ToJsonString()); var retrievedDocResponse = client.ReadAsync(request, null).Result; return(retrievedDocResponse); }
public void VerifyAllReadRegionsAreVisited(int numOfReadRegions) { Mock <IGlobalEndpointManager> mockEndpointManager = new Mock <IGlobalEndpointManager>(MockBehavior.Strict); GlobalPartitionEndpointManagerCore failoverManager = new GlobalPartitionEndpointManagerCore(mockEndpointManager.Object); List <Uri> readRegions = new List <Uri>(); for (int i = 0; i < numOfReadRegions; i++) { readRegions.Add(new Uri($"https://localhost:{i}/")); } mockEndpointManager.Setup(x => x.ReadEndpoints).Returns(() => new ReadOnlyCollection <Uri>(readRegions)); // Create a random pk range PartitionKeyRange partitionKeyRange = new PartitionKeyRange() { Id = "0", MinInclusive = "", MaxExclusive = "BB" }; PartitionKeyRange partitionKeyRangeNotOverriden = new PartitionKeyRange() { Id = "1", MinInclusive = "BB", MaxExclusive = "FF" }; using DocumentServiceRequest createRequest = DocumentServiceRequest.Create(OperationType.Create, ResourceType.Document, AuthorizationTokenType.PrimaryMasterKey); createRequest.RequestContext.ResolvedPartitionKeyRange = partitionKeyRange; createRequest.RequestContext.RouteToLocation(readRegions.First()); mockEndpointManager.Setup(x => x.CanUseMultipleWriteLocations(createRequest)).Returns(false); foreach (Uri region in readRegions) { Assert.AreEqual(region, createRequest.RequestContext.LocationEndpointToRoute); bool tryFailover = failoverManager.TryMarkEndpointUnavailableForPartitionKeyRange( createRequest); // If there are no more regions to failover it will return false. if (region == readRegions.Last()) { Assert.IsFalse(tryFailover); Assert.IsFalse(failoverManager.TryAddPartitionLevelLocationOverride(createRequest)); } else { Assert.IsTrue(tryFailover); Assert.IsTrue(failoverManager.TryAddPartitionLevelLocationOverride(createRequest)); Assert.AreNotEqual(region, createRequest.RequestContext.LocationEndpointToRoute); } } }
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 DocumentServiceRequest CreateRequest(bool isReadRequest, bool isMasterResourceType) { if (isReadRequest) { return(DocumentServiceRequest.Create(OperationType.Read, isMasterResourceType ? ResourceType.Database : ResourceType.Document, AuthorizationTokenType.PrimaryMasterKey)); } else { return(DocumentServiceRequest.Create(OperationType.Create, isMasterResourceType ? ResourceType.Database : ResourceType.Document, AuthorizationTokenType.PrimaryMasterKey)); } }
public void TestClearTokenKeepsUnmatchedCollection() { SessionContainer sessionContainer = new SessionContainer("127.0.0.1"); var collectionResourceId1 = ResourceId.NewDocumentCollectionId(42, 129).DocumentCollectionId.ToString(); string collectionFullname1 = "dbs/db1/colls/collName1"; sessionContainer.SetSessionToken( collectionResourceId1, collectionFullname1, new DictionaryNameValueCollection() { { HttpConstants.HttpHeaders.SessionToken, "range_0:1#100#4=90#5=1" } } ); var collectionResourceId2 = ResourceId.NewDocumentCollectionId(42, 130).DocumentCollectionId.ToString(); string collectionFullname2 = "dbs/db1/colls/collName2"; sessionContainer.SetSessionToken( collectionResourceId2, collectionFullname2, new DictionaryNameValueCollection() { { HttpConstants.HttpHeaders.SessionToken, "range_0:1#100#4=90#5=1" } } ); using (DocumentServiceRequest request = DocumentServiceRequest.Create(OperationType.Read, collectionResourceId1, ResourceType.Document, AuthorizationTokenType.PrimaryMasterKey, null)) { ISessionToken token = sessionContainer.ResolvePartitionLocalSessionToken(request, "range_0"); Assert.AreEqual(100, token.LSN); } using (DocumentServiceRequest request = DocumentServiceRequest.Create(OperationType.Read, collectionResourceId2, ResourceType.Document, AuthorizationTokenType.PrimaryMasterKey, null)) { ISessionToken token = sessionContainer.ResolvePartitionLocalSessionToken(request, "range_0"); Assert.AreEqual(100, token.LSN); } sessionContainer.ClearTokenByResourceId(collectionResourceId1); using (DocumentServiceRequest request = DocumentServiceRequest.Create(OperationType.Read, collectionResourceId1, ResourceType.Document, AuthorizationTokenType.PrimaryMasterKey, null)) { ISessionToken token = sessionContainer.ResolvePartitionLocalSessionToken(request, "range_0"); Assert.AreEqual(null, token); } using (DocumentServiceRequest request = DocumentServiceRequest.Create(OperationType.Read, collectionResourceId2, ResourceType.Document, AuthorizationTokenType.PrimaryMasterKey, null)) { ISessionToken token = sessionContainer.ResolvePartitionLocalSessionToken(request, "range_0"); Assert.AreEqual(100, token.LSN); } }
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=")); } } }
public void TransportClientMockTest() { // create a real document service request DocumentServiceRequest entity = DocumentServiceRequest.Create(OperationType.Read, ResourceType.Document, AuthorizationTokenType.PrimaryMasterKey); // setup mocks for address information AddressInformation[] addressInformation = new AddressInformation[3]; // construct URIs that look like the actual uri // rntbd://yt1prdddc01-docdb-1.documents.azure.com:14003/apps/ce8ab332-f59e-4ce7-a68e-db7e7cfaa128/services/68cc0b50-04c6-4716-bc31-2dfefd29e3ee/partitions/5604283d-0907-4bf4-9357-4fa9e62de7b5/replicas/131170760736528207s/ for (int i = 0; i < 3; i++) { addressInformation[i] = new AddressInformation { PhysicalUri = "rntbd://dummytenant.documents.azure.com:14003/apps/APPGUID/services/SERVICEGUID/partitions/PARTITIONGUID/replicas/" + i.ToString("G", CultureInfo.CurrentCulture) + (i == 0 ? "p" : "s") + "/" }; } // create objects for all the dependencies of the StoreReader Mock <TransportClient> mockTransportClient = new Mock <TransportClient>(); // create mock store response object StoreResponse mockStoreResponse = new StoreResponse { // set lsn and activityid on the store response. Headers = new DictionaryNameValueCollection( new NameValueCollection() { { WFConstants.BackendHeaders.LSN, "50" }, { WFConstants.BackendHeaders.ActivityId, "ACTIVITYID1_1" } }) }; // setup mock transport client mockTransportClient.Setup( client => client.InvokeResourceOperationAsync( new Uri(addressInformation[0].PhysicalUri), It.IsAny <DocumentServiceRequest>())) .ReturnsAsync(mockStoreResponse); TransportClient mockTransportClientObject = mockTransportClient.Object; // get response from mock object StoreResponse response = mockTransportClientObject.InvokeResourceOperationAsync(new Uri(addressInformation[0].PhysicalUri), entity).Result; // validate that the LSN matches Assert.IsTrue(response.LSN == 50); response.TryGetHeaderValue(WFConstants.BackendHeaders.ActivityId, out string activityId); // validate that the ActivityId Matches Assert.IsTrue(activityId == "ACTIVITYID1_1"); }
private async Task <ShouldRetryResult> ShouldRetryAsyncInternal( HttpStatusCode?statusCode, SubStatusCodes?subStatusCode, CancellationToken cancellationToken, Func <Task <ShouldRetryResult> > continueIfNotHandled) { if (statusCode.HasValue && subStatusCode.HasValue && statusCode == HttpStatusCode.Gone && subStatusCode == SubStatusCodes.PartitionKeyRangeGone) { if (this.retried) { return(ShouldRetryResult.NoRetry()); } using (DocumentServiceRequest request = DocumentServiceRequest.Create( OperationType.Read, ResourceType.Collection, this.collectionLink, null, AuthorizationTokenType.PrimaryMasterKey)) { CosmosContainerSettings collection = await this.collectionCache.ResolveCollectionAsync(request, cancellationToken); CollectionRoutingMap routingMap = await this.partitionKeyRangeCache.TryLookupAsync(collection.ResourceId, null, request, false, cancellationToken); if (routingMap != null) { // Force refresh. await this.partitionKeyRangeCache.TryLookupAsync( collection.ResourceId, routingMap, request, false, cancellationToken); } } this.retried = true; return(ShouldRetryResult.RetryAfter(TimeSpan.FromSeconds(0))); } if (continueIfNotHandled != null) { return(await continueIfNotHandled() ?? ShouldRetryResult.NoRetry()); } else { return(await Task.FromResult(ShouldRetryResult.NoRetry())); } }
private async Task <ShouldRetryResult> ShouldRetryInternalAsync( HttpStatusCode?statusCode, SubStatusCodes?subStatusCode, CancellationToken cancellationToken) { if (!statusCode.HasValue && (!subStatusCode.HasValue || subStatusCode.Value == SubStatusCodes.Unknown)) { return(null); } if (statusCode == HttpStatusCode.Gone && subStatusCode == SubStatusCodes.PartitionKeyRangeGone) { if (this.retried) { return(ShouldRetryResult.NoRetry()); } using (DocumentServiceRequest request = DocumentServiceRequest.Create( OperationType.Read, ResourceType.Collection, this.collectionLink, null, AuthorizationTokenType.PrimaryMasterKey)) { ContainerProperties collection = await this.collectionCache.ResolveCollectionAsync(request, cancellationToken, this.trace); CollectionRoutingMap routingMap = await this.partitionKeyRangeCache.TryLookupAsync( collectionRid : collection.ResourceId, previousValue : null, request : request, trace : this.trace); if (routingMap != null) { // Force refresh. await this.partitionKeyRangeCache.TryLookupAsync( collectionRid : collection.ResourceId, previousValue : routingMap, request : request, trace : this.trace); } } this.retried = true; return(ShouldRetryResult.RetryAfter(TimeSpan.FromSeconds(0))); } return(null); }
public void TestSessionContainer() { SessionContainer sessionContainer = new SessionContainer("127.0.0.1"); int numCollections = 2; int numPartitionKeyRangeIds = 5; for (uint i = 0; i < numCollections; i++) { var collectionResourceId = ResourceId.NewDocumentCollectionId(42, 129 + i).DocumentCollectionId.ToString(); string collectionFullname = "dbs/db1/colls/collName_" + i; for (int j = 0; j < numPartitionKeyRangeIds; j++) { string partitionKeyRangeId = "range_" + j; string lsn = "1#" + j + "#4=90#5=2"; sessionContainer.SetSessionToken( collectionResourceId, collectionFullname, new DictionaryNameValueCollection() { { HttpConstants.HttpHeaders.SessionToken, $"{partitionKeyRangeId}:{lsn}" } }); } } using (DocumentServiceRequest request = DocumentServiceRequest.Create( OperationType.ReadFeed, ResourceType.Collection, new Uri("https://foo.com/dbs/db1/colls/collName_1", UriKind.Absolute), new MemoryStream(Encoding.UTF8.GetBytes("content1")), AuthorizationTokenType.PrimaryMasterKey, null)) { ISessionToken sessionToken = sessionContainer.ResolvePartitionLocalSessionToken(request, "range_1"); Assert.IsTrue(sessionToken.LSN == 1); DocumentServiceRequestContext dsrContext = new DocumentServiceRequestContext(); PartitionKeyRange resolvedPKRange = new PartitionKeyRange(); resolvedPKRange.Id = "range_" + (numPartitionKeyRangeIds + 10); resolvedPKRange.Parents = new Collection <string>(new List <string> { "range_2", "range_x" }); dsrContext.ResolvedPartitionKeyRange = resolvedPKRange; request.RequestContext = dsrContext; sessionToken = sessionContainer.ResolvePartitionLocalSessionToken(request, resolvedPKRange.Id); Assert.IsTrue(sessionToken.LSN == 2); } }