From 41c3fa3d8424619404673c4b99a4c89d20cfc076 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Sat, 16 May 2026 05:38:50 -0400 Subject: [PATCH] fix(triggers): seed the trigger-expression attribute snapshot at actor startup --- src/ScadaLink.SiteRuntime/Actors/AlarmActor.cs | 10 ++++++++++ src/ScadaLink.SiteRuntime/Actors/InstanceActor.cs | 2 ++ src/ScadaLink.SiteRuntime/Actors/ScriptActor.cs | 10 ++++++++++ 3 files changed, 22 insertions(+) diff --git a/src/ScadaLink.SiteRuntime/Actors/AlarmActor.cs b/src/ScadaLink.SiteRuntime/Actors/AlarmActor.cs index aa3ad70..65588c7 100644 --- a/src/ScadaLink.SiteRuntime/Actors/AlarmActor.cs +++ b/src/ScadaLink.SiteRuntime/Actors/AlarmActor.cs @@ -72,6 +72,7 @@ public class AlarmActor : ReceiveActor SiteRuntimeOptions options, ILogger logger, Script? compiledTriggerExpression = null, + IReadOnlyDictionary? initialAttributes = null, ISiteHealthCollector? healthCollector = null) { _alarmName = alarmName; @@ -86,6 +87,15 @@ public class AlarmActor : ReceiveActor _onTriggerCompiledScript = onTriggerCompiledScript; _compiledTriggerExpression = compiledTriggerExpression; + // Seed the trigger-expression attribute snapshot from the instance's + // initial attribute set so static attributes (which never re-emit an + // AttributeValueChanged after deploy) evaluate correctly at startup. + if (initialAttributes != null) + { + foreach (var kvp in initialAttributes) + _attributeSnapshot[kvp.Key] = kvp.Value; + } + // Parse trigger type _triggerType = Enum.TryParse(alarmConfig.TriggerType, true, out var tt) ? tt : AlarmTriggerType.ValueMatch; diff --git a/src/ScadaLink.SiteRuntime/Actors/InstanceActor.cs b/src/ScadaLink.SiteRuntime/Actors/InstanceActor.cs index f3fb530..9f49b3e 100644 --- a/src/ScadaLink.SiteRuntime/Actors/InstanceActor.cs +++ b/src/ScadaLink.SiteRuntime/Actors/InstanceActor.cs @@ -529,6 +529,7 @@ public class InstanceActor : ReceiveActor _options, _logger, triggerExpression, + _attributes, _healthCollector, _serviceProvider)); @@ -578,6 +579,7 @@ public class InstanceActor : ReceiveActor _options, _logger, triggerExpression, + _attributes, _healthCollector)); var actorRef = Context.ActorOf(props, $"alarm-{alarm.CanonicalName}"); diff --git a/src/ScadaLink.SiteRuntime/Actors/ScriptActor.cs b/src/ScadaLink.SiteRuntime/Actors/ScriptActor.cs index 9435397..60c6a28 100644 --- a/src/ScadaLink.SiteRuntime/Actors/ScriptActor.cs +++ b/src/ScadaLink.SiteRuntime/Actors/ScriptActor.cs @@ -60,6 +60,7 @@ public class ScriptActor : ReceiveActor, IWithTimers SiteRuntimeOptions options, ILogger logger, Script? compiledTriggerExpression = null, + IReadOnlyDictionary? initialAttributes = null, ISiteHealthCollector? healthCollector = null, IServiceProvider? serviceProvider = null) { @@ -76,6 +77,15 @@ public class ScriptActor : ReceiveActor, IWithTimers _scope = scriptConfig.Scope; _compiledTriggerExpression = compiledTriggerExpression; + // Seed the trigger-expression attribute snapshot from the instance's + // initial attribute set so static attributes (which never re-emit an + // AttributeValueChanged after deploy) evaluate correctly at startup. + if (initialAttributes != null) + { + foreach (var kvp in initialAttributes) + _attributeSnapshot[kvp.Key] = kvp.Value; + } + // Parse trigger configuration _triggerConfig = ParseTriggerConfig(scriptConfig.TriggerType, scriptConfig.TriggerConfiguration);