using Serein.Library; using Serein.Library.Utils; using System; using System.Collections.Generic; using System.Data.Common; using System.Globalization; using System.Linq; using System.Threading.Tasks; namespace Serein.Library.Api { /// /// 流程上下文,包含运行环境接口,可以通过注册环境事件或调用环境接口,实现在流程运行时更改流程行为。 /// public interface IFlowContext { /// /// 是否记录流程信息 /// bool IsRecordInvokeInfo { get; set; } /// /// 标识流程 /// string Guid {get; } /// /// 运行环境 /// IFlowEnvironment Env { get; } /// /// 是否正在运行 /// RunState RunState { get; } /// /// 下一个要执行的节点类别 /// ConnectionInvokeType NextOrientation { get; set; } /// /// 运行时异常信息 /// Exception ExceptionOfRuning { get; set; } /// /// 获取当前流程上下文的所有节点调用信息,包含每个节点的执行时间、调用类型、执行状态等。 /// /// List GetAllInvokeInfos(); /// /// 新增当前流程上下文的节点调用信息。 /// FlowInvokeInfo NewInvokeInfo(IFlowNode previousNode, IFlowNode theNode, FlowInvokeInfo.InvokeType invokeType); /// /// 获取节点的运行时参数数据 /// /// 节点 /// 第几个参数 /// 数据 void SetParamsTempData(string nodeModel, int index, object data); /// /// 获取节点的运行时参数数据 /// /// 节点 /// 第几个参数 /// 获取到的参数 bool TryGetParamsTempData(string nodeModel, int index, out object data); /// /// 设置节点的运行时上一节点,用以多线程中隔开不同流程的数据 /// /// 当前节点 /// 运行时上一节点 void SetPreviousNode(string currentNodeModel, string PreviousNode); /// /// 获取当前节点的运行时上一节点,用以流程中获取数据 /// /// /// string GetPreviousNode(string currentNodeModel); /// /// 获取节点的数据(当前节点需要获取上一节点数据时,需要从 运行时上一节点 的Guid 通过这个方法进行获取 /// /// /// FlowResult GetFlowData(string nodeModel); /// /// 上一节点数据透传到下一节点 /// /// FlowResult TransmissionData(string nodeModel); /// /// 添加或更新当前节点的数据 /// /// /// void AddOrUpdateFlowData(string nodeModel, FlowResult flowData); /// /// 添加或更新当前节点的数据 /// /// /// void AddOrUpdate(string nodeModel, object data); /// /// 重置流程状态(用于对象池回收) /// void Reset(); /// /// 用以提前结束当前上下文流程的运行 /// void Exit(); } /// /// 流程调用信息,记录每个节点的调用信息,包括执行时间、调用类型、执行状态等。 /// public sealed class FlowInvokeInfo { /// /// 调用类型枚举,指示节点的调用方式。 /// public enum InvokeType { /// /// 初始化。 /// None = -1, /// /// 上游分支调用,指向上游流程的节点。 /// Upstream = 0, /// /// 真分支调用,指示节点执行成功后的分支。 /// IsSucceed = 1, /// /// 假分支调用,指示节点执行失败后的分支。 /// IsFail = 2, /// /// 异常发生分支调用,指示节点执行过程中发生异常后的分支。 /// IsError = 3, /// /// 参数来源调用,标明此次调用出自其它节点需要参数时的执行。 /// ArgSource = 4, } /// /// 运行状态枚举,指示节点的执行结果。 /// public enum RunState { /// /// 初始化 /// None = -1, /// /// 正在运行,指示节点正在执行中。 /// Running = 0, /// /// 执行成功,指示节点执行完成且结果正常。 /// Succeed = 1, /// /// 执行失败,指示节点执行完成但结果异常或不符合预期。 /// Failed = 2, /// /// 执行异常,指示节点在执行过程中发生了未处理的异常。 /// Error = 3, } /// /// 流程上下文标识符,唯一标识一个流程上下文 /// public string ContextGuid { get; set; } /// /// 节点执行信息标识符,唯一标识一个节点执行信息 /// public long Id { get; set; } /// /// 上一节点的唯一标识符,指向流程图中的上一个节点 /// public string PreviousNodeGuid { get; set; } /// /// 节点唯一标识符,指向流程图中的节点 /// public string NodeGuid { get; set; } /// /// 执行时间,记录节点执行的时间戳 /// public DateTime StateTime { get; } = DateTime.Now; /// /// 节点调用类型,指示节点的调用方式 /// public InvokeType Type { get; set; } /// /// 节点方法名称,指示节点执行的方法 /// public string Method { get; set; } /// /// 节点执行状态,指示节点的执行结果 /// public RunState State { get; set; } /// /// 耗时,记录节点执行的耗时(单位:毫秒) /// public TimeSpan TS { get; private set; } = TimeSpan.Zero; /// /// 节点参数,存储节点执行时的参数信息 /// public string[] Parameters { get; private set; } /// /// 节点执行结果,存储节点执行后的结果信息 /// public string Result { get; private set; } /// /// 上传当前节点的执行状态和结果信息。 /// /// public void UploadState(RunState runState) { State = runState; TS = DateTime.Now - StateTime; } /// /// 上传当前节点的执行结果值。 /// /// public void UploadResultValue(object value = null) { if(value is null) { Result = string.Empty; } else { var type = value.GetType(); Result = $"{type.FullName}::{value}"; } } /// /// 上传当前节点的执行参数信息。 /// /// public void UploadParameters(object[] values = null) { if (values is null) { Parameters = []; } else { Parameters = values.Select(v => v.ToString()).ToArray(); } } /// /// 返回当前节点的执行信息字符串,包含状态、耗时和结果。 /// /// public override string ToString() { return $"[{State}]{TS.TotalSeconds:0.000}ms : {Result}"; } } }