namespace ZB.MOM.WW.OtOpcUa.Runtime.Drivers;
///
/// Pure diff between the currently-running driver children (keyed by
/// DriverInstance.DriverInstanceId) and the target spec list from a freshly-applied
/// deployment artifact. The DriverHostActor consumes the three lists and calls
/// spawn / ApplyDelta / stop on its child actors accordingly.
///
/// Specs with no current child — create a new actor.
/// Specs whose child exists but config JSON or type differs.
/// DriverInstanceIds currently running but missing from the new artifact, or now disabled.
public sealed record DriverSpawnPlan(
IReadOnlyList ToSpawn,
IReadOnlyList ToApplyDelta,
IReadOnlyList ToStop);
public static class DriverSpawnPlanner
{
///
/// Compute the spawn/delta/stop sets. Disabled entries in are
/// treated as "not desired here": if a child exists for the id it goes into ToStop,
/// otherwise the row is dropped entirely (no spawn for a disabled driver).
///
/// The currently running driver children keyed by ID.
/// The target driver instances from the deployment artifact.
public static DriverSpawnPlan Compute(
IReadOnlyDictionary current,
IReadOnlyList target)
{
var toSpawn = new List();
var toDelta = new List();
var toStop = new List();
var targetById = new Dictionary(StringComparer.Ordinal);
foreach (var spec in target) targetById[spec.DriverInstanceId] = spec;
foreach (var (id, snap) in current)
{
if (!targetById.TryGetValue(id, out var spec) || !spec.Enabled)
{
toStop.Add(id);
continue;
}
// Driver type changes can't be reinitialized in-place (factory-bound) — stop + respawn.
if (!string.Equals(snap.DriverType, spec.DriverType, StringComparison.Ordinal))
{
toStop.Add(id);
toSpawn.Add(spec);
continue;
}
if (!string.Equals(snap.LastConfigJson, spec.DriverConfig, StringComparison.Ordinal))
{
toDelta.Add(spec);
}
}
foreach (var (id, spec) in targetById)
{
if (!spec.Enabled) continue;
if (current.ContainsKey(id)) continue;
toSpawn.Add(spec);
}
return new DriverSpawnPlan(toSpawn, toDelta, toStop);
}
}
/// Snapshot of one running driver child as the host sees it. Used as the diff input.
public sealed record DriverChildSnapshot(string DriverType, string LastConfigJson);