private async Task ExcutingWithTasks(TTData data, NodeResp <TTRes> nodeResp, IList <IEventTask <TTData> > tasks, int triedTimes) { if (NodeMeta.Process_type == NodeProcessType.Parallel) { await this.Excuting_Parallel(data, nodeResp, tasks, triedTimes); } else { await this.Excuting_Serial(data, nodeResp, tasks, triedTimes); } // 处理回退其他任务 if (nodeResp.node_status == NodeStatus.ProcessFailedRevert) { var revertTasks = triedTimes > 0 ? (await GetTasks()) : tasks; if (NodeMeta.Process_type == NodeProcessType.Parallel) { await this.Excuting_ParallelRevert(data, nodeResp, revertTasks, nodeResp.block_taskid, triedTimes); } else { await this.Excuting_SerialRevert(data, nodeResp, revertTasks, nodeResp.block_taskid, triedTimes); } } }
/// <summary> /// 处理入口 /// </summary> /// <param name="data">请求数据</param> /// <param name="triedTimes">已经处理过的次数,重试时需要传入</param> /// <param name="taskIds">重试的任务Id</param> /// <returns></returns> public Task <NodeResp <TTRes> > Process(TTData data, int triedTimes, params string[] taskIds) { var nodeResp = new NodeResp <TTRes> { node_status = NodeStatus.WaitProcess }; return(TryProcess(data, nodeResp, triedTimes, taskIds)); }
// 基类入口方法 public Task <NodeResp <TTRes> > Process(TTData data) { var nodeResp = new NodeResp <TTRes> { node_status = NodeStatus.WaitProcess }; return(TryProcess(data, nodeResp, 0, null)); }
private async Task <NodeResp <TTRes> > TryProcess(TTData data, NodeResp <TTRes> nodeResp, int triedTimes, params string[] taskIds) { try { // 检查初始化 var checkRes = await ProcessCheck(data, nodeResp, triedTimes, taskIds); if (!checkRes) { return(nodeResp); } // 【2】 任务处理执行方法 await Excuting(data, nodeResp, triedTimes, taskIds); var pResp = await Processed(data, nodeResp.node_status, nodeResp.TaskResults, triedTimes); if (pResp != null) { nodeResp.node_status = pResp.node_status; nodeResp.resp = pResp.resp; } // 【3】 扩展后置执行方法 await ProcessEnd(data, nodeResp, triedTimes); // 结束, 如果节点是暂停状态,需要保存上下文请求信息 if (nodeResp.node_status == NodeStatus.ProcessPaused) { await TrySaveNodeContext(data, nodeResp); } return(nodeResp); } catch (Exception e) { nodeResp.node_status = NodeStatus.ProcessFailed; nodeResp.resp = new TTRes().WithResp(SysRespTypes.ApplicationError, "Error occurred during Node [Process]!"); LogHelper.Error($"sys_ret:{nodeResp.resp.sys_ret}, ret:{nodeResp.resp.ret},msg:{nodeResp.resp.msg}, Detail:{e}", NodeMeta.node_id, EventTaskProvider.ModuleName); } await TrySaveNodeContext(data, nodeResp); return(nodeResp); }
// 根据任务结果格式化当前节点结果, 外部循环使用 internal static bool FormatNodeErrorResp<TTRes>(NodeResp<TTRes> nodeResp, TaskResp<Resp> taskResp, TaskMeta tMeta) where TTRes : Resp, new() { var status = NodeStatus.ProcessCompoleted; if (!taskResp.run_status.IsCompleted()) { var haveError = true; switch (tMeta.node_action) { case NodeResultAction.PauseOnFailed: status = NodeStatus.ProcessPaused; break; case NodeResultAction.FailedOnFailed: status = taskResp.run_status == TaskRunStatus.RunFailed ? NodeStatus.ProcessFailed : NodeStatus.ProcessPaused; break; case NodeResultAction.RevrtAllOnFailed: status = taskResp.run_status == TaskRunStatus.RunFailed ? NodeStatus.ProcessFailedRevert : NodeStatus.ProcessPaused; break; default: haveError = false; break; } if (haveError) { if (status < nodeResp.node_status) { nodeResp.node_status = status; nodeResp.resp = ConvertToNodeResult<TTRes>(taskResp.resp); } return true; } } if (nodeResp.node_status == NodeStatus.ProcessCompoleted && taskResp.resp is TTRes nres) { nodeResp.resp = nres; } return false; }
private Task TrySaveNodeContext(TTData data, NodeResp <TTRes> nodeResp) { try { var blockTaskResp = nodeResp[nodeResp.block_taskid]; return(nodeResp.node_status == NodeStatus.ProcessPaused ? SaveNodekContext(data, nodeResp.resp, blockTaskResp.task_cond, nodeResp.TaskResults) : SaveErrorNodeContext(data, nodeResp.resp, blockTaskResp.task_cond, nodeResp.TaskResults)); } catch (Exception e) { // 防止Provider中SaveTaskContext内部使用Task实现时,级联异常死循环 LogHelper.Error($"Errors occurred during [Task context] saving. Detail:{e}", NodeMeta.node_id, EventTaskProvider.ModuleName); } return(Task.CompletedTask); }
internal virtual async Task Excuting(TTData data, NodeResp <TTRes> nodeResp, int triedTimes, params string[] taskIds) { // 获取任务元数据列表 var tasks = await GetTasks(); if (tasks != null && triedTimes > 0) { tasks = tasks.Where(t => taskIds.Contains(t.TaskMeta.task_id)).ToList(); } if (tasks == null || !tasks.Any()) { //nodeResp.node_status = NodeStatus.ProcessFailed; //nodeResp.resp = new TTRes().WithResp(SysRespTypes.ApplicationError, ResultTypes.ObjectNull, // $"{this.GetType()} have no tasks can be Runed!"); return; } // 执行处理结果 await ExcutingWithTasks(data, nodeResp, tasks, triedTimes); }
/// 顺序执行 internal static async Task Excuting_Serial <TTData, TTRes>(this BaseNode <TTData, TTRes> node, TTData data, NodeResp <TTRes> nodeResp, IList <IEventTask <TTData> > tasks, int triedTimes) where TTData : class where TTRes : Resp, new() { nodeResp.TaskResults = new Dictionary <TaskMeta, TaskResp <Resp> >(tasks.Count); nodeResp.node_status = NodeStatus.ProcessCompoleted; // 默认成功,给出最大值,循环内部处理 foreach (var tItem in tasks) { var taskResp = await ExecutorUtil.TryGetTaskItemResult(data, tItem, triedTimes); var tMeta = tItem.TaskMeta; nodeResp.TaskResults.Add(tMeta, taskResp); var haveError = ExecutorUtil.FormatNodeErrorResp(nodeResp, taskResp, tMeta); if (haveError) { nodeResp.block_taskid = tMeta.task_id; break; } } }
private async Task <bool> ProcessCheck(TTData data, NodeResp <TTRes> nodeResp, int triedTimes, params string[] taskIds) { if (triedTimes > 0 && (taskIds == null || taskIds.Length == 0)) { nodeResp.node_status = NodeStatus.ProcessFailed; nodeResp.resp = new TTRes() { sys_ret = (int)SysRespTypes.ApplicationError, msg = "Have no tasks to run" }; return(false); } var res = await ProcessInitial(data, triedTimes); if (res != null && !res.IsSuccess()) { nodeResp.node_status = NodeStatus.ProcessFailed; nodeResp.resp = new TTRes().WithResp(res);// res.ConvertToResultInherit<TTRes>(); return(false); } return(true); }
// 并行执行任务扩展 internal static async Task Excuting_Parallel <TTData, TTRes>(this BaseNode <TTData, TTRes> node, TTData data, NodeResp <TTRes> nodeResp, IList <IEventTask <TTData> > tasks, int triedTimes) where TTData : class where TTRes : Resp, new() { var taskResults = tasks.ToDictionary(t => t, t => ExecutorUtil.TryGetTaskItemResult(data, t, triedTimes)); try { await Task.WhenAll(taskResults.Select(tr => tr.Value)); } catch (Exception ex) { LogUtil.Error(ex, node.NodeMeta.node_id, EventTaskProvider.ModuleName); } var taskResps = taskResults.ToDictionary(d => d.Key, d => d.Value.Status == TaskStatus.Faulted ? new TaskResp <Resp>().WithError(TaskRunStatus.RunFailed, new RunCondition()) : d.Value.Result); nodeResp.TaskResults = taskResps.ToDictionary(tk => tk.Key.TaskMeta, tk => tk.Value); nodeResp.node_status = NodeStatus.ProcessCompoleted; // 循环里会处理结果,这里给出最大值 foreach (var tItemRes in taskResps) { var isBlocked = ExecutorUtil.FormatNodeErrorResp(nodeResp, tItemRes.Value, tItemRes.Key.TaskMeta); if (isBlocked) { nodeResp.block_taskid = tItemRes.Key.TaskMeta.task_id; if (nodeResp.node_status == NodeStatus.ProcessFailedRevert) { break; } } } }
/// <summary> /// 节点处理结束 /// </summary> /// <param name="data">处理数据</param> /// <param name="resp">节点处理返回值</param> /// <param name="triedTimes">已经处理过的次数</param> /// <returns></returns> protected virtual Task ProcessEnd(TTData data, NodeResp <TTRes> resp, int triedTimes) { return(Task.CompletedTask); }
// 顺序任务 回退当前任务之前所有任务 internal static async Task Excuting_SerialRevert <TTData, TTRes>(this BaseNode <TTData, TTRes> node, TTData data, NodeResp <TTRes> nodeResp, IList <IEventTask <TTData> > tasks, string blockTaskId, int triedTimes) where TTData : class where TTRes : Resp, new() { if (nodeResp.RevrtTasks == null) { nodeResp.RevrtTasks = new List <TaskMeta>(tasks.Count); } foreach (var tItem in tasks) { if (tItem.TaskMeta.task_id == blockTaskId) { nodeResp.RevrtTasks.Add(tItem.TaskMeta); break; } var rRes = await ExecutorUtil.TryRevertTask(tItem, data, triedTimes);// tItem.Revert(data); if (rRes) { nodeResp.RevrtTasks.Add(tItem.TaskMeta); } } }
// 并行任务回退处理(回退当前其他所有任务) internal static async Task Excuting_ParallelRevert <TTData, TTRes>(this BaseNode <TTData, TTRes> node, TTData data, NodeResp <TTRes> nodeResp, IList <IEventTask <TTData> > tasks, string blockTaskId, int triedTimes) where TTData : class where TTRes : Resp, new() { var revResList = tasks.Select(tItem => tItem.TaskMeta.task_id == blockTaskId ? Task.FromResult(true) : ExecutorUtil.TryRevertTask(tItem, data, triedTimes)) .ToArray(); try { await Task.WhenAll(revResList); } catch (Exception ex) { LogUtil.Error($"An error occurred while the parallel node reverted all tasks. Detail:{ex}", node.NodeMeta.node_id, EventTaskProvider.ModuleName); } if (nodeResp.RevrtTasks == null) { nodeResp.RevrtTasks = new List <TaskMeta>(tasks.Count); } for (var i = 0; i < tasks.Count; i++) { var res = false; var resT = revResList[i]; if (resT.Status == TaskStatus.RanToCompletion) { res = resT.Result; } if (res) { nodeResp.RevrtTasks.Add(tasks[i].TaskMeta); } } }