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); }
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); }
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); }
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); }
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; } }
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)); }
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); }
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); }