Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        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);
        }
Esempio n. 4
0
        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);
                }
            }
        }
Esempio n. 5
0
 // 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);
 }
Esempio n. 6
0
        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);
            }
        }
Esempio n. 7
0
        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);
                }
            }
        }
Esempio n. 8
0
        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);
        }