private void RunApp() { var auditStream = config.AuditStream; challengeServerClient = new ChallengeServerClient(config.Hostname, config.Port, config.JourneyId, config.UseColours); try { var journeyProgress = challengeServerClient.GetJourneyProgress(); auditStream.WriteLine(journeyProgress); var availableActions = challengeServerClient.GetAvailableActions(); auditStream.WriteLine(availableActions); bool noActionsAvailable = availableActions.Contains("No actions available."); if (noActionsAvailable) { recordingSystem.TellToStop(); return; } var userInput = userInputCallback.Get(); auditStream.WriteLine("Selected action is: " + userInput); if (userInput.Equals("deploy")) { implementationRunner.Run(); var lastFetchedRound = RoundManagement.GetLastFetchedRound(); recordingSystem.NotifyEvent(lastFetchedRound, RecordingEvent.ROUND_SOLUTION_DEPLOY); } var actionFeedback = challengeServerClient.SendAction(userInput); if (actionFeedback.Contains("Round time for")) { var lastFetchedRound = RoundManagement.GetLastFetchedRound(); recordingSystem.NotifyEvent(lastFetchedRound, RecordingEvent.ROUND_COMPLETED); } if (actionFeedback.Contains("All challenges have been completed")) { recordingSystem.TellToStop(); } config.AuditStream.WriteLine(actionFeedback); var roundDescription = challengeServerClient.GetRoundDescription(); RoundManagement.SaveDescription(recordingSystem, roundDescription, auditStream); } catch (ServerErrorException) { auditStream.WriteLine("Server experienced an error. Try again in a few minutes."); } catch (OtherCommunicationException) { auditStream.WriteLine("Client threw an unexpected error. Try again."); } catch (ClientErrorException e) { // The client sent something the server didn't expect. auditStream.WriteLine(e.Message); } }
private async Task ProcessActionsAsync(IContext context, Action[] actions, CancellationToken cancellationToken) { // Execute all state actions foreach (var stateAction in actions.OrderBy(a => a.Order)) { var action = _actionProvider.Get(stateAction.Type); try { var settings = stateAction.Settings; if (settings != null) { var settingsJson = settings.ToString(Formatting.None); settingsJson = await _variableReplacer.ReplaceAsync(settingsJson, context, cancellationToken); settings = JObject.Parse(settingsJson); } await action.ExecuteAsync(context, settings, cancellationToken); } catch (Exception ex) { throw new ActionProcessingException( $"The processing of the action '{stateAction.Type}' has failed: {ex.Message}", ex); } } }
private async Task ProcessActionsAsync(LazyInput lazyInput, IContext context, Action[] actions, ICollection <ActionTrace> actionTraces, CancellationToken cancellationToken) { // Execute all state actions foreach (var stateAction in actions.OrderBy(a => a.Order)) { if (stateAction.Conditions != null && !await stateAction.Conditions.EvaluateConditionsAsync(lazyInput, context, cancellationToken)) { continue; } var action = _actionProvider.Get(stateAction.Type); // Trace infra var(actionTrace, actionStopwatch) = actionTraces != null ? (stateAction.ToTrace(), Stopwatch.StartNew()) : (null, null); if (actionTrace != null) { context.SetCurrentActionTrace(actionTrace); } // Configure the action timeout, that can be defined in action or flow level var executionTimeoutInSeconds = stateAction.Timeout ?? context.Flow?.BuilderConfiguration?.ActionExecutionTimeout; var executionTimeout = executionTimeoutInSeconds.HasValue ? TimeSpan.FromSeconds(executionTimeoutInSeconds.Value) : _configuration.DefaultActionExecutionTimeout; using (var cts = new CancellationTokenSource(executionTimeout)) using (var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cts.Token, cancellationToken)) { try { var settings = stateAction.Settings; if (settings != null) { var settingsJson = settings.ToString(Formatting.None); settingsJson = await _variableReplacer.ReplaceAsync(settingsJson, context, cancellationToken); settings = JObject.Parse(settingsJson); } if (actionTrace != null) { actionTrace.ParsedSettings = settings; } using (LogContext.PushProperty(nameof(BuilderException.MessageId), lazyInput?.Message?.Id)) using (LogContext.PushProperty(nameof(Action.Settings), settings, true)) await action.ExecuteAsync(context, settings, linkedCts.Token); } catch (Exception ex) { if (actionTrace != null) { actionTrace.Error = ex.ToString(); } var message = ex is OperationCanceledException && cts.IsCancellationRequested ? $"The processing of the action '{stateAction.Type}' has timed out after {executionTimeout.TotalMilliseconds} ms" : $"The processing of the action '{stateAction.Type}' has failed"; var actionProcessingException = new ActionProcessingException(message, ex) { ActionType = stateAction.Type, ActionSettings = stateAction.Settings.ToObject <IDictionary <string, object> >() }; if (stateAction.ContinueOnError) { _logger.Warning(actionProcessingException, "Action '{ActionType}' has failed but was forgotten", stateAction.Type); } else { throw actionProcessingException; } } finally { actionStopwatch?.Stop(); if (actionTrace != null && actionTraces != null && actionStopwatch != null) { actionTrace.ElapsedMilliseconds = actionStopwatch.ElapsedMilliseconds; actionTraces.Add(actionTrace); } } } } }