refactor: rename ScadaLink → ZB.MOM.WW.ScadaBridge (code + projects + namespaces)
Solution + 23 src projects + 26 test projects renamed; folders, csproj, namespaces, and ScadaLinkDbContext/ScadaBridgeDbContext class updated. ActorSystem "scadalink" → "scadabridge", Akka seed-node URLs migrated. SQL roles/logins, LDAP domains, CLI command name, and CLI config dir (~/.scadalink → ~/.scadabridge) also renamed. Build green; 5 Host.Tests fail awaiting SQL login rename in next commit. Pre-existing StaleTagMonitor timing flakes unchanged. Rename script committed at tools/rename-to-scadabridge.sh.
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
using Microsoft.CodeAnalysis.Scripting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using ZB.MOM.WW.ScadaBridge.Commons.Types;
|
||||
|
||||
namespace ZB.MOM.WW.ScadaBridge.SiteRuntime.Scripts;
|
||||
|
||||
/// <summary>
|
||||
/// WP-17: 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.
|
||||
/// WP-33: Recompiled on update when new artifacts arrive.
|
||||
/// </summary>
|
||||
public class SharedScriptLibrary
|
||||
{
|
||||
private readonly ScriptCompilationService _compilationService;
|
||||
private readonly ILogger<SharedScriptLibrary> _logger;
|
||||
private readonly Dictionary<string, Script<object?>> _compiledScripts = new();
|
||||
private readonly object _lock = new();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new <see cref="SharedScriptLibrary"/> with the compilation service and logger.
|
||||
/// </summary>
|
||||
/// <param name="compilationService">Service used to compile Roslyn scripts.</param>
|
||||
/// <param name="logger">Logger for compilation warnings and diagnostics.</param>
|
||||
public SharedScriptLibrary(
|
||||
ScriptCompilationService compilationService,
|
||||
ILogger<SharedScriptLibrary> logger)
|
||||
{
|
||||
_compilationService = compilationService;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compiles and registers a shared script. Replaces any existing script with the same name.
|
||||
/// Returns true if compilation succeeded, false otherwise.
|
||||
/// </summary>
|
||||
/// <param name="name">Unique name for the shared script.</param>
|
||||
/// <param name="code">C# source code of the shared script.</param>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a shared script from the library.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the shared script to remove.</param>
|
||||
public bool Remove(string name)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _compiledScripts.Remove(name);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="scriptName">Name of the shared script to execute.</param>
|
||||
/// <param name="context">Runtime context providing instance state and services to the script globals.</param>
|
||||
/// <param name="parameters">Optional input parameters passed to the script.</param>
|
||||
/// <param name="cancellationToken">Cancellation token for the execution.</param>
|
||||
public async Task<object?> ExecuteAsync(
|
||||
string scriptName,
|
||||
ScriptRuntimeContext context,
|
||||
IReadOnlyDictionary<string, object?>? parameters = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
Script<object?> script;
|
||||
lock (_lock)
|
||||
{
|
||||
if (!_compiledScripts.TryGetValue(scriptName, out script!))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"Shared script '{scriptName}' not found in library.");
|
||||
}
|
||||
}
|
||||
|
||||
var globals = new ScriptGlobals
|
||||
{
|
||||
Instance = context,
|
||||
Parameters = new ScriptParameters(parameters ?? new Dictionary<string, object?>()),
|
||||
CancellationToken = cancellationToken
|
||||
};
|
||||
|
||||
var state = await script.RunAsync(globals, cancellationToken);
|
||||
return state.ReturnValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the names of all currently registered shared scripts.
|
||||
/// </summary>
|
||||
public IReadOnlyList<string> GetRegisteredScriptNames()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _compiledScripts.Keys.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether a script with the given name is registered.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the shared script to look up.</param>
|
||||
public bool Contains(string name)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _compiledScripts.ContainsKey(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user