using Serein.Library.Api;
using Serein.Library.Utils;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Serein.Library
{
///
/// 流程调用树,管理所有的调用节点
///
public class FlowCallTree : IFlowCallTree
{
private readonly SortedDictionary _callNodes = new SortedDictionary();
//private readonly Dictionary _callNodes = new Dictionary();
///
/// 索引器,允许通过字符串索引访问CallNode
///
///
///
public CallNode this[string index]
{
get
{
_callNodes.TryGetValue(index, out CallNode callNode);
return callNode;
}
set
{
// 设置指定索引的值
_callNodes.Add(index, value);
}
}
///
/// 添加一个调用节点到流程调用树中
///
///
///
public void AddCallNode(string nodeGuid, Action action)
{
var node = new CallNode(nodeGuid, action);
_callNodes[nodeGuid] = node;
}
///
/// 添加一个调用节点到流程调用树中,使用异步函数
///
///
///
public void AddCallNode(string nodeGuid, Func func)
{
var node = new CallNode(nodeGuid, func);
_callNodes[nodeGuid] = node;
}
///
/// 获取指定Key的CallNode,如果不存在则返回null
///
///
///
public CallNode Get(string key)
{
return _callNodes.TryGetValue(key, out CallNode callNode) ? callNode : null;
}
}
///
/// 调用节点,代表一个流程中的调用点,可以是一个Action或一个异步函数。
///
public class CallNode
{
private Func taskFunc;
private Action action;
///
/// 创建一个新的调用节点,使用指定的节点Guid。
///
///
public CallNode(string nodeGuid)
{
Guid = nodeGuid;
Init();
}
///
/// 创建一个新的调用节点,使用指定的节点Guid和Action。
///
///
///
public CallNode(string nodeGuid, Action action)
{
Guid = nodeGuid;
this.action = action;
Init();
}
///
/// 创建一个新的调用节点,使用指定的节点Guid和异步函数。
///
///
///
public CallNode(string nodeGuid, Func func)
{
Guid = nodeGuid;
this.taskFunc = func;
Init();
}
///
/// 初始化调用节点,设置默认的子节点和后继节点字典。
///
private void Init()
{
//PreviousNodes = new Dictionary>();
SuccessorNodes = new Dictionary>();
foreach (ConnectionInvokeType ctType in NodeStaticConfig.ConnectionTypes)
{
//PreviousNodes[ctType] = new List();
SuccessorNodes[ctType] = new List();
}
}
private enum ActionType
{
Action,
Task,
}
private ActionType actionType = ActionType.Action;
///
/// 设置调用节点的Action,表示该节点执行一个同步操作。
///
///
public void SetAction(Action action)
{
this.action = action;
actionType = ActionType.Action;
}
///
/// 设置调用节点的异步函数,表示该节点执行一个异步操作。
///
///
public void SetAction(Func taskFunc)
{
this.taskFunc = taskFunc;
actionType = ActionType.Task;
}
///
/// 对应的节点
///
public string Guid { get; }
#if false
///
/// 不同分支的父节点(流程调用)
///
public Dictionary> PreviousNodes { get; private set; }
#endif
///
/// 不同分支的子节点(流程调用)
///
public Dictionary> SuccessorNodes { get; private set; }
///
/// 子节点数组,分为四个分支:上游、成功、失败、错误,每个分支最多支持16个子节点。
///
public CallNode[][] ChildNodes { get; private set; } = new CallNode[][]
{
new CallNode[MaxChildNodeCount],
new CallNode[MaxChildNodeCount],
new CallNode[MaxChildNodeCount],
new CallNode[MaxChildNodeCount]
};
private const int MaxChildNodeCount = 16; // 每个分支最多支持16个子节点
///
/// 获取指定类型的子节点数量。
///
///
///
public int GetCount(ConnectionInvokeType type)
{
if (type == ConnectionInvokeType.Upstream) return UpstreamNodeCount;
if (type == ConnectionInvokeType.IsSucceed) return IsSuccessorNodeCount;
if (type == ConnectionInvokeType.IsFail) return IsFailNodeCount;
if (type == ConnectionInvokeType.IsError) return IsErrorNodeCount;
return 0;
}
///
/// 获取当前节点的子节点数量。
///
public int UpstreamNodeCount { get; private set; } = 0;
///
/// 获取当前节点的成功后继子节点数量。
///
public int IsSuccessorNodeCount { get; private set; } = 0;
///
/// 获取当前节点的失败后继子节点数量。
///
public int IsFailNodeCount { get; private set; } = 0;
///
/// 获取当前节点的错误后继子节点数量。
///
public int IsErrorNodeCount { get; private set; } = 0;
///
/// 添加一个上游子节点到当前节点。
///
///
///
public CallNode AddChildNodeUpstream(CallNode callNode)
{
var connectionInvokeType = ConnectionInvokeType.Upstream;
ChildNodes[(int)connectionInvokeType][UpstreamNodeCount++] = callNode;
SuccessorNodes[connectionInvokeType].Add(callNode);
return this;
}
///
/// 添加一个成功后继子节点到当前节点。
///
///
///
public CallNode AddChildNodeSucceed(CallNode callNode)
{
ChildNodes[0][UpstreamNodeCount++] = callNode;
var connectionInvokeType = ConnectionInvokeType.IsSucceed;
ChildNodes[(int)connectionInvokeType][IsSuccessorNodeCount++] = callNode;
SuccessorNodes[connectionInvokeType].Add(callNode);
return this;
}
///
/// 添加一个失败后继子节点到当前节点。
///
///
///
public CallNode AddChildNodeFail(CallNode callNode)
{
var connectionInvokeType = ConnectionInvokeType.IsFail;
ChildNodes[(int)connectionInvokeType][IsFailNodeCount++] = callNode;
SuccessorNodes[connectionInvokeType].Add(callNode);
return this;
}
///
/// 添加一个错误后继子节点到当前节点。
///
///
///
public CallNode AddChildNodeError(CallNode callNode)
{
var connectionInvokeType = ConnectionInvokeType.IsError;
ChildNodes[(int)connectionInvokeType][IsErrorNodeCount++] = callNode;
SuccessorNodes[connectionInvokeType].Add(callNode);
return this;
}
///
/// 调用
///
///
///
///
///
public async Task InvokeAsync(IFlowContext context, CancellationToken token)
{
if (token.IsCancellationRequested)
{
return;
}
if (actionType == ActionType.Action)
{
action.Invoke(context);
}
else if (actionType == ActionType.Task)
{
await taskFunc.Invoke(context);
}
else
{
throw new InvalidOperationException($"生成了错误的CallNode。【{Guid}】");
}
}
private static readonly ObjectPool> _stackPool = new ObjectPool>(() => new Stack());
///
/// 开始执行
///
///
/// 流程运行
///
public async Task StartFlowAsync(IFlowContext context, CancellationToken token)
{
var stack = _stackPool.Allocate();
stack.Push(this);
while (true)
{
if (token.IsCancellationRequested)
{
throw new Exception($"流程执行被取消,未能获取到流程结果。");
}
#region 执行相关
// 从栈中弹出一个节点作为当前节点进行处理
var currentNode = stack.Pop();
context.NextOrientation = ConnectionInvokeType.None; // 重置上下文状态
FlowResult flowResult = null;
try
{
context.NextOrientation = ConnectionInvokeType.IsSucceed; // 默认执行成功
await currentNode.InvokeAsync(context, token);
}
catch (Exception ex)
{
flowResult = FlowResult.Fail(currentNode.Guid, context, ex.Message);
context.Env.WriteLine(InfoType.ERROR, $"节点[{currentNode}]异常:" + ex);
context.NextOrientation = ConnectionInvokeType.IsError;
context.ExceptionOfRuning = ex;
}
#endregion
#region 执行完成时更新栈
// 首先将指定类别后继分支的所有节点逆序推入栈中
var nextNodes = currentNode.SuccessorNodes[context.NextOrientation];
for (int index = nextNodes.Count - 1; index >= 0; index--)
{
var node = nextNodes[index];
context.SetPreviousNode(node.Guid, currentNode.Guid);
stack.Push(node);
}
// 然后将指上游分支的所有节点逆序推入栈中
var upstreamNodes = currentNode.SuccessorNodes[ConnectionInvokeType.Upstream];
for (int index = upstreamNodes.Count - 1; index >= 0; index--)
{
var node = upstreamNodes[index];
context.SetPreviousNode(node.Guid, currentNode.Guid);
stack.Push(node);
}
#endregion
#region 执行完成后检查
if (stack.Count == 0)
{
_stackPool.Free(stack);
flowResult = context.GetFlowData(currentNode.Guid);
return flowResult; // 说明流程到了终点
}
if (context.RunState == RunState.Completion)
{
_stackPool.Free(stack);
context.Env.WriteLine(InfoType.INFO, $"流程执行到节点[{currentNode.Guid}]时提前结束,将返回当前执行结果。");
flowResult = context.GetFlowData(currentNode.Guid);
return flowResult; // 流程执行完成,返回结果
}
if (token.IsCancellationRequested)
{
_stackPool.Free(stack);
throw new Exception($"流程执行到节点[{currentNode.Guid}]时被取消,未能获取到流程结果。");
}
#endregion
}
}
}
///
/// 流程调用树接口,提供获取CallNode的方法。
///
public interface IFlowCallTree
{
///
/// 获取指定Key的CallNode,如果不存在则返回null。
///
///
///
CallNode Get(string key);
}
///
/// 轻量级流程控制器
///
public class LightweightFlowControl : IFlowControl
{
private readonly IFlowCallTree flowCallTree;
private readonly IFlowEnvironment flowEnvironment;
///
/// 轻量级流程上下文池,使用对象池模式来管理流程上下文的创建和回收。
///
public static Serein.Library.Utils.ObjectPool FlowContextPool { get; set; }
///
/// 单例IOC容器,用于依赖注入和服务定位。
///
public ISereinIOC IOC => throw new NotImplementedException();
///
/// 轻量级流程控制器构造函数,接受流程调用树和流程环境作为参数。
///
///
///
public LightweightFlowControl(IFlowCallTree flowCallTree, IFlowEnvironment flowEnvironment)
{
this.flowCallTree = flowCallTree;
this.flowEnvironment = flowEnvironment;
FlowContextPool = new Utils.ObjectPool(() =>
{
return new FlowContext(flowEnvironment);
});
}
///
public Task