using Microsoft.CodeAnalysis.Scripting;
using Microsoft.Extensions.Logging;
using ZB.MOM.WW.ScadaBridge.Commons.Types;
namespace ZB.MOM.WW.ScadaBridge.SiteRuntime.Scripts;
///
/// Shared Script Library — stores compiled shared script delegates in memory.
/// Shared scripts are compiled when received from central and executed inline
/// (direct method call, not actor message). NOT available on central.
/// Recompiled on update when new artifacts arrive.
///
public class SharedScriptLibrary
{
private readonly ScriptCompilationService _compilationService;
private readonly ILogger _logger;
private readonly Dictionary> _compiledScripts = new();
private readonly object _lock = new();
///
/// Initializes a new with the compilation service and logger.
///
/// Service used to compile Roslyn scripts.
/// Logger for compilation warnings and diagnostics.
public SharedScriptLibrary(
ScriptCompilationService compilationService,
ILogger logger)
{
_compilationService = compilationService;
_logger = logger;
}
///
/// Compiles and registers a shared script. Replaces any existing script with the same name.
/// Returns true if compilation succeeded, false otherwise.
///
/// Unique name for the shared script.
/// C# source code of the shared script.
/// true if compilation succeeded and the script was registered; false if compilation failed.
public bool CompileAndRegister(string name, string code)
{
var result = _compilationService.Compile(name, code);
if (!result.IsSuccess)
{
_logger.LogWarning(
"Shared script '{Name}' failed to compile: {Errors}",
name, string.Join("; ", result.Errors));
return false;
}
lock (_lock)
{
_compiledScripts[name] = result.CompiledScript!;
}
_logger.LogInformation("Shared script '{Name}' compiled and registered", name);
return true;
}
///
/// Removes a shared script from the library.
///
/// Name of the shared script to remove.
/// true if the script was found and removed; false if no script with that name was registered.
public bool Remove(string name)
{
lock (_lock)
{
return _compiledScripts.Remove(name);
}
}
///
/// Executes a shared script inline with the given runtime context.
/// This is a direct method call, not an actor message — executes on the calling thread.
///
/// Name of the shared script to execute.
/// Runtime context providing instance state and services to the script globals.
/// Optional input parameters passed to the script.
/// Cancellation token for the execution.
/// A task that resolves to the script's return value, or null if the script returns nothing.
public async Task