public async Task RegistryManager_QueryDevicesInvalidServiceCertificateHttp_Fails() { using var rm = RegistryManager.CreateFromConnectionString(TestConfiguration.IoTHub.ConnectionStringInvalidServiceCertificate); IQuery query = rm.CreateQuery("select * from devices"); IotHubCommunicationException exception = await Assert.ThrowsExceptionAsync <IotHubCommunicationException>( () => query.GetNextAsTwinAsync()).ConfigureAwait(false); #if NET451 || NET472 Assert.IsInstanceOfType(exception.InnerException.InnerException.InnerException, typeof(AuthenticationException)); #else Assert.IsInstanceOfType(exception.InnerException.InnerException, typeof(AuthenticationException)); #endif }
/// <summary> /// Retry an async operation on encountering a transient operation. The retry strategy followed is an exponential backoff strategy. /// </summary> /// <param name="operationName">An identifier for the async operation to be executed. This is used for debugging purposes.</param> /// <param name="asyncOperation">The async operation to be retried.</param> /// <param name="shouldExecuteOperation">A function that determines if the operation should be executed. /// Eg.: for scenarios when we want to execute the operation only if the client is connected, this would be a function that returns if the client is currently connected.</param> /// <param name="logger">The <see cref="ILogger"/> instance to be used.</param> /// <param name="exceptionsToBeIgnored">An optional list of exceptions that can be ignored.</param> /// <param name="cancellationToken">The cancellation token to cancel the operation.</param> internal static async Task RetryTransientExceptionsAsync( string operationName, Func <Task> asyncOperation, Func <bool> shouldExecuteOperation, ILogger logger, IDictionary <Type, string> exceptionsToBeIgnored = default, CancellationToken cancellationToken = default) { IRetryPolicy retryPolicy = new ExponentialBackoffTransientExceptionRetryPolicy(maxRetryCount: int.MaxValue, exceptionsToBeIgnored: exceptionsToBeIgnored); int attempt = 0; bool shouldRetry; do { Exception lastException = new IotHubCommunicationException("Client is currently reconnecting internally; attempt the operation after some time."); try { if (shouldExecuteOperation()) { logger.LogInformation(FormatRetryOperationLogMessage(operationName, attempt, "executing.")); await asyncOperation(); break; } else { logger.LogWarning(FormatRetryOperationLogMessage(operationName, attempt, "operation is not ready to be executed. Attempt discarded.")); } } catch (Exception ex) { logger.LogWarning(FormatRetryOperationLogMessage(operationName, attempt, $"encountered an exception while processing the request: {ex}")); lastException = ex; } shouldRetry = retryPolicy.ShouldRetry(++attempt, lastException, out TimeSpan retryInterval); if (shouldRetry) { logger.LogWarning(FormatRetryOperationLogMessage(operationName, attempt, $"caught a recoverable exception, will retry in {retryInterval}.")); await Task.Delay(retryInterval); } else { logger.LogWarning(FormatRetryOperationLogMessage(operationName, attempt, $"retry policy determined that the operation should no longer be retried, stopping retries.")); } }while (shouldRetry && !cancellationToken.IsCancellationRequested); }
public async Task JobClient_ScheduleTwinUpdateInvalidServiceCertificateHttp_Fails() { using var jobClient = JobClient.CreateFromConnectionString(TestConfiguration.IoTHub.ConnectionStringInvalidServiceCertificate); IotHubCommunicationException exception = await Assert.ThrowsExceptionAsync <IotHubCommunicationException>( () => jobClient.ScheduleTwinUpdateAsync( "testDevice", "DeviceId IN ['testDevice']", new Shared.Twin(), DateTime.UtcNow, 60)).ConfigureAwait(false); #if NET451 || NET472 Assert.IsInstanceOfType(exception.InnerException.InnerException.InnerException, typeof(AuthenticationException)); #else Assert.IsInstanceOfType(exception.InnerException.InnerException, typeof(AuthenticationException)); #endif }
static async Task <IotHubBridge> CreateFromConnectionStringAsync(string deviceId, string connectionString, int connectionPoolSize, TimeSpan?connectionIdleTimeout, IotHubClientSettings settings, CancellationToken cancellationToken) { int maxPendingOutboundMessages = settings.MaxPendingOutboundMessages; var tcpSettings = new AmqpTransportSettings(TransportType.Amqp_Tcp_Only); var webSocketSettings = new AmqpTransportSettings(TransportType.Amqp_WebSocket_Only); webSocketSettings.PrefetchCount = tcpSettings.PrefetchCount = (uint)maxPendingOutboundMessages; if (connectionPoolSize > 0) { var amqpConnectionPoolSettings = new AmqpConnectionPoolSettings { MaxPoolSize = unchecked ((uint)connectionPoolSize), Pooling = connectionPoolSize > 0 }; if (connectionIdleTimeout.HasValue) { amqpConnectionPoolSettings.ConnectionIdleTimeout = connectionIdleTimeout.Value; } tcpSettings.AmqpConnectionPoolSettings = amqpConnectionPoolSettings; webSocketSettings.AmqpConnectionPoolSettings = amqpConnectionPoolSettings; } var client = DeviceClient.CreateFromConnectionString(connectionString, new ITransportSettings[] { tcpSettings, webSocketSettings }); client.SetRetryPolicy(DeviceClientRetryPolicy.Instance); var bridge = new IotHubBridge(client, deviceId, settings); client.SetConnectionStatusChangesHandler((status, reason) => { if (status != ConnectionStatus.Connected) { var cause = new IotHubCommunicationException("Connection to IoT Hub is closed"); if (Interlocked.CompareExchange(ref bridge.closedCause, cause, null) == null) { bridge.messagingChannel?.Close(cause); } } }); // This helps in usage instrumentation at IotHub service. client.ProductInfo = $"protocolgateway/poolsize={connectionPoolSize}"; try { await client.OpenAsync(cancellationToken); cancellationToken.ThrowIfCancellationRequested(); // in case SDK does not always honor cancellation token in async operations } catch (IotHubException ex) { client.Dispose(); throw ex.ToMessagingException(); } catch (Exception) { client.Dispose(); throw; } return(bridge); }