chore(runtime): warn on missing VirtualTag evaluator; document Stale-recovery VirtualTag behaviour
Log a WARNING on startup when IVirtualTagEvaluator is not registered so a DI misconfig on a driver-role node is visible in logs instead of silently evaluating all VirtualTags to NoChange. Add a comment in PushDesiredSubscriptions noting that TryRecoverFromStale does not call this method, so VirtualTags remain empty after a Stale recovery until the next deployment dispatch (intentional, consistent with driver recovery).
This commit is contained in:
@@ -524,6 +524,11 @@ public sealed class DriverHostActor : ReceiveActor, IWithTimers
|
|||||||
// VirtualTagActor per plan and streams their evaluated values back onto the just-rebuilt
|
// VirtualTagActor per plan and streams their evaluated values back onto the just-rebuilt
|
||||||
// address space. Runs on BOTH the fresh-apply path (ApplyAndAck) and the bootstrap-restore
|
// address space. Runs on BOTH the fresh-apply path (ApplyAndAck) and the bootstrap-restore
|
||||||
// path (RestoreApplied) because both call this method, so one send covers both.
|
// path (RestoreApplied) because both call this method, so one send covers both.
|
||||||
|
// NOTE: the Stale-recovery path (TryRecoverFromStale) does NOT call PushDesiredSubscriptions,
|
||||||
|
// so — like drivers — VirtualTags remain empty after a Stale recovery until the next
|
||||||
|
// deployment dispatch. This is intentional and consistent with driver recovery: the Stale
|
||||||
|
// path only restores the revision marker + NodeDeploymentState; a subsequent dispatch
|
||||||
|
// (or a redeploy from AdminUI) triggers the full apply + subscribe pass.
|
||||||
_virtualTagHost?.Tell(new VirtualTagHostActor.ApplyVirtualTags(composition.EquipmentVirtualTags));
|
_virtualTagHost?.Tell(new VirtualTagHostActor.ApplyVirtualTags(composition.EquipmentVirtualTags));
|
||||||
if (composition.EquipmentVirtualTags.Count > 0)
|
if (composition.EquipmentVirtualTags.Count > 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -93,7 +93,13 @@ public static class ServiceCollectionExtensions
|
|||||||
// Production evaluator is the Host's RoslynVirtualTagEvaluator (registered as
|
// Production evaluator is the Host's RoslynVirtualTagEvaluator (registered as
|
||||||
// IVirtualTagEvaluator); fall back to the null evaluator for test harnesses that don't
|
// IVirtualTagEvaluator); fall back to the null evaluator for test harnesses that don't
|
||||||
// register one (VirtualTagActor children then evaluate to nothing).
|
// register one (VirtualTagActor children then evaluate to nothing).
|
||||||
var virtualTagEvaluator = resolver.GetService<IVirtualTagEvaluator>() ?? NullVirtualTagEvaluator.Instance;
|
var virtualTagEvaluator = resolver.GetService<IVirtualTagEvaluator>();
|
||||||
|
if (virtualTagEvaluator is null)
|
||||||
|
{
|
||||||
|
loggerFactory.CreateLogger("ZB.MOM.WW.OtOpcUa.Runtime.ServiceCollectionExtensions")
|
||||||
|
.LogWarning("IVirtualTagEvaluator not registered; Equipment VirtualTags will evaluate to NoChange (no live values). Expected only in test harnesses — driver-role nodes should register RoslynVirtualTagEvaluator.");
|
||||||
|
virtualTagEvaluator = NullVirtualTagEvaluator.Instance;
|
||||||
|
}
|
||||||
|
|
||||||
var dbHealth = system.ActorOf(
|
var dbHealth = system.ActorOf(
|
||||||
DbHealthProbeActor.Props(dbFactory),
|
DbHealthProbeActor.Props(dbFactory),
|
||||||
|
|||||||
Reference in New Issue
Block a user