示例#1
0
        protected virtual async Task <DateTime> OnRenewLockAsync(string lockToken)
        {
            DateTime lockedUntilUtc = DateTime.MinValue;

            try
            {
                // Create an AmqpRequest Message to renew  lock
                AmqpRequestMessage requestMessage = AmqpRequestMessage.CreateRequest(ManagementConstants.Operations.RenewLockOperation, this.OperationTimeout, null);
                requestMessage.Map[ManagementConstants.Properties.LockTokens] = new[] { new Guid(lockToken) };

                AmqpResponseMessage response = await this.ExecuteRequestResponseAsync(requestMessage).ConfigureAwait(false);

                if (response.StatusCode == AmqpResponseStatusCode.OK)
                {
                    IEnumerable <DateTime> lockedUntilUtcTimes = response.GetValue <IEnumerable <DateTime> >(ManagementConstants.Properties.Expirations);
                    lockedUntilUtc = lockedUntilUtcTimes.First();
                }
                else
                {
                    throw response.ToMessagingContractException();
                }
            }
            catch (Exception exception)
            {
                throw AmqpExceptionHelper.GetClientException(exception);
            }

            return(lockedUntilUtc);
        }
示例#2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="operation"></param>
        /// <param name="scope"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        internal async Task RunOperation(
            Func <TimeSpan, Task> operation,
            TransportConnectionScope scope,
            CancellationToken cancellationToken)
        {
            var failedAttemptCount = 0;

            TimeSpan tryTimeout = CalculateTryTimeout(0);

            if (IsServerBusy && tryTimeout < ServerBusyBaseSleepTime)
            {
                // We are in a server busy state before we start processing.
                // Since ServerBusyBaseSleepTime > remaining time for the operation, we don't wait for the entire Sleep time.
                await Task.Delay(tryTimeout, cancellationToken).ConfigureAwait(false);

                throw new ServiceBusException(
                          ServerBusyExceptionMessage,
                          ServiceBusFailureReason.ServiceBusy);
            }
            while (!cancellationToken.IsCancellationRequested)
            {
                if (IsServerBusy)
                {
                    await Task.Delay(ServerBusyBaseSleepTime, cancellationToken).ConfigureAwait(false);
                }

                try
                {
                    await operation(tryTimeout).ConfigureAwait(false);

                    return;
                }

                catch (Exception ex)
                {
                    Exception activeEx = AmqpExceptionHelper.TranslateException(ex);

                    // Determine if there should be a retry for the next attempt; if so enforce the delay but do not quit the loop.
                    // Otherwise, throw the translated exception.

                    ++failedAttemptCount;
                    TimeSpan?retryDelay = CalculateRetryDelay(activeEx, failedAttemptCount);
                    if (retryDelay.HasValue && !scope.IsDisposed && !cancellationToken.IsCancellationRequested)
                    {
                        Logger.RunOperationExceptionEncountered(activeEx.ToString());
                        await Task.Delay(retryDelay.Value, cancellationToken).ConfigureAwait(false);

                        tryTimeout = CalculateTryTimeout(failedAttemptCount);
                    }
                    else
                    {
                        ExceptionDispatchInfo.Capture(activeEx)
                        .Throw();
                    }
                }
            }
            // If no value has been returned nor exception thrown by this point,
            // then cancellation has been requested.
            throw new TaskCanceledException();
        }
示例#3
0
        public void MismatchingExceptionNotTranslated()
        {
            var argumentException = new ArgumentException();

            EventHubsException newException;
            var translated = AmqpExceptionHelper.TryTranslateToRetriableException(argumentException, out newException);

            Assert.False(translated, "TryTranslateToRetriableException returned true");
        }
示例#4
0
        public void InvalidOperationExceptionWithoutClosingMessageNotTranslated()
        {
            var invalidOperationException = new InvalidOperationException("this is some other error");

            EventHubsException newException;
            var translated = AmqpExceptionHelper.TryTranslateToRetriableException(invalidOperationException, out newException);

            Assert.False(translated, "TryTranslateToRetriableException returned true");
        }
示例#5
0
        protected virtual async Task <IList <Message> > OnPeekAsync(long fromSequenceNumber, int messageCount = 1)
        {
            try
            {
                AmqpRequestMessage requestMessage =
                    AmqpRequestMessage.CreateRequest(
                        ManagementConstants.Operations.PeekMessageOperation,
                        this.OperationTimeout,
                        null);

                requestMessage.Map[ManagementConstants.Properties.FromSequenceNumber] = fromSequenceNumber;
                requestMessage.Map[ManagementConstants.Properties.MessageCount]       = messageCount;

                if (!string.IsNullOrWhiteSpace(this.SessionId))
                {
                    requestMessage.Map[ManagementConstants.Properties.SessionId] = this.SessionId;
                }

                List <Message> messages = new List <Message>();

                AmqpResponseMessage response = await this.ExecuteRequestResponseAsync(requestMessage).ConfigureAwait(false);

                if (response.StatusCode == AmqpResponseStatusCode.OK)
                {
                    Message message     = null;
                    var     messageList = response.GetListValue <AmqpMap>(ManagementConstants.Properties.Messages);
                    foreach (AmqpMap entry in messageList)
                    {
                        var         payload     = (ArraySegment <byte>)entry[ManagementConstants.Properties.Message];
                        AmqpMessage amqpMessage =
                            AmqpMessage.CreateAmqpStreamMessage(new BufferListStream(new[] { payload }), true);
                        message = AmqpMessageConverter.AmqpMessageToSBMessage(amqpMessage);
                        messages.Add(message);
                    }

                    if (message != null)
                    {
                        this.LastPeekedSequenceNumber = message.SystemProperties.SequenceNumber;
                    }

                    return(messages);
                }
                else if (response.StatusCode == AmqpResponseStatusCode.NoContent ||
                         (response.StatusCode == AmqpResponseStatusCode.NotFound && Equals(AmqpClientConstants.MessageNotFoundError, response.GetResponseErrorCondition())))
                {
                    return(messages);
                }
                else
                {
                    throw response.ToMessagingContractException();
                }
            }
            catch (Exception exception)
            {
                throw AmqpExceptionHelper.GetClientException(exception);
            }
        }
        /// <summary>
        /// Gets a particular session object identified by <paramref name="sessionId"/> that can be used to receive messages for that sessionId.
        /// </summary>
        /// <param name="sessionId">The sessionId present in all its messages.</param>
        /// <param name="serverWaitTime">Amount of time for which the call should wait to fetch the next session.</param>
        /// <remarks>All plugins registered on <see cref="SessionClient"/> will be applied to each <see cref="MessageSession"/> that is accepted.
        /// Individual sessions can further register additional plugins.</remarks>
        /// <returns>A session object.</returns>
        public async Task <IMessageSession> AcceptMessageSessionAsync(string sessionId, TimeSpan serverWaitTime)
        {
            MessagingEventSource.Log.AmqpSessionClientAcceptMessageSessionStart(
                this.ClientId,
                this.EntityPath,
                this.ReceiveMode,
                this.PrefetchCount,
                sessionId);

            var session = new MessageSession(
                this.EntityPath,
                this.EntityType,
                this.ReceiveMode,
                this.ServiceBusConnection,
                this.CbsTokenProvider,
                this.RetryPolicy,
                this.PrefetchCount,
                sessionId,
                true);

            try
            {
                await this.RetryPolicy.RunOperation(
                    async() =>
                {
                    await session.GetSessionReceiverLinkAsync(serverWaitTime).ConfigureAwait(false);
                }, serverWaitTime)
                .ConfigureAwait(false);
            }
            catch (Exception exception)
            {
                MessagingEventSource.Log.AmqpSessionClientAcceptMessageSessionException(
                    this.ClientId,
                    this.EntityPath,
                    exception);

                await session.CloseAsync().ConfigureAwait(false);

                throw AmqpExceptionHelper.GetClientException(exception);
            }

            MessagingEventSource.Log.AmqpSessionClientAcceptMessageSessionStop(
                this.ClientId,
                this.EntityPath,
                session.SessionIdInternal);

            session.UpdateClientId(ClientEntity.GenerateClientId(nameof(MessageSession), $"{this.EntityPath}_{session.SessionId}"));
            // Register plugins on the message session.
            foreach (var serviceBusPlugin in this.RegisteredPlugins)
            {
                session.RegisterPlugin(serviceBusPlugin);
            }

            return(session);
        }
示例#7
0
        public void InvalidOperationExceptionWithClosingMessageTranslated()
        {
            var invalidOperationException = new InvalidOperationException("Can't create session when the connection is closing.");

            EventHubsException newException;
            var translated = AmqpExceptionHelper.TryTranslateToRetriableException(invalidOperationException, out newException);

            Assert.True(translated, "TryTranslateToRetriableException returned false");
            Assert.True(newException.IsTransient, "newException.IsTransient == false");
            Assert.True(newException.InnerException == invalidOperationException, "newException.InnerException != invalidOperationException");
        }
示例#8
0
        protected virtual async Task <IList <Message> > OnReceiveAsync(int maxMessageCount, TimeSpan serverWaitTime)
        {
            ReceivingAmqpLink receiveLink = null;

            try
            {
                TimeoutHelper timeoutHelper = new TimeoutHelper(serverWaitTime, true);
                receiveLink = await this.ReceiveLinkManager.GetOrCreateAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false);

                IEnumerable <AmqpMessage> amqpMessages = null;
                bool hasMessages = await Task.Factory.FromAsync(
                    (c, s) => receiveLink.BeginReceiveRemoteMessages(maxMessageCount, DefaultBatchFlushInterval, timeoutHelper.RemainingTime(), c, s),
                    a => receiveLink.EndReceiveMessages(a, out amqpMessages),
                    this).ConfigureAwait(false);

                if (receiveLink.TerminalException != null)
                {
                    throw receiveLink.TerminalException;
                }

                if (hasMessages && amqpMessages != null)
                {
                    IList <Message> brokeredMessages = null;
                    foreach (var amqpMessage in amqpMessages)
                    {
                        if (brokeredMessages == null)
                        {
                            brokeredMessages = new List <Message>();
                        }

                        if (this.ReceiveMode == ReceiveMode.ReceiveAndDelete)
                        {
                            receiveLink.DisposeDelivery(amqpMessage, true, AmqpConstants.AcceptedOutcome);
                        }

                        Message message = AmqpMessageConverter.AmqpMessageToSBMessage(amqpMessage);
                        brokeredMessages.Add(message);
                    }

                    return(brokeredMessages);
                }

                return(null);
            }
            catch (Exception exception)
            {
                throw AmqpExceptionHelper.GetClientException(exception, receiveLink?.GetTrackingId());
            }
        }
示例#9
0
        public async Task <EventHubPartitionRuntimeInformation> GetPartitionRuntimeInformationAsync(string partitionId)
        {
            RequestResponseAmqpLink requestLink = await link.GetOrCreateAsync(
                TimeSpan.FromSeconds(AmqpClientConstants.AmqpSessionTimeoutInSeconds)).ConfigureAwait(false);

            // Create request and attach token.
            AmqpMessage request = CreateGetPartitionRuntimeInformationRequest(partitionId);

            request.ApplicationProperties.Map[AmqpClientConstants.ManagementSecurityTokenKey] = await GetTokenString().ConfigureAwait(false);

            AmqpMessage response = await requestLink.RequestAsync(request, eventHubClient.ConnectionStringBuilder.OperationTimeout).ConfigureAwait(false);

            int    statusCode        = (int)response.ApplicationProperties.Map[AmqpClientConstants.ResponseStatusCode];
            string statusDescription = (string)response.ApplicationProperties.Map[AmqpClientConstants.ResponseStatusDescription];

            if (statusCode != (int)AmqpResponseStatusCode.Accepted && statusCode != (int)AmqpResponseStatusCode.OK)
            {
                AmqpSymbol errorCondition = AmqpExceptionHelper.GetResponseErrorCondition(response, (AmqpResponseStatusCode)statusCode);
                Error      error          = new Error {
                    Condition = errorCondition, Description = statusDescription
                };
                throw AmqpExceptionHelper.ToMessagingContract(error);
            }

            AmqpMap infoMap = null;

            if (response.ValueBody != null)
            {
                infoMap = response.ValueBody.Value as AmqpMap;
            }

            if (infoMap == null)
            {
                throw new InvalidOperationException($"Return type mismatch in GetPartitionRuntimeInformationAsync. Response returned NULL or response isn't AmqpMap.");
            }

            return(new EventHubPartitionRuntimeInformation()
            {
                Type = (string)infoMap[new MapKey(AmqpClientConstants.EntityTypeName)],
                Path = (string)infoMap[new MapKey(AmqpClientConstants.EntityNameKey)],
                PartitionId = (string)infoMap[new MapKey(AmqpClientConstants.PartitionNameKey)],
                BeginSequenceNumber = (long)infoMap[new MapKey(AmqpClientConstants.ManagementPartitionBeginSequenceNumber)],
                LastEnqueuedSequenceNumber = (long)infoMap[new MapKey(AmqpClientConstants.ManagementPartitionLastEnqueuedSequenceNumber)],
                LastEnqueuedOffset = (string)infoMap[new MapKey(AmqpClientConstants.ManagementPartitionLastEnqueuedOffset)],
                LastEnqueuedTimeUtc = (DateTime)infoMap[new MapKey(AmqpClientConstants.ManagementPartitionLastEnqueuedTimeUtc)],
                IsEmpty = (bool)infoMap[new MapKey(AmqpClientConstants.ManagementPartitionRuntimeInfoPartitionIsEmpty)]
            });
        }
        public async Task <EventHubPartitionRuntimeInformation> GetPartitionRuntimeInformationAsync(string partitionId)
        {
            RequestResponseAmqpLink requestLink = await this.link.GetOrCreateAsync(TimeSpan.FromMinutes(1)).ConfigureAwait(false);

            // Create request and attach token.
            var request = this.CreateGetPartitionRuntimeInformationRequest(partitionId);

            request.ApplicationProperties.Map[AmqpClientConstants.ManagementSecurityTokenKey] = await GetTokenString().ConfigureAwait(false);

            var response = await requestLink.RequestAsync(request, TimeSpan.FromMinutes(1)).ConfigureAwait(false);

            int    statusCode        = (int)response.ApplicationProperties.Map[AmqpClientConstants.ResponseStatusCode];
            string statusDescription = (string)response.ApplicationProperties.Map[AmqpClientConstants.ResponseStatusDescription];

            if (statusCode != (int)AmqpResponseStatusCode.Accepted && statusCode != (int)AmqpResponseStatusCode.OK)
            {
                AmqpSymbol errorCondition = AmqpExceptionHelper.GetResponseErrorCondition(response, (AmqpResponseStatusCode)statusCode);
                Error      error          = new Error {
                    Condition = errorCondition, Description = statusDescription
                };
                throw AmqpExceptionHelper.ToMessagingContract(error);
            }

            AmqpMap infoMap = null;

            if (response.ValueBody != null)
            {
                infoMap = response.ValueBody.Value as AmqpMap;
            }

            if (infoMap == null)
            {
                throw new InvalidOperationException($"Return type mismatch in GetPartitionRuntimeInformationAsync. Response returned NULL or response isn't AmqpMap.");
            }

            return(new EventHubPartitionRuntimeInformation()
            {
                Type = (string)infoMap[new MapKey("type")],
                Path = (string)infoMap[new MapKey("name")],
                PartitionId = (string)infoMap[new MapKey("partition")],
                BeginSequenceNumber = (long)infoMap[new MapKey("begin_sequence_number")],
                LastEnqueuedSequenceNumber = (long)infoMap[new MapKey("last_enqueued_sequence_number")],
                LastEnqueuedOffset = (string)infoMap[new MapKey("last_enqueued_offset")],
                LastEnqueuedTimeUtc = (DateTime)infoMap[new MapKey("last_enqueued_time_utc")]
            });
        }
示例#11
0
        public async Task <EventHubRuntimeInformation> GetRuntimeInformationAsync()
        {
            RequestResponseAmqpLink requestLink = await link.GetOrCreateAsync(
                TimeSpan.FromSeconds(AmqpClientConstants.AmqpSessionTimeoutInSeconds)).ConfigureAwait(false);

            // Create request and attach token.
            AmqpMessage request = CreateGetRuntimeInformationRequest();

            request.ApplicationProperties.Map[AmqpClientConstants.ManagementSecurityTokenKey] = await GetTokenString().ConfigureAwait(false);

            AmqpMessage response = await requestLink.RequestAsync(request, eventHubClient.ConnectionStringBuilder.OperationTimeout).ConfigureAwait(false);

            int    statusCode        = (int)response.ApplicationProperties.Map[AmqpClientConstants.ResponseStatusCode];
            string statusDescription = (string)response.ApplicationProperties.Map[AmqpClientConstants.ResponseStatusDescription];

            if (statusCode != (int)AmqpResponseStatusCode.Accepted && statusCode != (int)AmqpResponseStatusCode.OK)
            {
                AmqpSymbol errorCondition = AmqpExceptionHelper.GetResponseErrorCondition(response, (AmqpResponseStatusCode)statusCode);
                Error      error          = new Error {
                    Condition = errorCondition, Description = statusDescription
                };
                throw AmqpExceptionHelper.ToMessagingContract(error);
            }

            AmqpMap infoMap = null;

            if (response.ValueBody != null)
            {
                infoMap = response.ValueBody.Value as AmqpMap;
            }

            if (infoMap == null)
            {
                throw new InvalidOperationException($"Return type mismatch in GetRuntimeInformationAsync. Response returned NULL or response isn't AmqpMap.");
            }

            return(new EventHubRuntimeInformation()
            {
                Type = (string)infoMap[new MapKey("type")],
                Path = (string)infoMap[new MapKey("name")],
                CreatedAt = (DateTime)infoMap[new MapKey("created_at")],
                PartitionCount = (int)infoMap[new MapKey("partition_count")],
                PartitionIds = (string[])infoMap[new MapKey("partition_ids")],
            });
        }
示例#12
0
        protected virtual async Task <IList <Message> > OnReceiveBySequenceNumberAsync(IEnumerable <long> sequenceNumbers)
        {
            List <Message> messages = new List <Message>();

            try
            {
                AmqpRequestMessage requestMessage = AmqpRequestMessage.CreateRequest(ManagementConstants.Operations.ReceiveBySequenceNumberOperation, this.OperationTimeout, null);
                requestMessage.Map[ManagementConstants.Properties.SequenceNumbers]    = sequenceNumbers.ToArray();
                requestMessage.Map[ManagementConstants.Properties.ReceiverSettleMode] = (uint)(this.ReceiveMode == ReceiveMode.ReceiveAndDelete ? 0 : 1);

                AmqpResponseMessage response = await this.ExecuteRequestResponseAsync(requestMessage).ConfigureAwait(false);

                if (response.StatusCode == AmqpResponseStatusCode.OK)
                {
                    IEnumerable <AmqpMap> amqpMapList = response.GetListValue <AmqpMap>(ManagementConstants.Properties.Messages);
                    foreach (AmqpMap entry in amqpMapList)
                    {
                        ArraySegment <byte> payload     = (ArraySegment <byte>)entry[ManagementConstants.Properties.Message];
                        AmqpMessage         amqpMessage = AmqpMessage.CreateAmqpStreamMessage(new BufferListStream(new[] { payload }), true);
                        Message             message     = AmqpMessageConverter.AmqpMessageToSBMessage(amqpMessage);
                        Guid lockToken;
                        if (entry.TryGetValue(ManagementConstants.Properties.LockToken, out lockToken))
                        {
                            message.SystemProperties.LockTokenGuid = lockToken;
                            this.requestResponseLockedMessages.AddOrUpdate(lockToken, message.SystemProperties.LockedUntilUtc);
                        }

                        messages.Add(message);
                    }
                }
                else
                {
                    throw response.ToMessagingContractException();
                }
            }
            catch (Exception exception)
            {
                throw AmqpExceptionHelper.GetClientException(exception);
            }

            return(messages);
        }
示例#13
0
        async Task DisposeMessageRequestResponseAsync(IEnumerable <Guid> lockTokens, DispositionStatus dispositionStatus)
        {
            try
            {
                // Create an AmqpRequest Message to update disposition
                AmqpRequestMessage requestMessage = AmqpRequestMessage.CreateRequest(ManagementConstants.Operations.UpdateDispositionOperation, this.OperationTimeout, null);
                requestMessage.Map[ManagementConstants.Properties.LockTokens]        = lockTokens.ToArray();
                requestMessage.Map[ManagementConstants.Properties.DispositionStatus] = dispositionStatus.ToString().ToLowerInvariant();

                AmqpResponseMessage amqpResponseMessage = await this.ExecuteRequestResponseAsync(requestMessage).ConfigureAwait(false);

                if (amqpResponseMessage.StatusCode != AmqpResponseStatusCode.OK)
                {
                    throw amqpResponseMessage.ToMessagingContractException();
                }
            }
            catch (Exception exception)
            {
                throw AmqpExceptionHelper.GetClientException(exception);
            }
        }
        async Task OnSendAsync(IList <Message> messageList)
        {
            TimeoutHelper timeoutHelper = new TimeoutHelper(this.OperationTimeout, true);

            using (AmqpMessage amqpMessage = AmqpMessageConverter.BatchSBMessagesAsAmqpMessage(messageList, true))
            {
                SendingAmqpLink amqpLink = null;
                try
                {
                    amqpLink = await this.SendLinkManager.GetOrCreateAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false);

                    if (amqpLink.Settings.MaxMessageSize.HasValue)
                    {
                        ulong size = (ulong)amqpMessage.SerializedMessageSize;
                        if (size > amqpLink.Settings.MaxMessageSize.Value)
                        {
                            // TODO: Add MessageSizeExceededException
                            throw new NotImplementedException("MessageSizeExceededException: " + Resources.AmqpMessageSizeExceeded.FormatForUser(amqpMessage.DeliveryId.Value, size, amqpLink.Settings.MaxMessageSize.Value));
                            ////throw Fx.Exception.AsError(new MessageSizeExceededException(
                            ////Resources.AmqpMessageSizeExceeded.FormatForUser(amqpMessage.DeliveryId.Value, size, amqpLink.Settings.MaxMessageSize.Value)));
                        }
                    }

                    Outcome outcome = await amqpLink.SendMessageAsync(amqpMessage, this.GetNextDeliveryTag(), AmqpConstants.NullBinary, timeoutHelper.RemainingTime()).ConfigureAwait(false);

                    if (outcome.DescriptorCode != Accepted.Code)
                    {
                        Rejected rejected = (Rejected)outcome;
                        throw Fx.Exception.AsError(AmqpExceptionHelper.ToMessagingContractException(rejected.Error));
                    }
                }
                catch (Exception exception)
                {
                    throw AmqpExceptionHelper.GetClientException(exception, amqpLink?.GetTrackingId());
                }
            }
        }
            public async Task <object> Start()
            {
                RequestResponseAmqpLink requestLink = await this.client.link.GetOrCreateAsync(TimeSpan.FromMinutes(1));

                ApplicationProperties properties = new ApplicationProperties();

                properties.Map[AmqpClientConstants.ManagementOperationKey] = this.md.Operation.Name;
                // generate message sections containing the arguments
                // convert custom-type parameters if needed
                object  bodyValue = null;
                AmqpMap bodyMap   = null;

                for (int i = 0; i < this.argCount; i++)
                {
                    ManagementParamAttribute paramAttribute = this.md.Parameters[i];
                    object value = SerializationHelper.ToAmqp(this.md.ParameterTypes[i].Serializable, this.mcm.InArgs[i]);

                    if (paramAttribute.Location == ManagementParamLocation.ApplicationProperties)
                    {
                        properties.Map[paramAttribute.Name] = value;
                    }
                    else if (paramAttribute.Location == ManagementParamLocation.MapBody)
                    {
                        if (bodyMap == null)
                        {
                            bodyMap = new AmqpMap();
                        }

                        bodyMap[new MapKey(paramAttribute.Name)] = value;
                    }
                    else
                    {
                        bodyValue = value;
                    }
                }

                // Upsert link RequestProperties to ApplicationProperties
                foreach (var requestProperty in requestLink.RequestProperties)
                {
                    properties.Map[requestProperty.Key] = requestProperty.Value;
                }

                this.request = AmqpMessage.Create(new AmqpValue {
                    Value = bodyMap ?? bodyValue
                });
                this.request.ApplicationProperties = properties;

                this.response = await requestLink.RequestAsync(request, TimeSpan.FromMinutes(1));

                int    statusCode        = (int)this.response.ApplicationProperties.Map[AmqpClientConstants.ResponseStatusCode];
                string statusDescription = (string)this.response.ApplicationProperties.Map[AmqpClientConstants.ResponseStatusDescription];

                if (statusCode != (int)AmqpResponseStatusCode.Accepted && statusCode != (int)AmqpResponseStatusCode.OK)
                {
                    AmqpSymbol errorCondition = AmqpExceptionHelper.GetResponseErrorCondition(this.response, (AmqpResponseStatusCode)statusCode);
                    Error      error          = new Error {
                        Condition = errorCondition, Description = statusDescription
                    };
                    throw new AmqpException(error);
                }

                object returnValue = null;

                if (this.response.ValueBody != null)
                {
                    returnValue = this.response.ValueBody.Value;
                }

                if (md.ReturnType.HasValue && returnValue != null)
                {
                    Type             expected     = md.ReturnType.Type;
                    SerializableType serializable = md.ReturnType.Serializable;
                    if (serializable == null)
                    {
                        // must be a generic parameter
                        expected     = mcm.GenericTypes[md.ReturnType.Type.GenericParameterPosition];
                        serializable = expected.GetSerializable();
                    }

                    returnValue = SerializationHelper.FromAmqp(serializable, returnValue);
                    if (!expected.IsAssignableFrom(returnValue.GetType()))
                    {
                        throw new InvalidOperationException($"Return type mismatch in {mcm.MethodBase.Name}. Expect {expected.Name} Actual {returnValue.GetType().Name}");
                    }
                }

                return(returnValue);
            }
示例#16
0
        async Task DisposeMessagesAsync(IEnumerable <Guid> lockTokens, Outcome outcome)
        {
            TimeoutHelper timeoutHelper = new TimeoutHelper(this.OperationTimeout, true);
            IList <ArraySegment <byte> > deliveryTags = this.ConvertLockTokensToDeliveryTags(lockTokens);

            ReceivingAmqpLink receiveLink = null;

            try
            {
                receiveLink = await this.ReceiveLinkManager.GetOrCreateAsync(timeoutHelper.RemainingTime()).ConfigureAwait(false);

                Task <Outcome>[] disposeMessageTasks = new Task <Outcome> [deliveryTags.Count];
                int i = 0;
                foreach (ArraySegment <byte> deliveryTag in deliveryTags)
                {
                    disposeMessageTasks[i++] = Task.Factory.FromAsync(
                        (c, s) => receiveLink.BeginDisposeMessage(deliveryTag, outcome, true, timeoutHelper.RemainingTime(), c, s),
                        a => receiveLink.EndDisposeMessage(a),
                        this);
                }

                Outcome[] outcomes = await Task.WhenAll(disposeMessageTasks).ConfigureAwait(false);

                Error error = null;
                foreach (Outcome item in outcomes)
                {
                    var disposedOutcome = item.DescriptorCode == Rejected.Code && ((error = ((Rejected)item).Error) != null) ? item : null;
                    if (disposedOutcome != null)
                    {
                        if (error.Condition.Equals(AmqpErrorCode.NotFound))
                        {
                            if (this.isSessionReceiver)
                            {
                                throw new SessionLockLostException(Resources.SessionLockExpiredOnMessageSession);
                            }
                            else
                            {
                                throw new MessageLockLostException(Resources.MessageLockLost);
                            }
                        }

                        throw AmqpExceptionHelper.ToMessagingContractException(error);
                    }
                }
            }
            catch (Exception exception)
            {
                if (exception is OperationCanceledException &&
                    receiveLink != null && receiveLink.State != AmqpObjectState.Opened)
                {
                    if (this.isSessionReceiver)
                    {
                        throw new SessionLockLostException(Resources.SessionLockExpiredOnMessageSession);
                    }
                    else
                    {
                        throw new MessageLockLostException(Resources.MessageLockLost);
                    }
                }

                throw AmqpExceptionHelper.GetClientException(exception);
            }
        }