Claude-Session: https://claude.ai/code/session_01Ub9hGmYLQvn9XETzw7CMsT
This commit is contained in:
+56
-14
@@ -38,13 +38,16 @@ public static class CalculationDriverFactoryExtensions
|
||||
/// <param name="registry">The driver factory registry to register with.</param>
|
||||
/// <param name="loggerFactory">Optional logger factory for per-instance diagnostics loggers.</param>
|
||||
/// <param name="scriptRoot">Optional root script logger (fans failure entries onto the <c>script-logs</c> topic).</param>
|
||||
/// <param name="scripting">The node-wide <c>Scripting</c> options every Calculation driver inherits; a key
|
||||
/// authored in a driver's own config overrides that one knob. Null ⇒ the compiled defaults.</param>
|
||||
public static void Register(
|
||||
DriverFactoryRegistry registry,
|
||||
ILoggerFactory? loggerFactory = null,
|
||||
ScriptRootLogger? scriptRoot = null)
|
||||
ScriptRootLogger? scriptRoot = null,
|
||||
ScriptingOptions? scripting = null)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(registry);
|
||||
registry.Register(DriverTypeName, (id, json) => CreateInstance(id, json, loggerFactory, scriptRoot));
|
||||
registry.Register(DriverTypeName, (id, json) => CreateInstance(id, json, loggerFactory, scriptRoot, scripting));
|
||||
}
|
||||
|
||||
/// <summary>Public overload for the Server-side bootstrapper + test consumers.</summary>
|
||||
@@ -63,6 +66,18 @@ public static class CalculationDriverFactoryExtensions
|
||||
public static CalculationDriver CreateInstance(
|
||||
string driverInstanceId, string driverConfigJson,
|
||||
ILoggerFactory? loggerFactory, ScriptRootLogger? scriptRoot)
|
||||
=> CreateInstance(driverInstanceId, driverConfigJson, loggerFactory, scriptRoot, nodeScripting: null);
|
||||
|
||||
/// <summary>The full overload: also takes the node-wide <c>Scripting</c> options the driver inherits.</summary>
|
||||
/// <param name="driverInstanceId">The unique identifier for the driver instance.</param>
|
||||
/// <param name="driverConfigJson">The merged driver config JSON (carries the <c>RawTags</c> array).</param>
|
||||
/// <param name="loggerFactory">Optional logger factory for per-instance diagnostics loggers.</param>
|
||||
/// <param name="scriptRoot">Optional root script logger for failure fan-out.</param>
|
||||
/// <param name="nodeScripting">The node-wide run-guard options; null ⇒ the compiled defaults.</param>
|
||||
/// <returns>The constructed <see cref="CalculationDriver"/>.</returns>
|
||||
public static CalculationDriver CreateInstance(
|
||||
string driverInstanceId, string driverConfigJson,
|
||||
ILoggerFactory? loggerFactory, ScriptRootLogger? scriptRoot, ScriptingOptions? nodeScripting)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(driverInstanceId);
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(driverConfigJson);
|
||||
@@ -71,15 +86,14 @@ public static class CalculationDriverFactoryExtensions
|
||||
?? throw new InvalidOperationException(
|
||||
$"Calculation driver config for '{driverInstanceId}' deserialised to null");
|
||||
|
||||
// Run-guard knobs are optional and default to the node-wide ScriptingOptions defaults; only an
|
||||
// explicitly authored key overrides one (so a config carrying neither binds Scripting = null).
|
||||
ScriptingOptions? scripting = null;
|
||||
if (dto.MaxAllocBytesPerRun is not null || dto.QuarantineAfterConsecutiveTimeouts is not null)
|
||||
{
|
||||
scripting = new ScriptingOptions();
|
||||
if (dto.MaxAllocBytesPerRun is { } alloc) scripting.MaxAllocBytesPerRun = alloc;
|
||||
if (dto.QuarantineAfterConsecutiveTimeouts is { } n) scripting.QuarantineAfterConsecutiveTimeouts = n;
|
||||
}
|
||||
var scripting = ResolveScripting(
|
||||
dto.MaxAllocBytesPerRun, dto.QuarantineAfterConsecutiveTimeouts, nodeScripting, out var adjustments);
|
||||
var logger = loggerFactory?.CreateLogger<CalculationDriver>();
|
||||
// An authored value is never changed silently: the run guard would clamp it anyway, without a word.
|
||||
foreach (var adjustment in adjustments)
|
||||
logger?.LogWarning(
|
||||
"Calculation driver {DriverInstanceId}: its run-guard config was out of range and is clamped: {Adjustment}",
|
||||
driverInstanceId, adjustment);
|
||||
|
||||
var options = new CalculationDriverOptions
|
||||
{
|
||||
@@ -89,9 +103,37 @@ public static class CalculationDriverFactoryExtensions
|
||||
Scripting = scripting,
|
||||
};
|
||||
|
||||
return new CalculationDriver(
|
||||
options, driverInstanceId, scriptRoot,
|
||||
logger: loggerFactory?.CreateLogger<CalculationDriver>());
|
||||
return new CalculationDriver(options, driverInstanceId, scriptRoot, logger: logger);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The run-guard options for one Calculation driver. The node-wide options are the base. A key authored
|
||||
/// in the driver's config overrides only its own knob, on a copy, so the shared node object is never
|
||||
/// written. With neither, the result is null and the guard uses its compiled defaults.
|
||||
/// </summary>
|
||||
/// <param name="maxAllocBytesPerRun">The driver config's <c>maxAllocBytesPerRun</c>, or null.</param>
|
||||
/// <param name="quarantineAfterConsecutiveTimeouts">The driver config's <c>quarantineAfterConsecutiveTimeouts</c>, or null.</param>
|
||||
/// <param name="nodeScripting">The node-wide options, or null.</param>
|
||||
/// <param name="adjustments">The clamps applied to the driver's OWN keys (the node options were already
|
||||
/// clamped and logged at bind), for the caller to log. Empty when nothing was out of range.</param>
|
||||
/// <returns>The options to hand the driver, or null.</returns>
|
||||
internal static ScriptingOptions? ResolveScripting(
|
||||
long? maxAllocBytesPerRun, int? quarantineAfterConsecutiveTimeouts, ScriptingOptions? nodeScripting,
|
||||
out IReadOnlyList<string> adjustments)
|
||||
{
|
||||
adjustments = [];
|
||||
if (maxAllocBytesPerRun is null && quarantineAfterConsecutiveTimeouts is null) return nodeScripting;
|
||||
|
||||
var resolved = new ScriptingOptions();
|
||||
if (nodeScripting is not null)
|
||||
{
|
||||
resolved.MaxAllocBytesPerRun = nodeScripting.MaxAllocBytesPerRun;
|
||||
resolved.QuarantineAfterConsecutiveTimeouts = nodeScripting.QuarantineAfterConsecutiveTimeouts;
|
||||
resolved.StuckOrphanQuarantineFactor = nodeScripting.StuckOrphanQuarantineFactor;
|
||||
}
|
||||
if (maxAllocBytesPerRun is { } alloc) resolved.MaxAllocBytesPerRun = alloc;
|
||||
if (quarantineAfterConsecutiveTimeouts is { } n) resolved.QuarantineAfterConsecutiveTimeouts = n;
|
||||
return resolved.Sanitized(out adjustments);
|
||||
}
|
||||
|
||||
/// <summary>The merged-config DTO the calc factory binds from. The Calculation driver has no
|
||||
|
||||
Reference in New Issue
Block a user