fix(deploy): address M2.1 review nits — comparer consistency + comments (#22)
- connection-name capable-set comparer kept as StringComparer.Ordinal: FlatteningService and SemanticValidator use all-ordinal name-keyed dictionaries throughout; OrdinalIgnoreCase would be inconsistent with the rest of the binding-resolution path — added comment documenting this - IsAlarmCapable protocol-match confirmed consistent with DataConnectionFactory (both OrdinalIgnoreCase); added case-insensitive InlineData variants (OPCUA, opcua, mxgateway, MXGATEWAY) to lock the contract - clarified FlatteningPipeline comment: "filters connections by alarm-capable protocol, then collects their names" (was "maps from the protocol string") - added DataConnectionLayer/DataConnectionFactory.cs path reference to AlarmCapableProtocols sync-risk comment
This commit is contained in:
@@ -6,8 +6,9 @@ namespace ZB.MOM.WW.ScadaBridge.Commons.Interfaces.Protocol;
|
|||||||
/// mirror native alarms).
|
/// mirror native alarms).
|
||||||
///
|
///
|
||||||
/// The set MUST stay in sync with the protocols registered against an
|
/// The set MUST stay in sync with the protocols registered against an
|
||||||
/// alarm-subscribable adapter in the DCL <c>DataConnectionFactory</c>: today the
|
/// alarm-subscribable adapter in
|
||||||
/// "OpcUa" adapter (<c>OpcUaDataConnection</c>) and the "MxGateway" adapter
|
/// <c>DataConnectionLayer/DataConnectionFactory.cs</c>: today the "OpcUa" adapter
|
||||||
|
/// (<c>OpcUaDataConnection</c>) and the "MxGateway" adapter
|
||||||
/// (<c>MxGatewayDataConnection</c>) both implement
|
/// (<c>MxGatewayDataConnection</c>) both implement
|
||||||
/// <see cref="IAlarmSubscribableConnection"/>. The runtime decision is made in
|
/// <see cref="IAlarmSubscribableConnection"/>. The runtime decision is made in
|
||||||
/// <c>DataConnectionActor</c> via <c>_adapter is IAlarmSubscribableConnection</c>;
|
/// <c>DataConnectionActor</c> via <c>_adapter is IAlarmSubscribableConnection</c>;
|
||||||
@@ -21,7 +22,9 @@ public static class AlarmCapableProtocols
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether a data connection's protocol string resolves to an
|
/// Determines whether a data connection's protocol string resolves to an
|
||||||
/// alarm-capable adapter (one implementing <see cref="IAlarmSubscribableConnection"/>).
|
/// alarm-capable adapter (one implementing <see cref="IAlarmSubscribableConnection"/>).
|
||||||
/// Case-insensitive; <c>null</c>/blank is not alarm-capable.
|
/// Case-insensitive to match <c>DataConnectionFactory</c>'s own
|
||||||
|
/// <c>OrdinalIgnoreCase</c> protocol-key lookup; <c>null</c>/blank is not
|
||||||
|
/// alarm-capable.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="protocol">The data connection protocol string (e.g. "OpcUa").</param>
|
/// <param name="protocol">The data connection protocol string (e.g. "OpcUa").</param>
|
||||||
/// <returns><c>true</c> when the protocol's adapter can subscribe native alarms; otherwise <c>false</c>.</returns>
|
/// <returns><c>true</c> when the protocol's adapter can subscribe native alarms; otherwise <c>false</c>.</returns>
|
||||||
|
|||||||
@@ -114,8 +114,14 @@ public class FlatteningPipeline : IFlatteningPipeline
|
|||||||
|
|
||||||
// Compute the alarm-capable connection-name set so the semantic validator
|
// Compute the alarm-capable connection-name set so the semantic validator
|
||||||
// can gate native-alarm-source bindings. "Alarm-capable" matches the DCL
|
// can gate native-alarm-source bindings. "Alarm-capable" matches the DCL
|
||||||
// runtime decision (DataConnectionActor: _adapter is IAlarmSubscribableConnection),
|
// runtime decision (DataConnectionActor: _adapter is IAlarmSubscribableConnection);
|
||||||
// mapped from the protocol string via the shared AlarmCapableProtocols helper.
|
// here we filter connections by alarm-capable protocol, then collect their names.
|
||||||
|
//
|
||||||
|
// StringComparer.Ordinal is intentional: connection names are stored and
|
||||||
|
// matched as authored throughout the pipeline (all other name-keyed
|
||||||
|
// dictionaries in FlatteningService and SemanticValidator use the same
|
||||||
|
// case-sensitive semantics). OrdinalIgnoreCase would be inconsistent with
|
||||||
|
// the rest of the binding-resolution path.
|
||||||
var alarmCapableConnectionNames = dataConnections.Values
|
var alarmCapableConnectionNames = dataConnections.Values
|
||||||
.Where(c => AlarmCapableProtocols.IsAlarmCapable(c.Protocol))
|
.Where(c => AlarmCapableProtocols.IsAlarmCapable(c.Protocol))
|
||||||
.Select(c => c.Name)
|
.Select(c => c.Name)
|
||||||
|
|||||||
+6
@@ -83,6 +83,12 @@ public class FlatteningPipelineNativeAlarmCapabilityTests
|
|||||||
[Theory]
|
[Theory]
|
||||||
[InlineData("OpcUa")]
|
[InlineData("OpcUa")]
|
||||||
[InlineData("MxGateway")]
|
[InlineData("MxGateway")]
|
||||||
|
// Case variants: IsAlarmCapable uses OrdinalIgnoreCase, matching DataConnectionFactory's
|
||||||
|
// own OrdinalIgnoreCase protocol-key lookup; lock the contract with non-canonical casing.
|
||||||
|
[InlineData("OPCUA")]
|
||||||
|
[InlineData("opcua")]
|
||||||
|
[InlineData("mxgateway")]
|
||||||
|
[InlineData("MXGATEWAY")]
|
||||||
public async Task FlattenAndValidate_NativeAlarmSourceOnAlarmCapableConnection_NoCapabilityError(string protocol)
|
public async Task FlattenAndValidate_NativeAlarmSourceOnAlarmCapableConnection_NoCapabilityError(string protocol)
|
||||||
{
|
{
|
||||||
Arrange(connectionName: "Boiler", connectionProtocol: protocol, boundConnectionName: "Boiler");
|
Arrange(connectionName: "Boiler", connectionProtocol: protocol, boundConnectionName: "Boiler");
|
||||||
|
|||||||
Reference in New Issue
Block a user