示例#1
0
        public override async Task OpenAsync(bool explicitOpen, CancellationToken cancellationToken)
        {
            TaskCompletionSource <int> openCompletionBeforeOperationStarted = Volatile.Read(ref this.openCompletion);

            if (openCompletionBeforeOperationStarted == null)
            {
                openCompletionBeforeOperationStarted = new TaskCompletionSource <int>();
                TaskCompletionSource <int> currentOpenPromise;
                if ((currentOpenPromise = Interlocked.CompareExchange(ref this.openCompletion, openCompletionBeforeOperationStarted, null)) == null)
                {
                    IDelegatingHandler handlerBeforeOperationStarted = this.ContinuationFactory(Context);
                    this.InnerHandler = handlerBeforeOperationStarted;
                    try
                    {
                        await this.ExecuteWithErrorHandlingAsync(() => base.OpenAsync(explicitOpen, cancellationToken), false, cancellationToken);

                        openCompletionBeforeOperationStarted.TrySetResult(0);
                    }
                    catch (Exception ex) when(IsTransportHandlerStillUsable(ex))
                    {
                        this.Reset(openCompletionBeforeOperationStarted, handlerBeforeOperationStarted);
                        throw;
                    }
                    catch (Exception ex) when(!ex.IsFatal())
                    {
                        throw;
                    }
                }
                else
                {
                    await currentOpenPromise.Task;
                }
            }
            else
            {
                await openCompletionBeforeOperationStarted.Task;
            }
        }
        // Tests_SRS_DEVICECLIENT_33_001: [** If the given eventMessageInternal argument is null, fail silently **]**
        public async Task ModuleClient_OnReceiveEventMessageCalled_NullMessageRequest()
        {
            var moduleClient = ModuleClient.CreateFromConnectionString(FakeConnectionString, TransportType.Mqtt_Tcp_Only);
            IDelegatingHandler innerHandler = Substitute.For <IDelegatingHandler>();

            moduleClient.InnerHandler = innerHandler;

            bool isMessageHandlerCalled = false;
            await moduleClient
            .SetInputMessageHandlerAsync(
                "endpoint1",
                (message, context) =>
            {
                isMessageHandlerCalled = true;
                return(Task.FromResult(MessageResponse.Completed));
            },
                "custom data")
            .ConfigureAwait(false);

            await moduleClient.InternalClient.OnModuleEventMessageReceivedAsync(null, null).ConfigureAwait(false);

            Assert.IsFalse(isMessageHandlerCalled);
        }
        public async Task ModuleClient_SetDefaultReceiveCallbackAsync_RemoveCallback_Amqp()
        {
            var moduleClient = ModuleClient.CreateFromConnectionString(FakeConnectionString, TransportType.Amqp_Tcp_Only);
            IDelegatingHandler innerHandler = Substitute.For <IDelegatingHandler>();

            moduleClient.InnerHandler = innerHandler;

            await moduleClient.SetMessageHandlerAsync((message, context) => Task.FromResult(MessageResponse.Completed), "custom data").ConfigureAwait(false);

            await innerHandler.Received(1).EnableEventReceiveAsync(false, Arg.Any <CancellationToken>()).ConfigureAwait(false);

            await innerHandler.DidNotReceiveWithAnyArgs().EnableReceiveMessageAsync(Arg.Any <CancellationToken>()).ConfigureAwait(false);

            await innerHandler.DidNotReceiveWithAnyArgs().DisableEventReceiveAsync(false, Arg.Any <CancellationToken>()).ConfigureAwait(false);

            await moduleClient.SetMessageHandlerAsync(null, null).ConfigureAwait(false);

            await innerHandler.Received(1).EnableEventReceiveAsync(false, Arg.Any <CancellationToken>()).ConfigureAwait(false);

            await innerHandler.DidNotReceiveWithAnyArgs().EnableReceiveMessageAsync(Arg.Any <CancellationToken>()).ConfigureAwait(false);

            await innerHandler.Received(1).DisableEventReceiveAsync(false, Arg.Any <CancellationToken>()).ConfigureAwait(false);
        }
        async Task ExecuteWithErrorHandlingAsync(Func <Task> asyncOperation, bool ensureOpen)
        {
            if (ensureOpen)
            {
                await this.EnsureOpenAsync();
            }

            TaskCompletionSource <int> completedPromise = this.openCompletion;
            IDelegatingHandler         handler          = this.InnerHandler;

            try
            {
                await asyncOperation();
            }
            catch (Exception ex) when(!ex.IsFatal())
            {
                if (this.IsTransient(ex))
                {
                    if (this.IsTranportTransient(ex))
                    {
                        if (ex is IotHubClientTransientException)
                        {
                            throw;
                        }
                        throw new IotHubClientTransientException("Transient error occured, please retry.", ex);
                    }
                    this.Reset(completedPromise, handler);
                    if (ex is IotHubClientTransientException)
                    {
                        throw;
                    }
                    throw new IotHubClientTransientException("Transient error occured, please retry.", ex);
                }
                this.Reset(completedPromise, handler);
                throw;
            }
        }
示例#5
0
        public IDelegatingHandler Build(PipelineContext context)
        {
            if (_pipeline.Count == 0)
            {
                throw new InvalidOperationException("Pipeline is not setup");
            }

            IDelegatingHandler nextHandler    = null;
            IDelegatingHandler currentHandler = null;

            // Initializes all handlers except the last one: the transport.
            // That is dynamically initialized by the ProtocolRoutingDelegatingHandler.
            for (int i = _pipeline.Count - 2; i >= 0; i--)
            {
                ContinuationFactory <IDelegatingHandler> currentFactory = _pipeline[i];
                ContinuationFactory <IDelegatingHandler> nextFactory    = _pipeline[i + 1];
                currentHandler = currentFactory(context, nextHandler);
                currentHandler.ContinuationFactory = nextFactory;

                nextHandler = currentHandler;
            }

            return(currentHandler);
        }
        // Tests_SRS_DEVICECLIENT_33_002: [** The OnReceiveEventMessageCalled shall invoke the specified delegate. **]**
        public async Task ModuleClient_OnReceiveEventMessageCalled_SpecifiedCallbackCalled()
        {
            var moduleClient = ModuleClient.CreateFromConnectionString(FakeConnectionString, TransportType.Mqtt_Tcp_Only);
            IDelegatingHandler innerHandler = Substitute.For <IDelegatingHandler>();

            moduleClient.InnerHandler = innerHandler;

            bool isDefaultCallbackCalled = false;
            await moduleClient.SetMessageHandlerAsync(
                (message, context) =>
            {
                isDefaultCallbackCalled = true;
                return(Task.FromResult(MessageResponse.Completed));
            },
                "custom data");

            bool isSpecificCallbackCalled = false;
            await moduleClient.SetInputMessageHandlerAsync(
                "endpoint2",
                (message, context) =>
            {
                isSpecificCallbackCalled = true;
                return(Task.FromResult(MessageResponse.Completed));
            },
                "custom data");

            var testMessage = new Message
            {
                LockToken = "AnyLockToken",
            };

            await moduleClient.InternalClient.OnModuleEventMessageReceivedAsync("endpoint2", testMessage).ConfigureAwait(false);

            Assert.IsFalse(isDefaultCallbackCalled);
            Assert.IsTrue(isSpecificCallbackCalled);
        }
        public async Task RetryDelegatingHandler_SendEventAsyncRetries()
        {
            // arrange
            int callCounter = 0;

            PipelineContext contextMock = Substitute.For <PipelineContext>();

            contextMock.ConnectionStatusChangesHandler = new ConnectionStatusChangesHandler(delegate(ConnectionStatus status, ConnectionStatusChangeReason reason) { });
            IDelegatingHandler innerHandlerMock = Substitute.For <IDelegatingHandler>();

            using var message = new Message(new MemoryStream(new byte[] { 1, 2, 3 }));
            innerHandlerMock
            .SendEventAsync(Arg.Is(message), Arg.Any <CancellationToken>())
            .Returns(t =>
            {
                callCounter++;

                Message m     = t.Arg <Message>();
                Stream stream = m.GetBodyStream();
                if (callCounter == 1)
                {
                    throw new IotHubException(TestExceptionMessage, isTransient: true);
                }
                byte[] buffer = new byte[3];
                stream.Read(buffer, 0, 3);
                return(TaskHelpers.CompletedTask);
            });

            var retryDelegatingHandler = new RetryDelegatingHandler(contextMock, innerHandlerMock);

            // act
            await retryDelegatingHandler.SendEventAsync(message, CancellationToken.None).ConfigureAwait(false);

            // assert
            callCounter.Should().Be(2);
        }
示例#8
0
        public async Task ModuleClient_SetReceiveCallbackAsync_RemoveCallback_Amqp()
        {
            ModuleClient moduleClient = await CreateAmqpModuleClientAsync();

            IDelegatingHandler innerHandler = Substitute.For <IDelegatingHandler>();

            moduleClient.InnerHandler = innerHandler;

            await moduleClient.SetInputMessageHandlerAsync("endpoint1", (message, context) => Task.FromResult(MessageResponse.Completed), "custom data").ConfigureAwait(false);

            await moduleClient.SetInputMessageHandlerAsync("endpoint2", (message, context) => Task.FromResult(MessageResponse.Completed), "custom data").ConfigureAwait(false);

            await innerHandler.Received(1).EnableEventReceiveAsync(true, Arg.Any <CancellationToken>()).ConfigureAwait(false);

            await innerHandler.DidNotReceiveWithAnyArgs().EnableReceiveMessageAsync(Arg.Any <CancellationToken>()).ConfigureAwait(false);

            await innerHandler.DidNotReceiveWithAnyArgs().DisableEventReceiveAsync(true, Arg.Any <CancellationToken>()).ConfigureAwait(false);

            await innerHandler.DidNotReceiveWithAnyArgs().DisableReceiveMessageAsync(Arg.Any <CancellationToken>()).ConfigureAwait(false);

            await moduleClient.SetInputMessageHandlerAsync("endpoint1", null, null).ConfigureAwait(false);

            await innerHandler.Received(1).EnableEventReceiveAsync(true, Arg.Any <CancellationToken>()).ConfigureAwait(false);

            await innerHandler.DidNotReceiveWithAnyArgs().EnableReceiveMessageAsync(Arg.Any <CancellationToken>()).ConfigureAwait(false);

            await innerHandler.DidNotReceiveWithAnyArgs().DisableEventReceiveAsync(true, Arg.Any <CancellationToken>()).ConfigureAwait(false);

            await moduleClient.SetInputMessageHandlerAsync("endpoint2", null, null).ConfigureAwait(false);

            await innerHandler.Received(1).EnableEventReceiveAsync(true, Arg.Any <CancellationToken>()).ConfigureAwait(false);

            await innerHandler.DidNotReceiveWithAnyArgs().EnableReceiveMessageAsync(Arg.Any <CancellationToken>()).ConfigureAwait(false);

            await innerHandler.Received(1).DisableEventReceiveAsync(true, Arg.Any <CancellationToken>()).ConfigureAwait(false);
        }
示例#9
0
        public async Task RetryDelegatingHandler_OpenAsyncRetries()
        {
            // arrange
            int callCounter = 0;

            IPipelineContext   contextMock      = Substitute.For <IPipelineContext>();
            IDelegatingHandler innerHandlerMock = Substitute.For <IDelegatingHandler>();

            innerHandlerMock.OpenAsync(Arg.Any <CancellationToken>()).Returns(t =>
            {
                return(++callCounter == 1
                    ? throw new IotHubException("Test transient exception", isTransient: true)
                    : TaskHelpers.CompletedTask);
            });
            innerHandlerMock.WaitForTransportClosedAsync().Returns(Task.Delay(TimeSpan.FromSeconds(10)));

            var retryDelegatingHandler = new RetryDelegatingHandler(contextMock, innerHandlerMock);

            // act
            await retryDelegatingHandler.OpenAsync(new CancellationToken()).ConfigureAwait(false);

            // assert
            Assert.AreEqual(2, callCounter);
        }
 protected DefaultDelegatingHandler(IDelegatingHandler innerHandler)
 {
     this.InnerHandler = innerHandler;
 }
 async Task Reset(TaskCompletionSource <int> openCompletionBeforeOperationStarted, IDelegatingHandler handlerBeforeOperationStarted)
 {
     if (openCompletionBeforeOperationStarted == Volatile.Read(ref this.openCompletion))
     {
         if (Interlocked.CompareExchange(ref this.openCompletion, null, openCompletionBeforeOperationStarted) == openCompletionBeforeOperationStarted)
         {
             await Cleanup(handlerBeforeOperationStarted).ConfigureAwait(false);
         }
     }
 }
示例#12
0
        DeviceClient(IotHubConnectionString iotHubConnectionString, ITransportSettings[] transportSettings)
        {
            this.iotHubConnectionString = iotHubConnectionString;

#if !WINDOWS_UWP
            var innerHandler = new RetryDelegatingHandler(
                new ErrorDelegatingHandler(
                    () => new RoutingDelegatingHandler(this.CreateTransportHandler, iotHubConnectionString, transportSettings)));
#else
            // UWP does not support retry yet. We need to make the underlying Message stream accessible internally on UWP
            // to be sure that either the stream has not been read or it is seekable to safely retry operation
            var innerHandler = new ErrorDelegatingHandler(
                () => new RoutingDelegatingHandler(this.CreateTransportHandler, iotHubConnectionString, transportSettings));
#endif
            this.InnerHandler = new GateKeeperDelegatingHandler(innerHandler);
        }
示例#13
0
 DeviceClient(IotHubConnectionString iotHubConnectionString)
 {
     this.InnerHandler = new GateKeeperDelegatingHandler(
         new ErrorDelegatingHandler(() => new HttpTransportHandler(iotHubConnectionString)));
 }
示例#14
0
 DeviceClient(IotHubConnectionString iotHubConnectionString)
 {
     this.InnerHandler = new GateKeeperDelegatingHandler(
         new ErrorDelegatingHandler(() => new HttpTransportHandler(iotHubConnectionString)));
 }
 protected DefaultDelegatingHandler(IDelegatingHandler innerHandler)
 {
     this.InnerHandler = innerHandler;
 }
 public ProtocolRoutingDelegatingHandler(IPipelineContext context, IDelegatingHandler innerHandler) :
     base(context, innerHandler)
 {
 }
示例#17
0
 public static DelegatingHandler ToImplementation([CanBeNull] this IDelegatingHandler abstraction)
 {
     return(((IAbstraction <DelegatingHandler>)abstraction)?.UnsafeConvert());
 }
        async Task <T> ExecuteWithErrorHandlingAsync <T>(Func <Task <T> > asyncOperation, bool ensureOpen, CancellationToken cancellationToken)
        {
            try
            {
                if (Logging.IsEnabled)
                {
                    Logging.Enter(this, ensureOpen, cancellationToken, $"{nameof(ErrorDelegatingHandler)}.{nameof(ExecuteWithErrorHandlingAsync)}");
                }

                if (ensureOpen)
                {
                    await this.EnsureOpenAsync(cancellationToken).ConfigureAwait(false);
                }

                TaskCompletionSource <int> openCompletionBeforeOperationStarted = Volatile.Read(ref this.openCompletion);
                IDelegatingHandler         handlerBeforeOperationStarted        = this.InnerHandler;

                try
                {
                    return(await asyncOperation().ConfigureAwait(false));
                }
                catch (Exception ex) when(!ex.IsFatal())
                {
                    if (IsTransient(ex))
                    {
                        if (IsTransportHandlerStillUsable(ex))
                        {
                            if (Logging.IsEnabled)
                            {
                                Logging.Error(this, $"Transient exception caught; IsTransportHandlerStillUsable=true : {ex}");
                            }

                            if (ex is IotHubClientTransientException)
                            {
                                throw;
                            }

                            throw new IotHubClientTransientException("Transient error occurred, please retry.", ex);
                        }

                        await this.Reset(openCompletionBeforeOperationStarted, handlerBeforeOperationStarted).ConfigureAwait(false);

                        if (Logging.IsEnabled)
                        {
                            Logging.Error(this, $"Transient exception caught; IsTransportHandlerStillUsable=false : {ex}");
                        }

                        if (ex is IotHubClientTransientException)
                        {
                            throw;
                        }
                        throw new IotHubClientTransientException("Transient error occurred, please retry.", ex);
                    }
                    else
                    {
                        if (Logging.IsEnabled)
                        {
                            Logging.Error(this, $"Non-transient exception caught: {ex}");
                        }

                        await this.Reset(openCompletionBeforeOperationStarted, handlerBeforeOperationStarted).ConfigureAwait(false);

                        throw;
                    }
                }
            }
            finally
            {
                if (Logging.IsEnabled)
                {
                    Logging.Exit(this, ensureOpen, cancellationToken, $"{nameof(ErrorDelegatingHandler)}.{nameof(ExecuteWithErrorHandlingAsync)}");
                }
            }
        }
        async Task Reset(TaskCompletionSource <int> openCompletionBeforeOperationStarted, IDelegatingHandler handlerBeforeOperationStarted)
        {
            try
            {
                if (Logging.IsEnabled)
                {
                    Logging.Enter(this, openCompletionBeforeOperationStarted, handlerBeforeOperationStarted, $"{nameof(ErrorDelegatingHandler)}.{nameof(Reset)}");
                }

                if (openCompletionBeforeOperationStarted == Volatile.Read(ref this.openCompletion))
                {
                    if (Interlocked.CompareExchange(ref this.openCompletion, null, openCompletionBeforeOperationStarted) == openCompletionBeforeOperationStarted)
                    {
                        await Cleanup(handlerBeforeOperationStarted).ConfigureAwait(false);
                    }
                }
            }
            finally
            {
                if (Logging.IsEnabled)
                {
                    Logging.Exit(this, $"{nameof(ErrorDelegatingHandler)}.{nameof(Reset)}");
                }
            }
        }
        public override async Task OpenAsync(bool explicitOpen, CancellationToken cancellationToken)
        {
            try
            {
                if (Logging.IsEnabled)
                {
                    Logging.Enter(this, explicitOpen, cancellationToken, $"{nameof(ErrorDelegatingHandler)}.{nameof(OpenAsync)}");
                }

                TaskCompletionSource <int> openCompletionBeforeOperationStarted = Volatile.Read(ref this.openCompletion);
                if (openCompletionBeforeOperationStarted == null)
                {
                    openCompletionBeforeOperationStarted = new TaskCompletionSource <int>();
                    TaskCompletionSource <int> currentOpenPromise;
                    if ((currentOpenPromise = Interlocked.CompareExchange(ref this.openCompletion, openCompletionBeforeOperationStarted, null)) == null)
                    {
                        IDelegatingHandler handlerBeforeOperationStarted = this.ContinuationFactory(Context);
                        this.InnerHandler = handlerBeforeOperationStarted;
                        try
                        {
                            await this.ExecuteWithErrorHandlingAsync(() => base.OpenAsync(explicitOpen, cancellationToken), false, cancellationToken).ConfigureAwait(false);

                            openCompletionBeforeOperationStarted.TrySetResult(0);
                        }
                        catch (Exception ex) when(IsTransportHandlerStillUsable(ex))
                        {
                            await this.Reset(openCompletionBeforeOperationStarted, handlerBeforeOperationStarted).ConfigureAwait(false);

                            throw;
                        }
                        catch (Exception ex) when(!ex.IsFatal())
                        {
                            if (Logging.IsEnabled)
                            {
                                Logging.Error(this, ex.Message, $"{nameof(ErrorDelegatingHandler)}.{nameof(OpenAsync)}");
                            }
                            throw;
                        }
                    }
                    else
                    {
                        if (Logging.IsEnabled)
                        {
                            Logging.Info(this, "Awaiting new Open task.", $"{nameof(ErrorDelegatingHandler)}.{nameof(OpenAsync)}");
                        }

                        await currentOpenPromise.Task.ConfigureAwait(false);
                    }
                }
                else
                {
                    if (Logging.IsEnabled)
                    {
                        Logging.Info(this, "Awaiting existing Open task.", $"{nameof(ErrorDelegatingHandler)}.{nameof(OpenAsync)}");
                    }

                    await openCompletionBeforeOperationStarted.Task.ConfigureAwait(false);
                }
            }
            finally
            {
                if (Logging.IsEnabled)
                {
                    Logging.Exit(this, explicitOpen, cancellationToken, $"{nameof(ErrorDelegatingHandler)}.{nameof(OpenAsync)}");
                }
            }
        }
示例#21
0
 public GateKeeperDelegatingHandler(IDelegatingHandler innerHandler)
 {
     this.InnerHandler             = innerHandler;
     this.thisLock                 = new object();
     this.openTaskCompletionSource = new TaskCompletionSource <object>(this);
 }
示例#22
0
 public RetryDelegatingHandler(IDelegatingHandler innerHandler)
     : base(innerHandler)
 {
     this.retryPolicy = new RetryPolicy(new IotHubTransientErrorIgnoreStrategy(), RetryCount, TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(10), TimeSpan.FromMilliseconds(100));
 }
示例#23
0
 public ErrorDelegatingHandler(IPipelineContext context, IDelegatingHandler innerHandler) : base(context, innerHandler)
 {
 }
 public GateKeeperDelegatingHandler(IDelegatingHandler innerHandler)
 {
     this.InnerHandler = innerHandler;
     this.thisLock = new object();
     this.openTaskCompletionSource = new TaskCompletionSource<object>(this);
 }
 public RetryDelegatingHandler(IDelegatingHandler innerHandler)
     :base(innerHandler)
 {
     this.retryPolicy = new RetryPolicy(new IotHubTransientErrorIgnoreStrategy(), RetryCount, TimeSpan.FromMilliseconds(100), TimeSpan.FromSeconds(10), TimeSpan.FromMilliseconds(100));
 }