private async Task <Twin> RoundTripTwinMessageAsync(
            AmqpTwinMessageType amqpTwinMessageType,
            TwinCollection reportedProperties,
            CancellationToken cancellationToken)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, cancellationToken, nameof(RoundTripTwinMessageAsync));
            }

            string correlationId = amqpTwinMessageType + Guid.NewGuid().ToString();
            Twin   response      = null;

            try
            {
                cancellationToken.ThrowIfCancellationRequested();
                var taskCompletionSource = new TaskCompletionSource <Twin>();
                _twinResponseCompletions[correlationId] = taskCompletionSource;

                using var ctb = new CancellationTokenBundle(_operationTimeout, cancellationToken);
                await _amqpUnit.SendTwinMessageAsync(amqpTwinMessageType, correlationId, reportedProperties, ctb.Token).ConfigureAwait(false);

                Task <Twin> receivingTask = taskCompletionSource.Task;

                if (await Task
                    .WhenAny(receivingTask, Task.Delay(TimeSpan.FromSeconds(ResponseTimeoutInSeconds), cancellationToken))
                    .ConfigureAwait(false) == receivingTask)
                {
                    if (receivingTask.Exception?.InnerException != null)
                    {
                        throw receivingTask.Exception.InnerException;
                    }

                    // Task completed within timeout.
                    // Consider that the task may have faulted or been canceled.
                    // We re-await the task so that any exceptions/cancellation is re-thrown.
                    response = await receivingTask.ConfigureAwait(false);
                }
                else
                {
                    // Timeout happen
                    throw new TimeoutException();
                }
            }
            finally
            {
                _twinResponseCompletions.TryRemove(correlationId, out _);
                if (Logging.IsEnabled)
                {
                    Logging.Exit(this, cancellationToken, nameof(RoundTripTwinMessageAsync));
                }
            }

            return(response);
        }
        public async Task SendTwinMessageAsync(AmqpTwinMessageType amqpTwinMessageType, string correlationId, TwinCollection reportedProperties, TimeSpan timeout)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, timeout, $"{nameof(SendTwinMessageAsync)}");
            }

            await EnableTwinLinksAsync(timeout).ConfigureAwait(false);

            Debug.Assert(_twinSendingLink != null);

            try
            {
                AmqpIoTOutcome amqpIoTOutcome;
                switch (amqpTwinMessageType)
                {
                case AmqpTwinMessageType.Get:
                    amqpIoTOutcome = await _twinSendingLink.SendTwinGetMessageAsync(correlationId, reportedProperties, timeout).ConfigureAwait(false);

                    if (amqpIoTOutcome != null)
                    {
                        amqpIoTOutcome.ThrowIfNotAccepted();
                    }
                    break;

                case AmqpTwinMessageType.Patch:
                    amqpIoTOutcome = await _twinSendingLink.SendTwinPatchMessageAsync(correlationId, reportedProperties, timeout).ConfigureAwait(false);

                    if (amqpIoTOutcome != null)
                    {
                        amqpIoTOutcome.ThrowIfNotAccepted();
                    }
                    break;

                case AmqpTwinMessageType.Put:
                    amqpIoTOutcome = await _twinSendingLink.SubscribeToDesiredPropertiesAsync(correlationId, timeout).ConfigureAwait(false);

                    if (amqpIoTOutcome != null)
                    {
                        amqpIoTOutcome.ThrowIfNotAccepted();
                    }
                    break;

                default:
                    break;
                }
            }
            finally
            {
                if (Logging.IsEnabled)
                {
                    Logging.Exit(this, timeout, $"{nameof(SendTwinMessageAsync)}");
                }
            }
        }
示例#3
0
        public async Task SendTwinMessageAsync(
            AmqpTwinMessageType amqpTwinMessageType,
            string correlationId,
            TwinCollection reportedProperties,
            CancellationToken cancellationToken)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, nameof(SendTwinMessageAsync));
            }

            await EnableTwinLinksAsync(cancellationToken).ConfigureAwait(false);

            Debug.Assert(_twinSendingLink != null);

            try
            {
                AmqpIotOutcome amqpIotOutcome;
                switch (amqpTwinMessageType)
                {
                case AmqpTwinMessageType.Get:
                    amqpIotOutcome = await _twinSendingLink.SendTwinGetMessageAsync(correlationId, cancellationToken).ConfigureAwait(false);

                    amqpIotOutcome?.ThrowIfNotAccepted();
                    break;

                case AmqpTwinMessageType.Patch:
                    amqpIotOutcome = await _twinSendingLink.SendTwinPatchMessageAsync(correlationId, reportedProperties, cancellationToken).ConfigureAwait(false);

                    amqpIotOutcome?.ThrowIfNotAccepted();
                    break;

                case AmqpTwinMessageType.Put:
                    amqpIotOutcome = await _twinSendingLink.SubscribeToDesiredPropertiesAsync(correlationId, cancellationToken).ConfigureAwait(false);

                    amqpIotOutcome?.ThrowIfNotAccepted();
                    break;
                }
            }
            finally
            {
                if (Logging.IsEnabled)
                {
                    Logging.Exit(this, nameof(SendTwinMessageAsync));
                }
            }
        }
        private async Task <Twin> RoundTripTwinMessage(AmqpTwinMessageType amqpTwinMessageType, TwinCollection reportedProperties, CancellationToken cancellationToken)
        {
            if (Logging.IsEnabled)
            {
                Logging.Enter(this, cancellationToken, $"{nameof(RoundTripTwinMessage)}");
            }
            string correlationId = Guid.NewGuid().ToString();
            Twin   response      = null;

            try
            {
                var taskCompletionSource = new TaskCompletionSource <Twin>();
                _twinResponseCompletions[correlationId] = taskCompletionSource;

                await _amqpUnit.SendTwinMessageAsync(amqpTwinMessageType, correlationId, reportedProperties, _operationTimeout).ConfigureAwait(false);

                var receivingTask = taskCompletionSource.Task;
                if (await Task.WhenAny(receivingTask, Task.Delay(TimeSpan.FromSeconds(ResponseTimeoutInSeconds))).ConfigureAwait(false) == receivingTask)
                {
                    // Task completed within timeout.
                    // Consider that the task may have faulted or been canceled.
                    // We re-await the task so that any exceptions/cancellation is rethrown.
                    response = await receivingTask.ConfigureAwait(false);

                    if (response == null)
                    {
                        throw new InvalidOperationException("Service response is null");
                    }
                }
                else
                {
                    // Timeout happen
                    throw new TimeoutException();
                }
            }
            finally
            {
                _twinResponseCompletions.TryRemove(correlationId, out _);
                if (Logging.IsEnabled)
                {
                    Logging.Exit(this, cancellationToken, $"{nameof(RoundTripTwinMessage)}");
                }
            }

            return(response);
        }