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 void ApplySessionToken(DocumentServiceRequest request) { if (request.Headers != null && !string.IsNullOrEmpty(request.Headers[HttpConstants.HttpHeaders.SessionToken])) { if (ReplicatedResourceClient.IsMasterResource(request.ResourceType)) { request.Headers.Remove(HttpConstants.HttpHeaders.SessionToken); } return; //User is explicitly controlling the session. } string requestConsistencyLevel = request.Headers[HttpConstants.HttpHeaders.ConsistencyLevel]; bool sessionConsistency = this.defaultConsistencyLevel == ConsistencyLevel.Session || (!string.IsNullOrEmpty(requestConsistencyLevel) && string.Equals(requestConsistencyLevel, ConsistencyLevel.Session.ToString(), StringComparison.OrdinalIgnoreCase)); if (!sessionConsistency || ReplicatedResourceClient.IsMasterResource(request.ResourceType)) { return; // Only apply the session token in case of session consistency and when resource is not a master resource } //Apply the ambient session. string sessionToken = this.sessionContainer.ResolveGlobalSessionToken(request); if (!string.IsNullOrEmpty(sessionToken)) { request.Headers[HttpConstants.HttpHeaders.SessionToken] = sessionToken; } }
public virtual async Task <DocumentServiceResponse> ProcessMessageAsync(DocumentServiceRequest request, CancellationToken cancellationToken = default(CancellationToken)) { this.ApplySessionToken(request); DocumentServiceResponse response; try { response = await this.InvokeAsync(request, request.ResourceType, 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(request, exception.Headers); } throw; } this.CaptureSessionToken(request, response.Headers); return(response); }
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); } } }
// 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 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 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); } } }
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); }