Skip to content

Commit 5a0904d

Browse files
💾 Feat(Workflow): 添加工作流编译与持久化功能,支持跨会话重用
1 parent 207d6c3 commit 5a0904d

8 files changed

Lines changed: 447 additions & 19 deletions

File tree

KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockScriptExecutionGlobals.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Threading;
4-
using Kscript.CSharp.Parser.Core;
5-
using Kscript.CSharp.Parser.Models;
4+
using KitX.Core.Contract.Workflow;
65
using KitX.Core.Workflow;
76
using Serilog;
87

KitX Clients/KitX Core/KitX.Core/Workflow/BlockScripting/BlockScriptExecutor.cs

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,12 @@
55
using System.Reflection;
66
using System.Threading;
77
using System.Threading.Tasks;
8-
using Kscript.CSharp.Parser.Core;
8+
using KitX.Core.Contract.Workflow;
99
using Microsoft.CodeAnalysis;
1010
using Microsoft.CodeAnalysis.CSharp;
1111
using Microsoft.CodeAnalysis.CSharp.Syntax;
1212
using Microsoft.CodeAnalysis.CSharp.Scripting;
1313
using Microsoft.CodeAnalysis.Scripting;
14-
using KitX.Core.Contract.Workflow;
1514
using KitX.Core.Workflow;
1615
using Serilog;
1716

@@ -40,6 +39,9 @@ public class BlockScriptExecutor : IBlockScriptExecutor
4039
private BlockScriptExecutionGlobals? _globals;
4140
private IPluginManager? _pluginManager;
4241

42+
// Workflow ID for disk persistence of compiled assemblies
43+
private string? _workflowId;
44+
4345
// Block-level precompilation
4446
private readonly BlockCompiler _blockCompiler = new();
4547
private Dictionary<string, string>? _blockCodeCache;
@@ -80,6 +82,48 @@ public void SetPluginManager(IPluginManager? pluginManager)
8082
_pluginManager = pluginManager;
8183
}
8284

85+
/// <summary>
86+
/// Sets the workflow ID for disk persistence of compiled assemblies.
87+
/// When set, compiled assemblies are saved to and loaded from disk
88+
/// to enable cross-session reuse.
89+
/// </summary>
90+
public void SetWorkflowId(string? workflowId)
91+
{
92+
_workflowId = workflowId;
93+
}
94+
95+
/// <summary>
96+
/// Compiles a BlockScript and persists it to disk (without executing).
97+
/// Used for pre-compilation at workflow save time.
98+
/// </summary>
99+
/// <param name="script">The block script to compile.</param>
100+
/// <param name="workflowId">Workflow ID for disk persistence.</param>
101+
/// <returns>True if compilation and persistence succeeded.</returns>
102+
public bool CompileForPersistence(BlockScript script, string workflowId)
103+
{
104+
try
105+
{
106+
var compiled = _assemblyCompiler.CompileScript(script, workflowId);
107+
return compiled != null;
108+
}
109+
catch (Exception ex)
110+
{
111+
Log.Warning(ex, "[BlockScriptExecutor] CompileForPersistence failed for workflow {WfId}", workflowId);
112+
return false;
113+
}
114+
}
115+
116+
/// <summary>
117+
/// Preloads all persisted compiled scripts for a workflow from disk
118+
/// into the in-memory cache.
119+
/// </summary>
120+
/// <param name="workflowId">Workflow ID to preload scripts for.</param>
121+
/// <returns>Number of scripts successfully loaded.</returns>
122+
public int PreloadFromDisk(string workflowId)
123+
{
124+
return _assemblyCompiler.PreloadFromDisk(workflowId);
125+
}
126+
83127
/// <summary>
84128
/// Executes a block script
85129
/// </summary>
@@ -100,7 +144,7 @@ public async Task<BlockScriptExecutionResult> ExecuteAsync(
100144
// On failure, falls back to the existing CSharpScript execution path.
101145
try
102146
{
103-
var compiled = _assemblyCompiler.CompileScript(script);
147+
var compiled = _assemblyCompiler.CompileScript(script, _workflowId);
104148
if (compiled != null)
105149
{
106150
Log.Debug("[BlockScriptExecutor] Using assembly-compiled execution path");
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using System;
2+
3+
namespace KitX.Core.Workflow.BlockScripting;
4+
5+
/// <summary>
6+
/// Metadata for a persisted compiled script assembly on disk.
7+
/// Stored alongside the .dll as {hash}.meta.json.
8+
/// </summary>
9+
internal class CompiledScriptMeta
10+
{
11+
/// <summary>
12+
/// Script hash — must match the .dll filename and the in-memory cache key.
13+
/// </summary>
14+
public string ScriptHash { get; set; } = string.Empty;
15+
16+
/// <summary>
17+
/// UTC timestamp when the assembly was compiled.
18+
/// </summary>
19+
public DateTime CompileTimeUtc { get; set; } = DateTime.UtcNow;
20+
21+
/// <summary>
22+
/// KitX assembly version at compile time.
23+
/// Mismatch triggers re-compilation (API surface may have changed).
24+
/// </summary>
25+
public string KitXVersion { get; set; } = string.Empty;
26+
27+
/// <summary>
28+
/// Full type name of the compiled script class in the assembly,
29+
/// e.g. "KitX.Core.Workflow.BlockScripting.Generated.CompiledScript_1a2b3c4d".
30+
/// </summary>
31+
public string TypeName { get; set; } = string.Empty;
32+
}

0 commit comments

Comments
 (0)