private async Task DisposeMessageAsync(string lockToken, AmqpIotDisposeActions outcome, CancellationToken cancellationToken) { if (Logging.IsEnabled) { Logging.Enter(this, outcome, nameof(DisposeMessageAsync)); } try { // Currently, the same mechanism is used for sending feedback for C2D messages and events received by modules. // However, devices only support C2D messages (they cannot receive events), and modules only support receiving events // (they cannot receive C2D messages). So we use this to distinguish whether to dispose the message (i.e. send outcome on) // the DeviceBoundReceivingLink or the EventsReceivingLink. // If this changes (i.e. modules are able to receive C2D messages, or devices are able to receive telemetry), this logic // will have to be updated. using var ctb = new CancellationTokenBundle(_operationTimeout, cancellationToken); AmqpIotOutcome disposeOutcome = await _amqpUnit.DisposeMessageAsync(lockToken, outcome, ctb.Token).ConfigureAwait(false); disposeOutcome.ThrowIfError(); } finally { if (Logging.IsEnabled) { Logging.Exit(this, outcome, nameof(DisposeMessageAsync)); } } }
private async Task DisposeMessageAsync(string lockToken, AmqpIoTDisposeActions outcome, CancellationToken cancellationToken) { if (Logging.IsEnabled) { Logging.Enter(this, outcome, $"{nameof(DisposeMessageAsync)}"); } AmqpIoTOutcome disposeOutcome; try { // Currently, the same mechanism is used for sending feedback for C2D messages and events received by modules. // However, devices only support C2D messages (they cannot receive events), and modules only support receiving events // (they cannot receive C2D messages). So we use this to distinguish whether to dispose the message (i.e. send outcome on) // the DeviceBoundReceivingLink or the EventsReceivingLink. // If this changes (i.e. modules are able to receive C2D messages, or devices are able to receive telemetry), this logic // will have to be updated. disposeOutcome = await _amqpUnit.DisposeMessageAsync(lockToken, outcome, _operationTimeout).ConfigureAwait(false); } catch (Exception exception) when(!exception.IsFatal() && !(exception is OperationCanceledException)) { throw AmqpIoTExceptionAdapter.ConvertToIoTHubException(exception); } disposeOutcome.ThrowIfError(); if (Logging.IsEnabled) { Logging.Exit(this, outcome, $"{nameof(DisposeMessageAsync)}"); } }
private async Task DisposeMessageAsync(string lockToken, Outcome outcome, CancellationToken cancellationToken) { Outcome disposeOutcome; try { // Currently, the same mechanism is used for sending feedback for C2D messages and events received by modules. // However, devices only support C2D messages (they cannot receive events), and modules only support receiving events // (they cannot receive C2D messages). So we use this to distinguish whether to dispose the message (i.e. send outcome on) // the DeviceBoundReceivingLink or the EventsReceivingLink. // If this changes (i.e. modules are able to receive C2D messages, or devices are able to receive telemetry), this logic // will have to be updated. disposeOutcome = await _amqpUnit.DisposeMessageAsync(lockToken, outcome, _operationTimeout).ConfigureAwait(false); } catch (Exception exception) when(!exception.IsFatal() && !(exception is OperationCanceledException)) { throw AmqpClientHelper.ToIotHubClientContract(exception); } if (disposeOutcome.DescriptorCode != Accepted.Code) { if (disposeOutcome.DescriptorCode == Rejected.Code) { var rejected = (Rejected)disposeOutcome; // Special treatment for NotFound amqp rejected error code in case of DisposeMessage if (rejected.Error != null && rejected.Error.Condition.Equals(AmqpErrorCode.NotFound)) { Error error = new Error { Condition = IotHubAmqpErrorCode.MessageLockLostError }; throw AmqpErrorMapper.ToIotHubClientContract(error); } } throw AmqpErrorMapper.GetExceptionFromOutcome(disposeOutcome); } }