예제 #1
0
        public async void WaitsForCommands()
        {
            var noOfRuns = 0;

            m_coreLinkMock.Setup(link => link.Request(It.IsAny <CommandConversation>(), It.IsAny <int>()))
            .Returns(() =>
            {
                var task = new Task <StateResponse>(() =>
                {
                    // Set up the "continuation" task.
                    var result = new Task <StateResponse>(() => new StateResponse());
                    result.Start();

                    // This should only get called once, because the OriginalTask will be called on the second go.
                    noOfRuns++;

                    // If this is the first run, simulate timeout.
                    if (noOfRuns == 1)
                    {
                        throw new TaskTimeoutException <StateResponse>(result);
                    }

                    return(result.Result);
                });
                task.Start();
                return(task);
            });

            var conversation = new CommandConversation(CommandType.Run);

            await m_controller.Command(conversation, () => TimeoutAction.Wait, timeoutMs : TimeoutMs);

            Assert.Equal(1, noOfRuns);
        }
예제 #2
0
        public async void RetriesCommands()
        {
            var noOfRuns = 0;

            m_coreLinkMock.Setup(link => link.Request(It.IsAny <CommandConversation>(), It.IsAny <int>()))
            .Returns(() =>
            {
                var task = new Task <StateResponse>(() =>
                {
                    if (noOfRuns++ == 0)
                    {
                        throw new TaskTimeoutException <StateResponse>(null);
                    }

                    return(new StateResponse());
                });
                task.Start();
                return(task);
            });

            var conversation = new CommandConversation(CommandType.Run);

            await m_controller.Command(conversation, () => TimeoutAction.Retry, timeoutMs : TimeoutMs);

            Assert.Equal(2, noOfRuns);
        }
예제 #3
0
        public async Task GetsAsyncConversationError()
        {
            const string errorMessage = "Foo bar";

            var       conv            = new CommandConversation(CommandType.Run);
            var       responseMessage = ErrorResponseBuilder.Build(errorMessage);
            ICoreLink coreLink        = GenerateCoreLink(responseMessage);

            var ex = await Assert.ThrowsAsync <RemoteCoreException>(() => coreLink.Request(conv, WaitMs));

            Assert.Equal(errorMessage, ex.Message);
        }
예제 #4
0
        public void GetsAsyncConversationResult()
        {
            var conversation = new CommandConversation(CommandType.Run);

            ResponseMessage responseMessage = StateResponseBuilder.Build(StateType.Running);

            ICoreLink coreLink = GenerateCoreLink(responseMessage);

            Task <StateResponse> futureResponse = coreLink.Request(conversation, WaitMs);

            StateResponse receivedResponse = ReadResponse(futureResponse);

            Assert.Equal(StateType.Running, receivedResponse.State);
        }
예제 #5
0
        private async Task SendCommandAsync(CommandConversation conversation, bool stopCheckingCoreState = false)
        {
            try
            {
                StateResponse response = await m_controller.Command(
                    conversation, CreateTimeoutHandler(conversation.RequestData.Command),
                    restartKeepaliveOnSuccess : !stopCheckingCoreState);

                HandleStateResponse(response);
            }
            catch (Exception ex)
            {
                HandleError(ex.Message);
                throw;
            }
        }
예제 #6
0
        public async Task TimesOut()
        {
            var conv = new CommandConversation(CommandType.Run);

            var response = StateResponseBuilder.Build(StateType.Paused);

            var converseClientMock = new Mock <IConverseFlatBuffersClient>();

            converseClientMock.Setup(client =>
                                     client.SendQuery <CommandRequest, ResponseMessage>(Conversation.Handler, It.IsAny <CommandRequest>()))
            .Callback(() => Thread.Sleep(WaitMs * 2))
            .Returns(response);
            IConverseFlatBuffersClient converseClient = converseClientMock.Object;

            var coreLink = new CoreLink(converseClient);

            await Assert.ThrowsAsync <TaskTimeoutException <StateResponse> >(() => coreLink.Request(conv, WaitMs));
        }
예제 #7
0
        public void OnlyAllowsOneCommand()
        {
            m_coreLinkMock.Setup(link => link.Request(It.IsAny <CommandConversation>(), It.IsAny <int>()))
            .Returns(() =>
            {
                var task = new Task <StateResponse>(() =>
                {
                    Thread.Sleep(100);
                    return(new StateResponse());
                });
                task.Start();
                return(task);
            });

            var conversation = new CommandConversation(CommandType.Run);

            var firstTask = m_controller.Command(conversation, () => TimeoutAction.Wait);

            var exception = Assert.Throws <AggregateException>(() => m_controller.Command(conversation, () => TimeoutAction.Wait).Wait());

            Assert.Contains(exception.InnerExceptions, ex => ex is InvalidOperationException);

            Assert.NotNull(firstTask.Result);
        }
예제 #8
0
        public async Task <StateResponse> Command(CommandConversation conversation, Func <TimeoutAction> timeoutCallback,
                                                  bool restartKeepaliveOnSuccess = true, int timeoutMs = CommandTimeoutMs)
        {
            if (m_runningCommand != null)
            {
                CommandType commandType = conversation.RequestData.Command;
                Log.Info("A command is already running: {commandType}", commandType);
                throw new InvalidOperationException($"A command is already running {commandType}");
            }

            m_cancellationTokenSource.Cancel();

            var retry = false;

            StateResponse result = null;

            while (true)
            {
                try
                {
                    if (retry || m_runningCommand == null)
                    {
                        retry            = false;
                        m_runningCommand = m_coreLink.Request(conversation, timeoutMs);
                    }

                    result = await m_runningCommand.ConfigureAwait(false);
                }
                catch (TaskTimeoutException <StateResponse> ex)
                {
                    TimeoutAction timeoutAction = timeoutCallback();
                    Log.Info("Command {command} timed out, {action} requested", conversation.RequestData.Command,
                             timeoutAction);
                    if (timeoutAction == TimeoutAction.Cancel)
                    {
                        break;
                    }

                    if (timeoutAction == TimeoutAction.Retry)
                    {
                        retry = true;
                    }

                    if (timeoutAction == TimeoutAction.Wait)
                    {
                        m_runningCommand = ex.OriginalTask.TimeoutAfter(CommandTimeoutMs);
                    }

                    continue;
                }
                catch (Exception ex)
                {
                    Log.Error(ex, "Request failed");
                    m_runningCommand = null;
                    RestartStateChecking();
                    throw;
                }

                Log.Debug("Successful command {command}", conversation.RequestData.Command);
                break;
            }

            m_runningCommand = null;

            if (restartKeepaliveOnSuccess)
            {
                RestartStateChecking();
            }

            return(result);
        }