public StoreResultStatistics( DocumentClientException exception, StatusCodes statusCode, SubStatusCodes subStatusCode, string partitionKeyRangeId, long lsn, double requestCharge, bool isValid, Uri storePhysicalAddress, long globalCommittedLSN, long itemLSN, ISessionToken sessionToken, bool usingLocalLSN, string activityId) { this.Exception = exception; this.StatusCode = statusCode; this.SubStatusCode = subStatusCode; this.PartitionKeyRangeId = partitionKeyRangeId; this.LSN = lsn; this.RequestCharge = requestCharge; this.IsValid = isValid; this.StorePhysicalAddress = storePhysicalAddress; this.GlobalCommittedLSN = globalCommittedLSN; this.ItemLSN = itemLSN; this.SessionToken = sessionToken; this.UsingLocalLSN = usingLocalLSN; this.ActivityId = activityId; }
public PointOperationStatisticsTraceDatum( string activityId, HttpStatusCode statusCode, SubStatusCodes subStatusCode, DateTime responseTimeUtc, double requestCharge, string errorMessage, HttpMethod method, string requestUri, string requestSessionToken, string responseSessionToken, string beLatencyInMs) { this.ActivityId = activityId; this.StatusCode = statusCode; this.SubStatusCode = subStatusCode; this.RequestCharge = requestCharge; this.ErrorMessage = errorMessage; this.Method = method; this.RequestUri = requestUri; this.RequestSessionToken = requestSessionToken; this.ResponseSessionToken = responseSessionToken; this.ResponseTimeUtc = responseTimeUtc; this.BELatencyInMs = beLatencyInMs; }
public static DocDbError ClassifyClientException(DocumentClientException clientException) { SubStatusCodes subStatusCode = clientException.GetSubStatusCode(); if (clientException.StatusCode == HttpStatusCode.NotFound && subStatusCode != SubStatusCodes.ReadSessionNotAvailable) { return(DocDbError.PartitionNotFound); } if (clientException.StatusCode == HttpStatusCode.Gone && (subStatusCode == SubStatusCodes.PartitionKeyRangeGone || subStatusCode == SubStatusCodes.CompletingSplit)) { return(DocDbError.PartitionSplit); } if (clientException.StatusCode == (HttpStatusCode)429 || clientException.StatusCode >= HttpStatusCode.InternalServerError) { return(DocDbError.TransientError); } // Temporary workaround to compare exception message, until server provides better way of handling this case. if (clientException.Message.Contains("Reduce page size and try again.")) { return(DocDbError.MaxItemCountTooLarge); } return(DocDbError.Undefined); }
public static QueryResponseCore CreateFailureResponse( HttpStatusCode httpStatusCode, SubStatusCodes subStatusCodes, string errorMessage) { IReadOnlyCollection <QueryPageDiagnostics> diagnostics = new List <QueryPageDiagnostics>() { new QueryPageDiagnostics("0", "SomeQueryMetricText", "SomeIndexUtilText", new PointOperationStatistics( Guid.NewGuid().ToString(), System.Net.HttpStatusCode.Gone, subStatusCode: SubStatusCodes.PartitionKeyRangeGone, requestCharge: 10.4, errorMessage: null, method: HttpMethod.Post, requestUri: new Uri("http://localhost.com"), requestSessionToken: null, responseSessionToken: null, clientSideRequestStatistics: null), new SchedulingStopwatch()) }; QueryResponseCore splitResponse = QueryResponseCore.CreateFailure( statusCode: httpStatusCode, subStatusCodes: subStatusCodes, errorMessage: errorMessage, requestCharge: 10.4, activityId: Guid.NewGuid().ToString(), diagnostics: diagnostics); return(splitResponse); }
private async Task RetryHandlerDontRetryOnStatusCode( HttpStatusCode statusCode, SubStatusCodes subStatusCode = SubStatusCodes.Unknown) { int handlerCalls = 0; TestHandler testHandler = new TestHandler((request, response) => { handlerCalls++; if (handlerCalls == 0) { return(TestHandler.ReturnStatusCode(statusCode, subStatusCode)); } return(TestHandler.ReturnSuccess()); }); CosmosClient client = MockDocumentClient.CreateMockCosmosClient(); RetryHandler retryHandler = new RetryHandler(client.DocumentClient.ResetSessionTokenRetryPolicy); retryHandler.InnerHandler = testHandler; RequestInvokerHandler invoker = new RequestInvokerHandler(client); invoker.InnerHandler = retryHandler; CosmosRequestMessage requestMessage = new CosmosRequestMessage(HttpMethod.Delete, RetryHandlerTests.TestUri); requestMessage.Headers.Add(HttpConstants.HttpHeaders.PartitionKey, "[]"); requestMessage.ResourceType = ResourceType.Document; requestMessage.OperationType = OperationType.Read; await invoker.SendAsync(requestMessage, new CancellationToken()); int expectedHandlerCalls = 1; Assert.AreEqual(expectedHandlerCalls, handlerCalls); }
/// <summary> /// Initializes a new instance of the <see cref="PartitionKeyRangeBatchResponse"/> class. /// </summary> /// <param name="statusCode">Completion status code of the batch request.</param> /// <param name="subStatusCode">Provides further details about why the batch was not processed.</param> /// <param name="operations">Operations that were supposed to be executed, but weren't.</param> /// <param name="errorMessage">The reason for failure if any.</param> // This constructor is expected to be used when the batch is not executed at all (if it is a bad request). internal PartitionKeyRangeBatchResponse( HttpStatusCode statusCode, SubStatusCodes subStatusCode, string errorMessage, IReadOnlyList <ItemBatchOperation> operations) : base(statusCode, subStatusCode, errorMessage, operations) { }
private async Task CaptureSessionTokenAndHandleSplitAsync( HttpStatusCode?statusCode, SubStatusCodes subStatusCode, DocumentServiceRequest request, INameValueCollection responseHeaders) { // Exceptionless can try to capture session token from CompleteResponse if (request.IsValidStatusCodeForExceptionlessRetry((int)statusCode, subStatusCode)) { // Not capturing on master resources if (ReplicatedResourceClient.IsMasterResource(request.ResourceType)) { return; } // Only capturing on 409, 412, 404 && !1002 if (statusCode != HttpStatusCode.PreconditionFailed && statusCode != HttpStatusCode.Conflict && (statusCode != HttpStatusCode.NotFound || subStatusCode == SubStatusCodes.ReadSessionNotAvailable)) { return; } } if (request.ResourceType == ResourceType.Collection && request.OperationType == OperationType.Delete) { string resourceId; if (request.IsNameBased) { resourceId = responseHeaders[HttpConstants.HttpHeaders.OwnerId]; } else { resourceId = request.ResourceId; } this.sessionContainer.ClearTokenByResourceId(resourceId); } else { this.sessionContainer.SetSessionToken(request, responseHeaders); PartitionKeyRange detectedPartitionKeyRange = request.RequestContext.ResolvedPartitionKeyRange; string partitionKeyRangeInResponse = responseHeaders[HttpConstants.HttpHeaders.PartitionKeyRangeId]; if (detectedPartitionKeyRange != null && !string.IsNullOrEmpty(partitionKeyRangeInResponse) && !string.IsNullOrEmpty(request.RequestContext.ResolvedCollectionRid) && !partitionKeyRangeInResponse.Equals(detectedPartitionKeyRange.Id, StringComparison.OrdinalIgnoreCase)) { // The request ended up being on a different partition unknown to the client, so we better refresh the caches await this.partitionKeyRangeCache.TryGetPartitionKeyRangeByIdAsync( request.RequestContext.ResolvedCollectionRid, partitionKeyRangeInResponse, NoOpTrace.Singleton, forceRefresh : true); } } }
internal BatchResponse( HttpStatusCode statusCode, SubStatusCodes subStatusCode, string errorMessage, double requestCharge, TimeSpan?retryAfter, string activityId, ServerBatchRequest serverRequest, CosmosSerializer serializer) : this(statusCode, subStatusCode, errorMessage, requestCharge, retryAfter, activityId, serverRequest.Operations, serializer) { }
private static async Task <ResponseMessage> GenerateResponseAsync( ItemBatchOperation itemBatchOperation, HttpStatusCode httpStatusCode, SubStatusCodes subStatusCode) { List <TransactionalBatchOperationResult> results = new List <TransactionalBatchOperationResult>(); ItemBatchOperation[] arrayOperations = new ItemBatchOperation[1]; results.Add( new TransactionalBatchOperationResult(httpStatusCode) { ETag = itemBatchOperation.Id, SubStatusCode = subStatusCode }); arrayOperations[0] = itemBatchOperation; MemoryStream responseContent = await new BatchResponsePayloadWriter(results).GeneratePayloadAsync(); _ = await SinglePartitionKeyServerBatchRequest.CreateAsync( partitionKey : null, operations : new ArraySegment <ItemBatchOperation>(arrayOperations), serializerCore : MockCosmosUtil.Serializer, trace : NoOpTrace.Singleton, cancellationToken : CancellationToken.None); ResponseMessage responseMessage = new ResponseMessage(httpStatusCode) { Content = responseContent, }; using (responseMessage.Trace = Trace.GetRootTrace("Test Trace")) { responseMessage.Trace.AddDatum( "Point Operation Statistics", new PointOperationStatisticsTraceDatum( activityId: Guid.NewGuid().ToString(), statusCode: httpStatusCode, subStatusCode: subStatusCode, responseTimeUtc: DateTime.UtcNow, requestCharge: 0, errorMessage: string.Empty, method: HttpMethod.Get, requestUri: "http://localhost", requestSessionToken: null, responseSessionToken: null, beLatencyInMs: "0.42")); } responseMessage.Headers.SubStatusCode = subStatusCode; return(responseMessage); }
/// <summary> /// Initializes a new instance of the <see cref="BatchResponse"/> class. /// This method is intended to be used only when a response from the server is not available. /// </summary> /// <param name="statusCode">Indicates why the batch was not processed.</param> /// <param name="subStatusCode">Provides further details about why the batch was not processed.</param> /// <param name="errorMessage">The reason for failure.</param> /// <param name="operations">Operations that were to be executed.</param> internal BatchResponse( HttpStatusCode statusCode, SubStatusCodes subStatusCode, string errorMessage, IReadOnlyList <ItemBatchOperation> operations) : this(statusCode, subStatusCode, errorMessage, requestCharge : 0, retryAfter : null, activityId : Guid.Empty.ToString(), operations : operations, serializer : null) { }
/// <summary> /// Initializes a new instance of the <see cref="TransactionalBatchResponse"/> class. /// This method is intended to be used only when a response from the server is not available. /// </summary> /// <param name="statusCode">Indicates why the batch was not processed.</param> /// <param name="subStatusCode">Provides further details about why the batch was not processed.</param> /// <param name="errorMessage">The reason for failure.</param> /// <param name="operations">Operations that were to be executed.</param> /// <param name="diagnosticsContext">Diagnostics for the operation</param> internal TransactionalBatchResponse( HttpStatusCode statusCode, SubStatusCodes subStatusCode, string errorMessage, IReadOnlyList <ItemBatchOperation> operations, CosmosDiagnosticsContext diagnosticsContext) : this(statusCode, subStatusCode, errorMessage, new Headers(), diagnosticsContext : diagnosticsContext, operations : operations, serializer : null) { this.CreateAndPopulateResults(operations); }
/// <summary> /// Initializes a new instance of the <see cref="TransactionalBatchResponse"/> class. /// This method is intended to be used only when a response from the server is not available. /// </summary> /// <param name="statusCode">Indicates why the batch was not processed.</param> /// <param name="subStatusCode">Provides further details about why the batch was not processed.</param> /// <param name="errorMessage">The reason for failure.</param> /// <param name="operations">Operations that were to be executed.</param> /// <param name="trace">Diagnostics for the operation</param> internal TransactionalBatchResponse( HttpStatusCode statusCode, SubStatusCodes subStatusCode, string errorMessage, IReadOnlyList <ItemBatchOperation> operations, ITrace trace) : this(statusCode, subStatusCode, errorMessage, new Headers(), trace : trace, operations : operations, serializer : null) { this.CreateAndPopulateResults(operations, trace); }
public static QueryResponseCore CreateFailureResponse( HttpStatusCode httpStatusCode, SubStatusCodes subStatusCodes, string errorMessage) { QueryResponseCore splitResponse = QueryResponseCore.CreateFailure( statusCode: httpStatusCode, subStatusCodes: subStatusCodes, errorMessage: errorMessage, requestCharge: 10.4, activityId: Guid.NewGuid().ToString(), queryMetricsText: null, queryMetrics: null); return(splitResponse); }
/// <summary> /// Initializes a new instance of the <see cref="TransactionalBatchResponse"/> class. /// This method is intended to be used only when a response from the server is not available. /// </summary> /// <param name="statusCode">Indicates why the batch was not processed.</param> /// <param name="subStatusCode">Provides further details about why the batch was not processed.</param> /// <param name="errorMessage">The reason for failure.</param> /// <param name="operations">Operations that were to be executed.</param> internal TransactionalBatchResponse( HttpStatusCode statusCode, SubStatusCodes subStatusCode, string errorMessage, IReadOnlyList <ItemBatchOperation> operations) : this(statusCode, subStatusCode, errorMessage, requestCharge : 0, retryAfter : null, activityId : Guid.Empty.ToString(), cosmosDiagnostics : null, operations : operations, serializer : null) { this.CreateAndPopulateResults(operations); }
private TransactionalBatchResponse( HttpStatusCode statusCode, SubStatusCodes subStatusCode, string errorMessage, Headers headers, ITrace trace, IReadOnlyList <ItemBatchOperation> operations, CosmosSerializerCore serializer) { this.StatusCode = statusCode; this.SubStatusCode = subStatusCode; this.ErrorMessage = errorMessage; this.Operations = operations; this.SerializerCore = serializer; this.Headers = headers; this.Diagnostics = new CosmosTraceDiagnostics(trace ?? NoOpTrace.Singleton); }
private TransactionalBatchResponse( HttpStatusCode statusCode, SubStatusCodes subStatusCode, string errorMessage, Headers headers, CosmosDiagnosticsContext diagnosticsContext, IReadOnlyList <ItemBatchOperation> operations, CosmosSerializerCore serializer) { this.StatusCode = statusCode; this.SubStatusCode = subStatusCode; this.ErrorMessage = errorMessage; this.Operations = operations; this.SerializerCore = serializer; this.Headers = headers; this.Diagnostics = diagnosticsContext.Diagnostics; this.DiagnosticsContext = diagnosticsContext ?? throw new ArgumentNullException(nameof(diagnosticsContext)); }
private void CaptureSessionToken( HttpStatusCode?statusCode, SubStatusCodes subStatusCode, DocumentServiceRequest request, INameValueCollection responseHeaders) { // Exceptionless can try to capture session token from CompleteResponse if (request.IsValidStatusCodeForExceptionlessRetry((int)statusCode, subStatusCode)) { // Not capturing on master resources if (ReplicatedResourceClient.IsMasterResource(request.ResourceType)) { return; } // Only capturing on 409, 412, 404 && !1002 if (statusCode != HttpStatusCode.PreconditionFailed && statusCode != HttpStatusCode.Conflict && (statusCode != HttpStatusCode.NotFound || subStatusCode == SubStatusCodes.ReadSessionNotAvailable)) { return; } } if (request.ResourceType == ResourceType.Collection && request.OperationType == OperationType.Delete) { string resourceId; if (request.IsNameBased) { resourceId = responseHeaders[HttpConstants.HttpHeaders.OwnerId]; } else { resourceId = request.ResourceId; } this.sessionContainer.ClearTokenByResourceId(resourceId); } else { this.sessionContainer.SetSessionToken(request, responseHeaders); } }
private BatchResponse( HttpStatusCode statusCode, SubStatusCodes subStatusCode, string errorMessage, double requestCharge, TimeSpan?retryAfter, string activityId, IReadOnlyList <ItemBatchOperation> operations, CosmosSerializer serializer) { this.StatusCode = statusCode; this.SubStatusCode = subStatusCode; this.ErrorMessage = errorMessage; this.Operations = operations; this.Serializer = serializer; this.RequestCharge = requestCharge; this.RetryAfter = retryAfter; this.ActivityId = activityId; }
public static Task <ResponseMessage> ReturnStatusCode( HttpStatusCode statusCode, SubStatusCodes subStatusCode = SubStatusCodes.Unknown) { return(Task.Factory.StartNew( () => { ResponseMessage httpResponse = new ResponseMessage(statusCode); if (subStatusCode != SubStatusCodes.Unknown) { httpResponse.Headers.Add( WFConstants.BackendHeaders.SubStatus, ((uint)subStatusCode).ToString(CultureInfo.InvariantCulture)); } httpResponse.Content = new MemoryStream(Encoding.UTF8.GetBytes("{}")); return httpResponse; })); }
public static QueryResponseCore CreateFailureResponse( HttpStatusCode httpStatusCode, SubStatusCodes subStatusCodes, string errorMessage) { string acitivityId = Guid.NewGuid().ToString(); CosmosDiagnosticsContext diagnosticsContext = new CosmosDiagnosticsContextCore(); diagnosticsContext.AddDiagnosticsInternal(new PointOperationStatistics( acitivityId, System.Net.HttpStatusCode.Gone, subStatusCode: SubStatusCodes.PartitionKeyRangeGone, responseTimeUtc: DateTime.UtcNow, requestCharge: 10.4, errorMessage: null, method: HttpMethod.Post, requestUri: "http://localhost.com", requestSessionToken: null, responseSessionToken: null)); IReadOnlyCollection <QueryPageDiagnostics> diagnostics = new List <QueryPageDiagnostics>() { new QueryPageDiagnostics( Guid.NewGuid(), "0", "SomeQueryMetricText", "SomeIndexUtilText", diagnosticsContext) }; QueryResponseCore splitResponse = QueryResponseCore.CreateFailure( statusCode: httpStatusCode, subStatusCodes: subStatusCodes, cosmosException: CosmosExceptionFactory.Create( statusCode: httpStatusCode, subStatusCode: (int)subStatusCodes, message: errorMessage, stackTrace: new System.Diagnostics.StackTrace().ToString(), activityId: acitivityId, requestCharge: 10.4, retryAfter: default,
private TransactionalBatchResponse( HttpStatusCode statusCode, SubStatusCodes subStatusCode, string errorMessage, double requestCharge, TimeSpan?retryAfter, string activityId, CosmosDiagnosticsContext diagnosticsContext, IReadOnlyList <ItemBatchOperation> operations, CosmosSerializerCore serializer) { this.StatusCode = statusCode; this.SubStatusCode = subStatusCode; this.ErrorMessage = errorMessage; this.Operations = operations; this.SerializerCore = serializer; this.RequestCharge = requestCharge; this.RetryAfter = retryAfter; this.ActivityId = activityId; this.Diagnostics = diagnosticsContext.Diagnostics; this.DiagnosticsContext = diagnosticsContext ?? throw new ArgumentNullException(nameof(diagnosticsContext)); }
public PointOperationStatistics( string activityId, HttpStatusCode statusCode, SubStatusCodes subStatusCode, double requestCharge, string errorMessage, HttpMethod method, Uri requestUri, string requestSessionToken, string responseSessionToken, CosmosClientSideRequestStatistics clientSideRequestStatistics) { this.ActivityId = activityId; this.StatusCode = statusCode; this.SubStatusCode = subStatusCode; this.RequestCharge = requestCharge; this.ErrorMessage = errorMessage; this.Method = method; this.RequestUri = requestUri; this.RequestSessionToken = requestSessionToken; this.ResponseSessionToken = responseSessionToken; this.ClientSideRequestStatistics = clientSideRequestStatistics; }
private async Task <bool> ConstainsSplitIsTrueInternal(HttpStatusCode statusCode, SubStatusCodes subStatusCode) { List <TransactionalBatchOperationResult> results = new List <TransactionalBatchOperationResult>(); ItemBatchOperation[] arrayOperations = new ItemBatchOperation[1]; ItemBatchOperation operation = new ItemBatchOperation(OperationType.Read, 0, Cosmos.PartitionKey.Null, "0"); results.Add( new TransactionalBatchOperationResult(HttpStatusCode.OK) { ResourceStream = new MemoryStream(new byte[] { 0x41, 0x42 }, index: 0, count: 2, writable: false, publiclyVisible: true), ETag = operation.Id }); arrayOperations[0] = operation; MemoryStream responseContent = await new BatchResponsePayloadWriter(results).GeneratePayloadAsync(); SinglePartitionKeyServerBatchRequest batchRequest = await SinglePartitionKeyServerBatchRequest.CreateAsync( partitionKey : null, operations : new ArraySegment <ItemBatchOperation>(arrayOperations), serializerCore : MockCosmosUtil.Serializer, cancellationToken : default(CancellationToken)); ResponseMessage response = new ResponseMessage(statusCode) { Content = responseContent }; response.Headers.SubStatusCode = subStatusCode; TransactionalBatchResponse batchresponse = await TransactionalBatchResponse.FromResponseMessageAsync( response, batchRequest, MockCosmosUtil.Serializer, true, CancellationToken.None); PartitionKeyRangeBatchExecutionResult result = new PartitionKeyRangeBatchExecutionResult("0", arrayOperations, batchresponse); return(result.IsSplit()); }
private static async Task <TransactionalBatchResponse> PopulateFromContentAsync( Stream content, ResponseMessage responseMessage, ServerBatchRequest serverRequest, CosmosSerializerCore serializer, ITrace trace, bool shouldPromoteOperationStatus) { List <TransactionalBatchOperationResult> results = new List <TransactionalBatchOperationResult>(); // content is ensured to be seekable in caller. int resizerInitialCapacity = (int)content.Length; Result res = await content.ReadRecordIOAsync( (Func <ReadOnlyMemory <byte>, Result>)(record => { Result r = TransactionalBatchOperationResult.ReadOperationResult(record, out TransactionalBatchOperationResult operationResult); if (r != Result.Success) { return(r); } operationResult.Trace = trace; results.Add(operationResult); return(r); }), resizer : new MemorySpanResizer <byte>(resizerInitialCapacity)); if (res != Result.Success) { return(null); } HttpStatusCode responseStatusCode = responseMessage.StatusCode; SubStatusCodes responseSubStatusCode = responseMessage.Headers.SubStatusCode; // Promote the operation error status as the Batch response error status if we have a MultiStatus response // to provide users with status codes they are used to. if ((int)responseMessage.StatusCode == (int)StatusCodes.MultiStatus && shouldPromoteOperationStatus) { foreach (TransactionalBatchOperationResult result in results) { if ((int)result.StatusCode != (int)StatusCodes.FailedDependency && (int)result.StatusCode >= (int)StatusCodes.StartingErrorCode) { responseStatusCode = result.StatusCode; responseSubStatusCode = result.SubStatusCode; break; } } } TransactionalBatchResponse response = new TransactionalBatchResponse( responseStatusCode, responseSubStatusCode, responseMessage.ErrorMessage, responseMessage.Headers, trace, serverRequest.Operations, serializer) { results = results }; return(response); }
private async Task <bool> ConstainsSplitIsTrueInternal(HttpStatusCode statusCode, SubStatusCodes subStatusCode) { List <BatchOperationResult> results = new List <BatchOperationResult>(); ItemBatchOperation[] arrayOperations = new ItemBatchOperation[1]; ItemBatchOperation operation = new ItemBatchOperation(OperationType.AddComputeGatewayRequestCharges, 0, "0"); results.Add( new BatchOperationResult(HttpStatusCode.OK) { ResourceStream = new MemoryStream(new byte[] { 0x41, 0x42 }, index: 0, count: 2, writable: false, publiclyVisible: true), ETag = operation.Id }); arrayOperations[0] = operation; MemoryStream responseContent = await new BatchResponsePayloadWriter(results).GeneratePayloadAsync(); SinglePartitionKeyServerBatchRequest batchRequest = await SinglePartitionKeyServerBatchRequest.CreateAsync( partitionKey : null, operations : new ArraySegment <ItemBatchOperation>(arrayOperations), maxBodyLength : 100, maxOperationCount : 1, serializer : new CosmosJsonDotNetSerializer(), cancellationToken : default(CancellationToken)); ResponseMessage response = new ResponseMessage(statusCode) { Content = responseContent }; response.Headers.SubStatusCode = subStatusCode; BatchResponse batchresponse = await BatchResponse.PopulateFromContentAsync( response, batchRequest, new CosmosJsonDotNetSerializer()); PartitionKeyRangeBatchExecutionResult result = new PartitionKeyRangeBatchExecutionResult("0", arrayOperations, batchresponse); return(result.IsSplit()); }
public static Task <CosmosResponseMessage> ReturnStatusCode(HttpStatusCode statusCode, SubStatusCodes subStatusCode = SubStatusCodes.Unknown) { return(Task.Factory.StartNew( () => { CosmosResponseMessage httpResponse = new CosmosResponseMessage(statusCode); if (subStatusCode != SubStatusCodes.Unknown) { httpResponse.Headers.Add(WFConstants.BackendHeaders.SubStatus, ((uint)subStatusCode).ToString(CultureInfo.InvariantCulture)); } return httpResponse; })); }
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, 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=")); } } }
private void HandleUnsuccessfulStoreResponse(DocumentServiceRequest request, HttpStatusCode?statusCode, SubStatusCodes subStatusCode, INameValueCollection responseHeaders) { if (request.IsNameBased && statusCode == HttpStatusCode.NotFound && subStatusCode == SubStatusCodes.ReadSessionNotAvailable && request.ClearSessionTokenOnSessionReadFailure) { // Clear the session token, because the collection name might be reused. DefaultTrace.TraceWarning("Clear the the token for named base request {0}", request.ResourceAddress); this.sessionContainer.ClearToken(null, request.ResourceAddress, responseHeaders); } else { if ((!ReplicatedResourceClient.IsMasterResource(request.ResourceType)) && (statusCode == HttpStatusCode.PreconditionFailed || statusCode == HttpStatusCode.Conflict || (statusCode == HttpStatusCode.NotFound && subStatusCode != SubStatusCodes.ReadSessionNotAvailable))) { this.CaptureSessionToken(request, responseHeaders); } } }