/// <summary> /// Immediately processes the specified task. /// </summary> /// <param name="task"></param> /// <returns></returns> public async Task ProcessSkraprTask(ISkraprTask task) { if (CancellationToken.IsCancellationRequested) { m_logger.LogDebug("{functionName} Cancellation requested. Skipping task {taskName}", nameof(ProcessSkraprTask), task.Name); return; } m_logger.LogDebug("{functionName} performing task {taskName}", nameof(ProcessSkraprTask), task.Name); if (task.Disabled) { m_logger.LogDebug("{functionName} Task {taskName} was marked as disabled. Skipping.", nameof(ProcessSkraprTask), task.Name); return; } if (task is IConditionalExpressionTask conditionalExpressionTask && !String.IsNullOrWhiteSpace(conditionalExpressionTask.Condition)) { m_logger.LogDebug("{functionName} Task {taskName} is a conditional task. Evaluating expression {expression}.", nameof(ProcessSkraprTask), task.Name, conditionalExpressionTask.Condition); var conditionResponse = await Session.Runtime.EvaluateCondition(conditionalExpressionTask.Condition, contextId : DevTools.CurrentFrameContext.Id); if (conditionResponse == false) { m_logger.LogDebug("{functionName} Condition result was false - skipping task {taskName}.", nameof(ProcessSkraprTask), task.Name); return; } m_logger.LogDebug("{functionName} Condition result was true - processing task {taskName}.", nameof(ProcessSkraprTask), task.Name); } //Perform the task await task.PerformTask(this); m_logger.LogDebug("{functionName} Completed task {taskName}", nameof(ProcessSkraprTask), task.Name); }
/// <summary> /// Adds the specified target to the queue. /// </summary> /// <param name="target"></param> public void Post(ISkraprTask task) { if (task == null) { throw new ArgumentNullException(nameof(task)); } if (m_disposed) { return; } Logger.LogDebug("{functionName} Added task {taskName} to the main flow. ({details})", nameof(Post), task.Name, task.ToString()); m_mainFlow.Post(task); }
/// <summary> /// Processes the specified task on the main skrapr flow. /// </summary> /// <param name="task"></param> /// <returns></returns> private async Task ProcessMainSkraprTask(ISkraprTask task) { try { await ProcessSkraprTask(task); } catch (Exception ex) when(ex is AssertionFailedException || ex is NavigationFailedException) { //Add it back into the queue. m_mainFlow.Post(task); } catch (Exception ex) when(ex is OperationCanceledException || ex is TaskCanceledException) { m_logger.LogWarning("{functionName} is terminating due to a cancellation request.", nameof(ProcessMainSkraprTask)); throw; } catch (Exception ex) { m_logger.LogError("{functionName} An unhandled error occurred while performing task {taskName} on frame {frameId}: {exception}", nameof(ProcessMainSkraprTask), task.Name, DevTools.CurrentFrameId, ex); throw; } //Get matching rules for the state of the session. var matchingRules = await GetMatchingRules(); foreach (var rule in matchingRules) { m_logger.LogDebug("{functionName} Found rule that matches current frame state: ({ruleType} - {details})", nameof(ProcessSkraprTask), rule.Type, rule.ToString()); var ruleSubflow = new Tasks.SubFlowTask() { Tasks = rule.Tasks }; Post(ruleSubflow); if (rule.Max.HasValue) { rule.Max -= 1; } } if (matchingRules.Count() == 0) { m_logger.LogDebug("{functionName} A rule was not found that matches the current frame state for task {taskName}: ({details})", nameof(ProcessSkraprTask), task.Name, task.ToString()); } //If there are no more tasks in the main flow... if (m_mainFlow.InputCount == 0) { //and there are no more shutdown tasks, complete. if (m_definition.Shutdown == null || m_definition.Shutdown.Count == 0) { m_logger.LogDebug("{functionName} Completed processing all tasks in the main flow. Completing.", nameof(ProcessSkraprTask)); m_mainFlow.Complete(); } //add any shutdown tasks to the flow. else { m_logger.LogDebug("{functionName} Adding shutdown tasks to the main flow.", nameof(ProcessSkraprTask)); foreach (var shutdownTask in m_definition.Shutdown) { m_mainFlow.Post(shutdownTask); } m_definition.Shutdown.Clear(); } } }
DataflowMessageStatus ITargetBlock <ISkraprTask> .OfferMessage(DataflowMessageHeader messageHeader, ISkraprTask messageValue, ISourceBlock <ISkraprTask> source, bool consumeToAccept) { return(((ITargetBlock <ISkraprTask>)m_mainFlow).OfferMessage(messageHeader, messageValue, source, consumeToAccept)); }