优化了节点加载逻辑

This commit is contained in:
fengjiayi
2025-07-08 17:37:03 +08:00
parent efe4d0a8e5
commit aa3d1763ed
8 changed files with 260 additions and 94 deletions

View File

@@ -504,6 +504,7 @@ namespace Serein.NodeFlow.Env
#endregion
await Task.Delay(100);
#region
foreach (var nodeInfo in nodeInfos)
{
@@ -513,14 +514,13 @@ namespace Serein.NodeFlow.Env
return;
}
if (fromNodeModel is null) continue;
List<(ConnectionInvokeType connectionType, string[] guids)> allToNodes = [(ConnectionInvokeType.IsSucceed,nodeInfo.TrueNodes),
(ConnectionInvokeType.IsFail, nodeInfo.FalseNodes),
(ConnectionInvokeType.IsError, nodeInfo.ErrorNodes),
(ConnectionInvokeType.Upstream, nodeInfo.UpstreamNodes)];
foreach ((ConnectionInvokeType connectionType, string[] toNodeGuids) item in allToNodes)
foreach (var kvp in nodeInfo.SuccessorNodes)
{
var type = kvp.Key;
var nodes = kvp.Value;
if (nodes.Length == 0) continue;
// 遍历当前类型分支的节点(确认连接关系)
foreach (var toNodeGuid in item.toNodeGuids)
foreach (var toNodeGuid in nodes)
{
if (!TryGetNodeModel(toNodeGuid, out var toNodeModel))
{
@@ -531,17 +531,76 @@ namespace Serein.NodeFlow.Env
// 防御性代码,加载正常保存的项目文件不会进入这里
continue;
}
ConnectInvokeNode(canvasGuid, fromNodeModel.Guid, toNodeModel.Guid, JunctionType.NextStep, JunctionType.Execute, item.connectionType);
if (fromNodeModel.SuccessorNodes[type].Contains(toNodeModel) || toNodeModel.PreviousNodes[type].Contains(fromNodeModel))
{
continue;
}
ConnectInvokeNode(canvasGuid, fromNodeModel.Guid, toNodeModel.Guid, JunctionType.NextStep, JunctionType.Execute, type);
}
}
}
foreach (var nodeInfo in nodeInfos)
{
var canvasGuid = nodeInfo.CanvasGuid;
if (!TryGetNodeModel(nodeInfo.Guid, out var toNodeModel))
{
return;
}
if (toNodeModel is null) continue;
foreach (var kvp in nodeInfo.PreviousNodes)
{
var type = kvp.Key;
var nodes = kvp.Value;
if (nodes.Length == 0) continue;
// 遍历当前类型分支的节点(确认连接关系)
foreach (var toNodeGuid in nodes)
{
if (!TryGetNodeModel(toNodeGuid, out var fromNodeModel))
{
return;
}
if (toNodeModel is null)
{
// 防御性代码,加载正常保存的项目文件不会进入这里
continue;
}
if (fromNodeModel.SuccessorNodes[type].Contains(toNodeModel) || toNodeModel.PreviousNodes[type].Contains(fromNodeModel))
{
continue;
}
ConnectInvokeNode(canvasGuid, fromNodeModel.Guid, toNodeModel.Guid, JunctionType.NextStep, JunctionType.Execute, type);
}
}
}
#endregion
#region
var nodeModels = flowModelService.GetAllNodeModel();
foreach (var nodeInfo in nodeInfos)
{
var pdInfos = nodeInfo.ParameterData;
var toNodeGuid = nodeInfo.Guid;
for (global::System.Int32 index = 0; index < pdInfos.Length; index++)
{
var pdInfo = pdInfos[index];
var fromNodeGuid = pdInfo.SourceNodeGuid;
if (!string.IsNullOrWhiteSpace(fromNodeGuid) && flowModelService.TryGetCanvasModel(fromNodeGuid,out var fromNode))
{
continue;
}
var type = EnumHelper.ConvertEnum<ConnectionArgSourceType>(pdInfo.SourceType);
var canvasGuid = nodeInfo.CanvasGuid;
ConnectArgSourceNode(canvasGuid, fromNodeGuid, toNodeGuid, JunctionType.ReturnData, JunctionType.ArgData, type,index);
}
}
/* var nodeModels = flowModelService.GetAllNodeModel();
foreach (var toNode in nodeModels)
{
var canvasGuid = toNode.CanvasDetails.Guid;
@@ -555,10 +614,16 @@ namespace Serein.NodeFlow.Env
if (!string.IsNullOrEmpty(pd.ArgDataSourceNodeGuid)
&& TryGetNodeModel(pd.ArgDataSourceNodeGuid, out var fromNode))
{
*//*if (fromNode.NeedResultNodes[pd.ArgDataSourceType].Contains(toNode)
&& pd.ArgDataSourceNodeGuid == fromNode.Guid
&& )
{
continue;
}*//*
ConnectArgSourceNode(canvasGuid, fromNode.Guid, toNode.Guid, JunctionType.ReturnData, JunctionType.ArgData, pd.ArgDataSourceType, pd.Index);
}
}
}
}*/
#endregion

View File

@@ -627,7 +627,7 @@ namespace Serein.NodeFlow.Services
// 初始化 Get 函数
var nodeIndexName = "node_index";
sb.AppendCode(2, $" [MethodImpl(MethodImplOptions.AggressiveInlining)]"); // 内联优化
//sb.AppendCode(2, $" [MethodImpl(MethodImplOptions.AggressiveInlining)]"); // 内联优化
sb.AppendCode(2, $"public global::Serein.Library.CallNode {nameof(IFlowCallTree.Get)}( global::System.String key)");
sb.AppendCode(2, $"{{");
sb.AppendCode(3, $"global::System.Int32 {nodeIndexName};");
@@ -703,7 +703,6 @@ namespace Serein.NodeFlow.Services
}
private void GenerateFlowApi_ApiParamClass(StringBuilder sb)
{
var infos = flowApiMethodInfos.Values.ToArray();
@@ -887,6 +886,7 @@ namespace Serein.NodeFlow.Services
var contextImpleFullName = $"global::{typeof(DynamicContext).FullName}";
var tokenSourceFullName = $"global::{typeof(CancellationTokenSource).FullName}";
var tokenFullName = $"global::{typeof(CancellationToken).FullName}";
var flowContextPoolName = $"global::{typeof(LightweightFlowControl).FullName}";
string flowEnvironment = nameof(flowEnvironment);
string flowContext = nameof(flowContext);
string token = nameof(token);
@@ -902,11 +902,22 @@ namespace Serein.NodeFlow.Services
var invokeParamSignature = string.Join(", ", ParamInfos.Select(p => p.ParamName));
sb.AppendCode(2, $"public async {returnTypeContext} {ApiMethodName}({paramSignature})");
sb.AppendCode(2, $"{{");
sb.AppendCode(3, $"{contextApiFullName} {flowContext} = new {contextImpleFullName}({flowEnvironment}); // 创建上下文");
sb.AppendCode(3, $"{tokenSourceFullName} cts = new {tokenSourceFullName}(); // 创建取消令牌");
sb.AppendCode(3, $"await {ApiMethodName}({flowContext}, cts.Token, {invokeParamSignature}); // 调用目标方法");
sb.AppendCode(3, $"{flowContext}.{nameof(IDynamicContext.Reset)}(); ");
sb.AppendCode(3, $"cts.{nameof(CancellationTokenSource.Dispose)}(); ");
sb.AppendCode(3, $"{contextApiFullName} {flowContext} = {flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Allocate)}(); // 从对象池获取一个上下文");
sb.AppendCode(3, $"{tokenSourceFullName} cts = new {tokenSourceFullName}(); // 创建取消令牌");
sb.AppendCode(3, $"try");
sb.AppendCode(3, $"{{");
sb.AppendCode(4, $"await {ApiMethodName}({flowContext}, cts.Token, {invokeParamSignature}); // 调用目标方法");
sb.AppendCode(3, $"}}");
sb.AppendCode(3, $"catch (Exception)");
sb.AppendCode(3, $"{{");
sb.AppendCode(4, $"throw;");
sb.AppendCode(3, $"}}");
sb.AppendCode(3, $"finally");
sb.AppendCode(3, $"{{");
sb.AppendCode(4, $"{flowContext}.{nameof(IDynamicContext.Reset)}(); ");
sb.AppendCode(4, $"cts.{nameof(CancellationTokenSource.Dispose)}(); ");
sb.AppendCode(4, $"{flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Free)}({flowContext}); // 释放上下文");
sb.AppendCode(3, $"}}");
sb.AppendCode(2, $"}}");
return sb.ToString();
}
@@ -916,9 +927,20 @@ namespace Serein.NodeFlow.Services
var invokeParamSignature = string.Join(", ", ParamInfos.Select(p => p.ParamName));
sb.AppendCode(2, $"public async {returnTypeContext} {ApiMethodName}({tokenFullName} {token}, {paramSignature})");
sb.AppendCode(2, $"{{");
sb.AppendCode(3, $"{contextApiFullName} {flowContext} = new {contextImpleFullName}({flowEnvironment}); // 创建上下文");
sb.AppendCode(3, $"await {ApiMethodName}({flowContext}, {token}, {invokeParamSignature}); // 调用目标方法");
sb.AppendCode(3, $"{flowContext}.{nameof(IDynamicContext.Reset)}(); ");
sb.AppendCode(3, $"{contextApiFullName} {flowContext} = {flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Allocate)}(); // 从对象池获取一个上下文");
sb.AppendCode(3, $"try");
sb.AppendCode(3, $"{{");
sb.AppendCode(4, $"await {ApiMethodName}({flowContext}, {token}, {invokeParamSignature}); // 调用目标方法");
sb.AppendCode(4, $"{flowContext}.{nameof(IDynamicContext.Reset)}(); ");
sb.AppendCode(3, $"}}");
sb.AppendCode(3, $"catch (Exception)");
sb.AppendCode(3, $"{{");
sb.AppendCode(4, $"throw;");
sb.AppendCode(3, $"}}");
sb.AppendCode(3, $"finally");
sb.AppendCode(3, $"{{");
sb.AppendCode(4, $"{flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Free)}({flowContext}); // 释放上下文");
sb.AppendCode(3, $"}}");
sb.AppendCode(2, $"}}");
return sb.ToString();
}
@@ -930,21 +952,28 @@ namespace Serein.NodeFlow.Services
sb.AppendCode(2, $"public async {returnTypeContext} {ApiMethodName}({contextApiFullName} {flowContext}, {tokenFullName} token, {paramSignature})");
sb.AppendCode(2, $"{{");
sb.AppendCode(3, $"token.ThrowIfCancellationRequested(); // 检查任务是否取消");
// 生成参数类实例化代码
sb.AppendCode(3, $"global::{ParamTypeName} data = new global::{ParamTypeName}");
sb.AppendCode(3, $"{{");
sb.AppendCode(3, $"token.ThrowIfCancellationRequested(); // 检查任务是否取消");
sb.AppendCode(3, $"try");
sb.AppendCode(3, $"{{");
sb.AppendCode(3, $"global::{ParamTypeName} data = {ObjPoolName}.Get(); // 从对象池获取一个对象");
for (int index = 0; index < ParamInfos.Count; index++)
{
ParamInfo? info = ParamInfos[index];
sb.AppendCode(4, $"{info.ParamName.ToPascalCase()} = {info.ParamName}; // [{index}] {info.Comments}");
sb.AppendCode(4, $"data.{info.ParamName.ToPascalCase()} = {info.ParamName}; // [{index}] {info.Comments}");
}
sb.AppendCode(3, $"}}");
sb.AppendCode(3, $"{flowContext}.{nameof(IDynamicContext.AddOrUpdate)}(\"{ApiMethodName}\", data);");
sb.AppendCode(3, $"{flowContext}.{nameof(IDynamicContext.SetPreviousNode)}(\"{NodeModel.Guid}\", \"{ApiMethodName}\");");
sb.AppendCode(3, $"global::{typeof(CallNode).FullName} node = Get(\"{NodeModel.Guid}\");");
sb.AppendCode(3, $"await node.{nameof(CallNode.StartFlowAsync)}({flowContext}, {token}); // 调用目标方法");
sb.AppendCode(3, $"{flowContext}.{nameof(IDynamicContext.AddOrUpdate)}(\"{ApiMethodName}\", data);");
sb.AppendCode(3, $"{flowContext}.{nameof(IDynamicContext.SetPreviousNode)}(\"{NodeModel.TargetNode.Guid}\", \"{ApiMethodName}\");");
sb.AppendCode(3, $"global::{typeof(CallNode).FullName} node = Get(\"{NodeModel.Guid}\");");
sb.AppendCode(3, $"await node.{nameof(CallNode.StartFlowAsync)}({flowContext}, {token}); // 调用目标方法");
sb.AppendCode(3, $"}}");
sb.AppendCode(3, $"catch (Exception)");
sb.AppendCode(3, $"{{");
sb.AppendCode(4, $"throw;");
sb.AppendCode(3, $"}}");
sb.AppendCode(3, $"finally");
sb.AppendCode(3, $"{{");
sb.AppendCode(4, $"{flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Free)}({flowContext}); // 释放上下文");
sb.AppendCode(3, $"}}");
sb.AppendCode(2, $"}}");
return sb.ToString();
}
@@ -954,16 +983,29 @@ namespace Serein.NodeFlow.Services
string flowResult = nameof(flowResult);
if (type == ParamType.Defute)
{
//sb.AppendCode(3, $"{contextApiFullName} {flowContext} = new {contextImpleFullName}({flowEnvironment}); // 创建上下文");
var paramSignature = string.Join(", ", ParamInfos.Select(p => $"global::{p.Type.FullName} {p.ParamName}"));
var invokeParamSignature = string.Join(", ", ParamInfos.Select(p => p.ParamName));
sb.AppendCode(2, $"public async {returnTypeContext} {ApiMethodName}({paramSignature})");
sb.AppendCode(2, $"{{");
sb.AppendCode(3, $"{contextApiFullName} {flowContext} = new {contextImpleFullName}({flowEnvironment}); // 创建上下文");
sb.AppendCode(3, $"{tokenSourceFullName} cts = new {tokenSourceFullName}(); // 创建取消令牌");
sb.AppendCode(3, $"{ReturnType.FullName} {flowResult} = await {ApiMethodName}({flowContext}, cts.{nameof(CancellationTokenSource.Token)}, {invokeParamSignature}); // 调用目标方法");
sb.AppendCode(3, $"{flowContext}.{nameof(IDynamicContext.Reset)}(); ");
sb.AppendCode(3, $"cts.{nameof(CancellationTokenSource.Dispose)}(); ");
sb.AppendCode(3, $"return {flowResult};");
sb.AppendCode(3, $"{contextApiFullName} {flowContext} = {flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Allocate)}(); // 从对象池获取一个上下文");
sb.AppendCode(3, $"{tokenSourceFullName} cts = new {tokenSourceFullName}(); // 创建取消令牌");
sb.AppendCode(3, $"try");
sb.AppendCode(3, $"{{");
sb.AppendCode(4, $"{ReturnType.FullName} {flowResult} = await {ApiMethodName}({flowContext}, cts.{nameof(CancellationTokenSource.Token)}, {invokeParamSignature}); // 调用目标方法");
sb.AppendCode(4, $"return {flowResult};");
sb.AppendCode(3, $"}}");
sb.AppendCode(3, $"catch (Exception)");
sb.AppendCode(3, $"{{");
sb.AppendCode(4, $"throw;");
sb.AppendCode(3, $"}}");
sb.AppendCode(3, $"finally");
sb.AppendCode(3, $"{{");
sb.AppendCode(4, $"{flowContext}.{nameof(IDynamicContext.Reset)}(); ");
sb.AppendCode(4, $"cts.{nameof(CancellationTokenSource.Dispose)}(); ");
sb.AppendCode(4, $"{flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Free)}({flowContext}); // 释放上下文");
sb.AppendCode(3, $"}}");
sb.AppendCode(2, $"}}");
return sb.ToString();
}
@@ -973,52 +1015,50 @@ namespace Serein.NodeFlow.Services
var invokeParamSignature = string.Join(", ", ParamInfos.Select(p => p.ParamName));
sb.AppendCode(2, $"public async {returnTypeContext} {ApiMethodName}({tokenFullName} {token}, {paramSignature})");
sb.AppendCode(2, $"{{");
sb.AppendCode(3, $"{contextApiFullName} {flowContext} = new {contextImpleFullName}({flowEnvironment}); // 创建上下文");
sb.AppendCode(3, $"{ReturnType.FullName} {flowResult} = await {ApiMethodName}({flowContext}, {token}, {invokeParamSignature}); // 调用目标方法");
sb.AppendCode(3, $"{flowContext}.{nameof(IDynamicContext.Reset)}(); ");
sb.AppendCode(3, $"return {flowResult};");
sb.AppendCode(3, $"{contextApiFullName} {flowContext} = {flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Allocate)}(); // 从对象池获取一个上下文");
sb.AppendCode(3, $"try");
sb.AppendCode(3, $"{{");
sb.AppendCode(4, $"{ReturnType.FullName} {flowResult} = await {ApiMethodName}({flowContext}, {token}, {invokeParamSignature}); // 调用目标方法");
sb.AppendCode(4, $"return {flowResult};");
sb.AppendCode(3, $"}}");
sb.AppendCode(3, $"catch (Exception)");
sb.AppendCode(3, $"{{");
sb.AppendCode(4, $"throw;");
sb.AppendCode(3, $"}}");
sb.AppendCode(3, $"finally");
sb.AppendCode(3, $"{{");
sb.AppendCode(4, $"{flowContext}.{nameof(IDynamicContext.Reset)}(); ");
sb.AppendCode(4, $"{flowContextPoolName}.{nameof(LightweightFlowControl.FlowContextPool)}.{nameof(LightweightFlowControl.FlowContextPool.Free)}({flowContext}); // 释放上下文");
sb.AppendCode(3, $"}}");
sb.AppendCode(2, $"}}");
return sb.ToString();
}
else if (type == ParamType.HasContextAndToken)
{
var paramSignature = string.Join(", ", ParamInfos.Select(p => $"global::{p.Type.FullName} {p.ParamName}"));
var invokeParamSignature = string.Join(", ", ParamInfos.Select(p => p.ParamName));
sb.AppendCode(2, $"public async {returnTypeContext} {ApiMethodName}({contextApiFullName} {flowContext}, {tokenFullName} token, {paramSignature})");
sb.AppendCode(2, $"{{");
sb.AppendCode(3, $"token.ThrowIfCancellationRequested(); // 检查任务是否取消");
// 生成参数类实例化代码
/*sb.AppendCode(3, $"global::{ParamTypeName} data = new global::{ParamTypeName}");
sb.AppendCode(3, $"{{");
sb.AppendCode(3, $"token.ThrowIfCancellationRequested(); // 检查任务是否取消");
sb.AppendCode(3, $"global::{ParamTypeName} data = {ObjPoolName}.Get(); // 从对象池获取一个对象");
for (int index = 0; index < ParamInfos.Count; index++)
{
ParamInfo? info = ParamInfos[index];
sb.AppendCode(4, $"{info.ParamName.ToPascalCase()} = {info.ParamName}; // [{index}] {info.Comments}");
sb.AppendCode(4, $"data.{info.ParamName.ToPascalCase()} = {info.ParamName}; // [{index}] {info.Comments}"); // 进行赋值
}
sb.AppendCode(3, $"}}");*/
sb.AppendCode(3, $"global::{ParamTypeName} data = {ObjPoolName}.Get(); // 从对象池获取一个对象");
for (int index = 0; index < ParamInfos.Count; index++)
{
ParamInfo? info = ParamInfos[index];
sb.AppendCode(4, $"data.{info.ParamName.ToPascalCase()} = {info.ParamName}; // [{index}] {info.Comments}");
}
sb.AppendCode(3, $"{flowContext}.{nameof(IDynamicContext.AddOrUpdate)}(\"{ApiMethodName}\", data);");
sb.AppendCode(3, $"{flowContext}.{nameof(IDynamicContext.SetPreviousNode)}(\"{NodeModel.Guid}\", \"{ApiMethodName}\");");
sb.AppendCode(3, $"global::{typeof(CallNode).FullName} node = Get(\"{NodeModel.Guid}\");");
sb.AppendCode(3, $"global::{typeof(FlowResult).FullName} {flowResult} = await node.{nameof(CallNode.StartFlowAsync)}({flowContext}, {token}); // 调用目标方法");
sb.AppendCode(3, $"if ({flowResult}.{nameof(FlowResult.Value)} is global::{ReturnType.FullName} result)");
sb.AppendCode(3, $"{{");
sb.AppendCode(4, $"return result;");
sb.AppendCode(3, $"}}");
sb.AppendCode(3, $"else");
sb.AppendCode(3, $"{{");
sb.AppendCode(4, $"throw new ArgumentNullException($\"{{(flowResult.Value is null ? \"返回数据为 null\" : $\"返回数据与需求类型不匹配,当前返回类型为[{{flowResult.Value.GetType().FullName}}。\")}}\");");
sb.AppendCode(3, $"}}");
sb.AppendCode(3, $"return {flowResult};");
sb.AppendCode(3, $"{flowContext}.{nameof(IDynamicContext.AddOrUpdate)}(\"{ApiMethodName}\", data);");
sb.AppendCode(3, $"{flowContext}.{nameof(IDynamicContext.SetPreviousNode)}(\"{NodeModel.Guid}\", \"{ApiMethodName}\");");
sb.AppendCode(3, $"global::{typeof(CallNode).FullName} node = Get(\"{NodeModel.Guid}\");");
sb.AppendCode(3, $"global::{typeof(FlowResult).FullName} {flowResult} = await node.{nameof(CallNode.StartFlowAsync)}({flowContext}, {token}); // 调用目标方法");
sb.AppendCode(3, $"if ({flowResult}.{nameof(FlowResult.Value)} is global::{ReturnType.FullName} result)");
sb.AppendCode(3, $"{{");
sb.AppendCode(4, $"return result;");
sb.AppendCode(3, $"}}");
sb.AppendCode(3, $"else");
sb.AppendCode(3, $"{{");
sb.AppendCode(4, $"throw new ArgumentNullException($\"{{(flowResult.Value is null ? \"返回数据为 null\" : $\"返回数据与需求类型不匹配,当前返回类型为[{{flowResult.Value.GetType().FullName}}。\")}}\");");
sb.AppendCode(3, $"}}");
sb.AppendCode(3, $"return {flowResult};");
sb.AppendCode(2, $"}}");
return sb.ToString();
// throw new ArgumentNullException($"类型转换失败,{(flowResult.Value is null ? "返回数据为 null" : $"返回数据与需求类型不匹配,当前返回类型为[{flowResult.Value.GetType().FullName}。")}");