From 067924918598f75fd674657ce55ab3bc1d848e6d Mon Sep 17 00:00:00 2001 From: Einar Date: Tue, 17 Sep 2024 08:15:07 +0200 Subject: [PATCH] Configure and run dotnet format on everything (#704) * Configure and run dotnet format on everything * Review comments * Verify no changes * Less stupid dictionary init --- .editorconfig | 23 +++- .github/workflows/common.yml | 3 + ConfigurationTool/UAServerExplorer.cs | 2 +- Extractor/Browse/BrowseParams.cs | 2 +- Extractor/Browse/BrowseScheduler.cs | 2 +- Extractor/Browse/Browser.cs | 3 +- Extractor/Config/ConfigToggles.cs | 2 +- Extractor/Config/EventConfig.cs | 6 +- Extractor/Config/ExtractionConfig.cs | 7 +- Extractor/Config/FullConfig.cs | 22 ++-- Extractor/Config/SourceConfig.cs | 4 +- Extractor/Deletes.cs | 6 +- Extractor/ExtractorUtils.cs | 2 +- Extractor/History/HistoryReader.cs | 7 +- Extractor/History/HistoryScheduler.cs | 91 ++++++--------- Extractor/History/SmartAggregateException.cs | 2 +- Extractor/Looper.cs | 2 +- .../NodeSources/CDFNodeSourceWithFallback.cs | 3 - Extractor/NodeSources/INodeSource.cs | 2 +- Extractor/NodeSources/NodeHierarchyBuilder.cs | 9 +- Extractor/NodeSources/NodeSetNodeSource.cs | 10 +- Extractor/NodeTransformation.cs | 25 ++--- Extractor/Nodes/UAObject.cs | 5 +- Extractor/Nodes/UAVariable.cs | 19 +--- Extractor/Nodes/UAVariableType.cs | 8 +- Extractor/PubSub/ServerPubSubConfigurator.cs | 2 +- Extractor/Pushers/CDFPusher.cs | 6 - .../Pushers/FDM/BaseDataModelDefinitions.cs | 2 +- Extractor/Pushers/FDM/DMSValueConverter.cs | 33 ++---- Extractor/Pushers/FDM/FDMUtils.cs | 7 +- Extractor/Pushers/FDM/FDMWriter.cs | 14 +-- Extractor/Pushers/FDM/InstanceBuilder.cs | 6 +- Extractor/Pushers/FDM/NodeHierarchy.cs | 2 - Extractor/Pushers/FDM/NodeIdContext.cs | 9 +- Extractor/Pushers/FDM/NodeTypeCollector.cs | 1 - Extractor/Pushers/FDM/SimpleTypeCollector.cs | 2 + Extractor/Pushers/FDM/TypeHierarchyBuilder.cs | 6 +- Extractor/Pushers/FDM/TypeMetadata.cs | 5 +- Extractor/Pushers/FDM/Types/NodeTypes.cs | 10 +- Extractor/Pushers/FDM/Types/ReferenceTypes.cs | 2 +- Extractor/Pushers/InfluxPusher.cs | 6 +- Extractor/Pushers/MqttPusher.cs | 9 +- Extractor/Pushers/PusherUtils.cs | 2 +- Extractor/Pushers/Writers/CDFWriter.cs | 15 ++- Extractor/Pushers/Writers/CleanWriter.cs | 2 +- Extractor/Pushers/Writers/IdmWriter.cs | 6 +- .../Writers/MinimalTimeseriesWriter.cs | 6 +- Extractor/RebrowseTriggerManager.cs | 2 +- Extractor/SessionManager.cs | 13 +-- Extractor/SourceInformation.cs | 5 +- Extractor/Streamer.cs | 7 +- .../BaseCreateSubscriptionTask.cs | 8 +- .../NodeMetricsSubscriptionTask.cs | 3 - .../RebrowseTriggerSubscriptionTask.cs | 2 +- .../Subscriptions/RecreateSubscriptionTask.cs | 5 +- .../ServiceLevelSubscriptionTask.cs | 4 +- .../Subscriptions/SubscriptionManager.cs | 3 +- Extractor/TypeCollectors/TypeManager.cs | 5 +- Extractor/Types/DummyMessageContext.cs | 6 +- Extractor/Types/UADataPoint.cs | 2 - Extractor/Types/UAEvent.cs | 18 +-- Extractor/Types/UAPropertySerializer.cs | 6 +- Extractor/UAClient.cs | 13 +-- Extractor/UAExtractor.cs | 25 ++--- ExtractorLauncher/ExtractorStarter.cs | 27 ++--- ExtractorLauncher/Worker.cs | 3 +- MQTTCDFBridge/Config.cs | 6 +- MQTTCDFBridge/Destination.cs | 15 +-- MQTTCDFBridge/Program.cs | 5 +- Server/DebugMasterNodeManager.cs | 12 +- Server/ErrorCallbacks.cs | 2 +- Server/IServerRequestCallbacks.cs | 4 +- Server/NodeManager.cs | 10 +- Server/Program.cs | 1 - Server/PubSubManager.cs | 2 +- Server/ServerController.cs | 4 +- Test/AssemblyInfo.cs | 2 +- Test/CDFMockHandler.cs | 11 +- Test/CommonTestUtils.cs | 4 +- Test/Integration/LauncherTests.cs | 15 ++- Test/Integration/NodeExtractionTests.cs | 3 - .../RebrowseTriggerManagerTests.cs | 2 +- Test/Unit/CDFPusherTest.cs | 20 ++-- Test/Unit/FDMTests.cs | 4 +- Test/Unit/HistoryReaderTest.cs | 105 ++++++++++++------ Test/Unit/TransformationTest.cs | 6 +- Test/Unit/TypeManagerTest.cs | 6 +- Test/Unit/UAClientTest.cs | 6 +- Test/Unit/UAExtractorTest.cs | 2 +- Test/Utils/BaseExtractorTestFixture.cs | 5 +- Test/Utils/EventUtils.cs | 6 +- 91 files changed, 374 insertions(+), 461 deletions(-) diff --git a/.editorconfig b/.editorconfig index c666e0540..1f5d257fe 100644 --- a/.editorconfig +++ b/.editorconfig @@ -48,4 +48,25 @@ dotnet_diagnostic.IDE0090.severity = none dotnet_diagnostic.CA1851.severity = none # CA1861: Prefer static readonly fields over constant array arguments. Not really that important where this pops up, and there are tons of false positives. -dotnet_diagnostic.CA1861.severity = none \ No newline at end of file +dotnet_diagnostic.CA1861.severity = none + +# IDE0057: Use range operator. +dotnet_diagnostic.IDE0057.severity = none +# IDE0300: Use collection expression [1, 2, 3] +dotnet_diagnostic.IDE0300.severity = none +# IDE0290: Use primary constructor, this syntax is insane +dotnet_diagnostic.IDE0290.severity = none + +# IDE1006: Naming style +dotnet_diagnostic.IDE1006.severity = warning + +dotnet_diagnostic.IDE0052.severity = warning +dotnet_diagnostic.xUnit1045.severity = warning +dotnet_diagnostic.IDE0060.severity = warning + +indent_size = 4 +indent_style = space +tab_width = 4 + +insert_final_newline = true + diff --git a/.github/workflows/common.yml b/.github/workflows/common.yml index 696d63f05..c1019b9bf 100644 --- a/.github/workflows/common.yml +++ b/.github/workflows/common.yml @@ -174,6 +174,9 @@ jobs: - name: Build run: dotnet build ExtractorLauncher/ + - name: Lint + run: dotnet format --verify-no-changes + - name: Install release dependencies run: sudo apt-get install -y rpm build-essential sed - name: Build release binary diff --git a/ConfigurationTool/UAServerExplorer.cs b/ConfigurationTool/UAServerExplorer.cs index 221a8112b..7fd890fdd 100644 --- a/ConfigurationTool/UAServerExplorer.cs +++ b/ConfigurationTool/UAServerExplorer.cs @@ -280,7 +280,7 @@ public void OnCreatedSubscription(SubscriptionName subscription) public FullConfig FinalConfig => baseConfig; - private PeriodicScheduler scheduler = null!; + private readonly PeriodicScheduler scheduler = null!; public PeriodicScheduler TaskScheduler => scheduler; } } diff --git a/Extractor/Browse/BrowseParams.cs b/Extractor/Browse/BrowseParams.cs index 0e7596939..299831a43 100644 --- a/Extractor/Browse/BrowseParams.cs +++ b/Extractor/Browse/BrowseParams.cs @@ -93,7 +93,7 @@ public BrowseNode(NodeId id, BrowseNode parent) public BrowseResult? Result { get; private set; } public void AddReferences(ReferenceDescriptionCollection references) { - if (references == null) references = new ReferenceDescriptionCollection(); + references ??= new ReferenceDescriptionCollection(); if (Result == null) { Result = new BrowseResult(this, references); diff --git a/Extractor/Browse/BrowseScheduler.cs b/Extractor/Browse/BrowseScheduler.cs index 54b134c4a..a0733f17f 100644 --- a/Extractor/Browse/BrowseScheduler.cs +++ b/Extractor/Browse/BrowseScheduler.cs @@ -81,7 +81,7 @@ public BrowseScheduler( callback = options.Callback; if (options == null) throw new ArgumentNullException(nameof(options)); - if (options.InitialParams?.Nodes == null) throw new ArgumentException("options.InitialParams.Nodes is required"); + if (options.InitialParams?.Nodes == null) throw new InvalidOperationException("options.InitialParams.Nodes is required"); baseParams = options.InitialParams; diff --git a/Extractor/Browse/Browser.cs b/Extractor/Browse/Browser.cs index 5f545431e..e7e1e7e5a 100644 --- a/Extractor/Browse/Browser.cs +++ b/Extractor/Browse/Browser.cs @@ -32,7 +32,6 @@ public sealed class Browser : IDisposable private readonly ILogger log; private readonly UAClient uaClient; private readonly FullConfig config; - private readonly object visitedNodesLock = new object(); private readonly ContinuationPointThrottlingConfig throttling; private readonly TaskThrottler throttler; @@ -190,7 +189,7 @@ await uaClient.GetReferences(new BrowseParams return roots.Values; } - public async Task GetRootNodes(IEnumerable ids, Action callback, CancellationToken token, string purpose = "") + public async Task GetRootNodes(IEnumerable ids, Action callback, CancellationToken token) { var refs = await GetRootNodes(ids, token); foreach (var rf in refs) diff --git a/Extractor/Config/ConfigToggles.cs b/Extractor/Config/ConfigToggles.cs index aedcd3240..bde8ff230 100644 --- a/Extractor/Config/ConfigToggles.cs +++ b/Extractor/Config/ConfigToggles.cs @@ -57,4 +57,4 @@ public ConfigToggles(FullConfig config) /// public bool LoadTypeReferences => FdmEnabled; } -} \ No newline at end of file +} diff --git a/Extractor/Config/EventConfig.cs b/Extractor/Config/EventConfig.cs index 194078d73..295ed4441 100644 --- a/Extractor/Config/EventConfig.cs +++ b/Extractor/Config/EventConfig.cs @@ -97,7 +97,7 @@ public IEnumerable BaseExcludeProperties public Dictionary DestinationNameMap { get => destinationNameMap; set => destinationNameMap = value ?? destinationNameMap; } private Dictionary destinationNameMap = new Dictionary(); - public HashSet? GetWhitelist(SessionContext context, ILogger logger) + public HashSet? GetWhitelist(SessionContext context) { if (EventIds == null || !EventIds.Any()) return null; var whitelist = new HashSet(); @@ -114,7 +114,7 @@ public IEnumerable BaseExcludeProperties return whitelist; } - public HashSet GetEmitterIds(SessionContext context, ILogger logger) + public HashSet GetEmitterIds(SessionContext context) { if (EmitterIds == null || !EmitterIds.Any()) return new HashSet(); var ids = new HashSet(); @@ -131,7 +131,7 @@ public HashSet GetEmitterIds(SessionContext context, ILogger logger) return ids; } - public HashSet GetHistorizingEmitterIds(SessionContext context, ILogger logger) + public HashSet GetHistorizingEmitterIds(SessionContext context) { if (HistorizingEmitterIds == null || !HistorizingEmitterIds.Any()) return new HashSet(); var ids = new HashSet(); diff --git a/Extractor/Config/ExtractionConfig.cs b/Extractor/Config/ExtractionConfig.cs index d55ba5c9d..428fc10c3 100644 --- a/Extractor/Config/ExtractionConfig.cs +++ b/Extractor/Config/ExtractionConfig.cs @@ -15,13 +15,10 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -using Cognite.Extensions.DataModels.QueryBuilder; using Cognite.Extractor.Common; using Cognite.OpcUa.Nodes; using Cognite.OpcUa.NodeSources; -using Microsoft.Extensions.Logging; using Opc.Ua; -using Serilog.Debugging; using System; using System.Collections.Generic; using System.IO; @@ -373,7 +370,7 @@ public class RebrowseTriggersConfig public class RebrowseTriggerTargets { - private List ToBeSubscribed = new List(); + private readonly List ToBeSubscribed = new List(); public bool NamespacePublicationDate { @@ -453,7 +450,7 @@ public override string ToString() first = false; builder.AppendFormat("\"{0}\"", entry); } - builder.Append("]"); + builder.Append(']'); return base.ToString(); } } diff --git a/Extractor/Config/FullConfig.cs b/Extractor/Config/FullConfig.cs index 3a8e4a7bf..1b116fb27 100644 --- a/Extractor/Config/FullConfig.cs +++ b/Extractor/Config/FullConfig.cs @@ -113,9 +113,9 @@ public FullConfig() : base() public bool DryRun { get; set; } public override void GenerateDefaults() { - if (Source == null) Source = new SourceConfig(); - if (Logger == null) Logger = new UALoggerConfig(); - if (Metrics == null) Metrics = new UAMetricsConfig(); + Source ??= new SourceConfig(); + Logger ??= new UALoggerConfig(); + Metrics ??= new UAMetricsConfig(); if (Cognite != null) { if (Cognite.CdfChunking == null) Cognite.CdfChunking = new ChunkingConfig(); @@ -123,14 +123,14 @@ public override void GenerateDefaults() if (Cognite.CdfRetries == null) Cognite.CdfRetries = new RetryConfig(); if (Cognite.SdkLogging == null) Cognite.SdkLogging = new SdkLoggingConfig(); } - if (Extraction == null) Extraction = new ExtractionConfig(); - if (Events == null) Events = new EventConfig(); - if (FailureBuffer == null) FailureBuffer = new FailureBufferConfig(); - if (History == null) History = new HistoryConfig(); - if (StateStorage == null) StateStorage = new StateStorageConfig(); - if (Subscriptions == null) Subscriptions = new SubscriptionConfig(); - if (PubSub == null) PubSub = new PubSubConfig(); - if (HighAvailability == null) HighAvailability = new HighAvailabilityConfig(); + Extraction ??= new ExtractionConfig(); + Events ??= new EventConfig(); + FailureBuffer ??= new FailureBufferConfig(); + History ??= new HistoryConfig(); + StateStorage ??= new StateStorageConfig(); + Subscriptions ??= new SubscriptionConfig(); + PubSub ??= new PubSubConfig(); + HighAvailability ??= new HighAvailabilityConfig(); } } public class UAMetricsConfig : MetricsConfig diff --git a/Extractor/Config/SourceConfig.cs b/Extractor/Config/SourceConfig.cs index 4e2b84f3f..ad4bcfc52 100644 --- a/Extractor/Config/SourceConfig.cs +++ b/Extractor/Config/SourceConfig.cs @@ -318,14 +318,14 @@ public HashSet FinalRetryStatusCodes } } - private static HashSet retryExceptions = new HashSet + private static readonly HashSet retryExceptions = new HashSet { typeof(ArgumentNullException), typeof(NullReferenceException), typeof(InvalidOperationException) }; - public bool ShouldRetryException(Exception ex, IEnumerable statusCodes) + public static bool ShouldRetryException(Exception ex, IEnumerable statusCodes) { if (ex is ServiceResultException serviceExc) { diff --git a/Extractor/Deletes.cs b/Extractor/Deletes.cs index affea22a0..e1c54026f 100644 --- a/Extractor/Deletes.cs +++ b/Extractor/Deletes.cs @@ -119,7 +119,7 @@ private async Task> GetDeletedItems(string? tableNa } var newStates = states.Values.Where(s => !oldStates.ContainsKey(s.Id)).ToList(); - if (newStates.Any()) + if (newStates.Count != 0) { logger.LogInformation("Found {New} new nodes in {Tab}, adding to state store...", newStates.Count, tableName); if (!config.DryRun) await stateStore.StoreExtractionState(newStates, tableName, @@ -136,10 +136,10 @@ public async Task GetDiffAndStoreIds(NodeSourceResult result, Sess var time = DateTime.UtcNow.AddSeconds(-1); var newVariables = result.DestinationVariables.Select(v => (v.Id, v.GetUniqueId(context)!)).ToDictionary( i => i.Item2, - i => new NodeExistsState(i.Item2, i.Item1, context, time)); + i => new NodeExistsState(i.Item2, i.Id, context, time)); var newObjects = result.DestinationObjects.Select(o => (o.Id, o.GetUniqueId(context)!)).ToDictionary( i => i.Item2, - i => new NodeExistsState(i.Item2, i.Item1, context, time)); + i => new NodeExistsState(i.Item2, i.Id, context, time)); var newReferences = result.DestinationReferences.Select(r => client.GetRelationshipId(r)!).ToDictionary( i => i, i => new NodeExistsState(i, null, null, time)); diff --git a/Extractor/ExtractorUtils.cs b/Extractor/ExtractorUtils.cs index 4801eb38e..0d73f9066 100644 --- a/Extractor/ExtractorUtils.cs +++ b/Extractor/ExtractorUtils.cs @@ -125,7 +125,7 @@ public enum SourceOp public static void LogException(ILogger log, Exception? e, string message, string? silentMessage = null) { - if (silentMessage == null) silentMessage = message; + silentMessage ??= message; if (e == null) { log.LogError("Unknown error: {Message}", message); diff --git a/Extractor/History/HistoryReader.cs b/Extractor/History/HistoryReader.cs index 018549038..0692fe376 100644 --- a/Extractor/History/HistoryReader.cs +++ b/Extractor/History/HistoryReader.cs @@ -18,17 +18,12 @@ You should have received a copy of the GNU General Public License using Cognite.Extractor.Common; using Cognite.OpcUa.Config; using Cognite.OpcUa.TypeCollectors; -using Google.Protobuf.WellKnownTypes; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.ObjectPool; using Opc.Ua; using System; using System.Collections.Generic; -using System.CommandLine.Parsing; using System.Linq; using System.Runtime.ExceptionServices; -using System.Text; -using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -209,7 +204,7 @@ private async Task RunAllHistory() class State { - private HashSet issues = new(); + private readonly HashSet issues = new(); public bool AddIssue(StateIssue issue) { diff --git a/Extractor/History/HistoryScheduler.cs b/Extractor/History/HistoryScheduler.cs index b61c11888..1530754e9 100644 --- a/Extractor/History/HistoryScheduler.cs +++ b/Extractor/History/HistoryScheduler.cs @@ -175,9 +175,8 @@ private DateTime DefaultEndTime() private static DateTime GetStartTime(string? start) { if (string.IsNullOrWhiteSpace(start)) return CogniteTime.DateTimeEpoch; - var parsed = CogniteTime.ParseTimestampString(start); - if (parsed == null) throw new ArgumentException($"Invalid history start time: {start}"); - return parsed!.Value; + var parsed = CogniteTime.ParseTimestampString(start) ?? throw new ArgumentException($"Invalid history start time: {start}"); + return parsed; } private static IEnumerable GetNodes( @@ -254,53 +253,43 @@ private static DateTime Max(DateTime t1, DateTime t2) private (HistoryReadDetails, DateTime, DateTime) GetReadDetails(IEnumerable nodes) { - HistoryReadDetails details; var (min, max) = GetReadRange(nodes); log.LogDebug("Read {Type} history chunk for {Count} nodes from {Min} to {Max}", type, nodes.Count(), min, max); - switch (type) + HistoryReadDetails details = type switch { - case HistoryReadType.FrontfillData: - details = new ReadRawModifiedDetails - { - IsReadModified = false, - StartTime = min, - EndTime = max, - NumValuesPerNode = (uint)Config.DataChunk, - ReturnBounds = false, - }; - break; - case HistoryReadType.BackfillData: - details = new ReadRawModifiedDetails - { - IsReadModified = false, - StartTime = min, - EndTime = max, - NumValuesPerNode = (uint)Config.DataChunk, - ReturnBounds = false, - }; - break; - case HistoryReadType.FrontfillEvents: - details = new ReadEventDetails - { - StartTime = min, - EndTime = max, - NumValuesPerNode = (uint)Config.EventChunk, - Filter = uaClient.BuildEventFilter(typeManager.EventFields), - }; - break; - case HistoryReadType.BackfillEvents: - details = new ReadEventDetails - { - StartTime = min, - EndTime = max, - NumValuesPerNode = (uint)Config.EventChunk, - Filter = uaClient.BuildEventFilter(typeManager.EventFields) - }; - break; - default: - throw new InvalidOperationException(); - } + HistoryReadType.FrontfillData => new ReadRawModifiedDetails + { + IsReadModified = false, + StartTime = min, + EndTime = max, + NumValuesPerNode = (uint)Config.DataChunk, + ReturnBounds = false, + }, + HistoryReadType.BackfillData => new ReadRawModifiedDetails + { + IsReadModified = false, + StartTime = min, + EndTime = max, + NumValuesPerNode = (uint)Config.DataChunk, + ReturnBounds = false, + }, + HistoryReadType.FrontfillEvents => new ReadEventDetails + { + StartTime = min, + EndTime = max, + NumValuesPerNode = (uint)Config.EventChunk, + Filter = uaClient.BuildEventFilter(typeManager.EventFields), + }, + HistoryReadType.BackfillEvents => new ReadEventDetails + { + StartTime = min, + EndTime = max, + NumValuesPerNode = (uint)Config.EventChunk, + Filter = uaClient.BuildEventFilter(typeManager.EventFields) + }, + _ => throw new InvalidOperationException(), + }; return (details, min, max); } @@ -557,10 +546,7 @@ private async Task HistoryDataHandler(HistoryReadNode node) var data = node.LastResult as HistoryData; node.LastResult = null; - if (node.State == null) - { - node.State = extractor.State.GetNodeState(node.Id); - } + node.State ??= extractor.State.GetNodeState(node.Id); if (node.State == null) { @@ -699,10 +685,7 @@ private async Task HistoryEventHandler(HistoryReadNode node, HistoryReadDetails log.LogWarning("No event filter when reading from history, ignoring"); return; } - if (node.State == null) - { - node.State = extractor.State.GetEmitterState(node.Id); - } + node.State ??= extractor.State.GetEmitterState(node.Id); if (node.State == null) { diff --git a/Extractor/History/SmartAggregateException.cs b/Extractor/History/SmartAggregateException.cs index 5671e8108..39f3de1ea 100644 --- a/Extractor/History/SmartAggregateException.cs +++ b/Extractor/History/SmartAggregateException.cs @@ -71,4 +71,4 @@ public SmartAggregateException(AggregateException aex) : base(AggregateException { } } -} \ No newline at end of file +} diff --git a/Extractor/Looper.cs b/Extractor/Looper.cs index 88757ca43..0b0562934 100644 --- a/Extractor/Looper.cs +++ b/Extractor/Looper.cs @@ -192,7 +192,7 @@ await Task.WhenAll( numPushes.Inc(); - if (pushWaiterSource != null) pushWaiterSource.TrySetResult(true); + pushWaiterSource?.TrySetResult(true); } diff --git a/Extractor/NodeSources/CDFNodeSourceWithFallback.cs b/Extractor/NodeSources/CDFNodeSourceWithFallback.cs index a80c0fa69..c15ec7fc1 100644 --- a/Extractor/NodeSources/CDFNodeSourceWithFallback.cs +++ b/Extractor/NodeSources/CDFNodeSourceWithFallback.cs @@ -1,9 +1,6 @@ using Cognite.OpcUa.Nodes; using Opc.Ua; -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; diff --git a/Extractor/NodeSources/INodeSource.cs b/Extractor/NodeSources/INodeSource.cs index c5cca4e6b..680059fa1 100644 --- a/Extractor/NodeSources/INodeSource.cs +++ b/Extractor/NodeSources/INodeSource.cs @@ -59,7 +59,7 @@ Task LoadNonHierarchicalReferences( CancellationToken token); } - public interface ITypeAndNodeSource: INodeSource + public interface ITypeAndNodeSource : INodeSource { Task LoadTypeMetadata(IEnumerable nodes, DataTypeConfig config, CancellationToken token); } diff --git a/Extractor/NodeSources/NodeHierarchyBuilder.cs b/Extractor/NodeSources/NodeHierarchyBuilder.cs index 8ccb3e792..3b936599c 100644 --- a/Extractor/NodeSources/NodeHierarchyBuilder.cs +++ b/Extractor/NodeSources/NodeHierarchyBuilder.cs @@ -3,7 +3,6 @@ using Cognite.OpcUa.History; using Cognite.OpcUa.Nodes; using Cognite.OpcUa.Types; -using CogniteSdk; using Microsoft.Extensions.Logging; using Opc.Ua; using System; @@ -279,7 +278,7 @@ private void UpdateFromParent(UANodeCollection nodeMap, BaseUANode node) } } - private void CheckParentShouldBeObject(BaseUANode node) + private static void CheckParentShouldBeObject(BaseUANode node) { if (node.Parent == null) return; if (node.Parent.NodeClass != NodeClass.Variable) return; @@ -289,12 +288,12 @@ private void CheckParentShouldBeObject(BaseUANode node) varParent.IsObject = true; } - private bool IsDescendantOfType(BaseUANode node) + private static bool IsDescendantOfType(BaseUANode node) { return node.Parent != null && (node.Parent.IsType || node.Parent.IsChildOfType); } - private (int Length, bool IsCollection) GetLengthOfCollection(object value) + private static (int Length, bool IsCollection) GetLengthOfCollection(object value) { int size = 0; if (value is ICollection coll) @@ -316,7 +315,7 @@ private bool IsDescendantOfType(BaseUANode node) private async Task EstimateArraySizes(IEnumerable nodes, CancellationToken token) { nodes = nodes.Where(node => - (node.ArrayDimensions == null || !node.ArrayDimensions.Any() || node.ArrayDimensions[0] == 0) + (node.ArrayDimensions == null || node.ArrayDimensions.Length == 0 || node.ArrayDimensions[0] == 0) && (node.ValueRank == ValueRanks.OneDimension || node.ValueRank == ValueRanks.ScalarOrOneDimension || node.ValueRank == ValueRanks.OneOrMoreDimensions diff --git a/Extractor/NodeSources/NodeSetNodeSource.cs b/Extractor/NodeSources/NodeSetNodeSource.cs index c4ad2ab43..65837832f 100644 --- a/Extractor/NodeSources/NodeSetNodeSource.cs +++ b/Extractor/NodeSources/NodeSetNodeSource.cs @@ -19,10 +19,8 @@ You should have received a copy of the GNU General Public License using Cognite.OpcUa.Nodes; using Cognite.OpcUa.TypeCollectors; using Cognite.OpcUa.Types; -using CogniteSdk.Beta.DataModels; using Microsoft.Extensions.Logging; using Opc.Ua; -using Serilog.Core; using System.Collections.Generic; using System.IO; using System.Linq; @@ -87,7 +85,7 @@ public Task Initialize(CancellationToken token) logger.LogInformation("Server built, resulted in a total of {Nodes} nodes", nodes.Count); isInitialized = true; } - }); + }, token); } public Task LoadNodes(IEnumerable nodesToBrowse, uint nodeClassMask, HierarchicalReferenceMode hierarchicalReferences, string purpose, CancellationToken token) @@ -341,8 +339,10 @@ private IEnumerable Browse(NodeId node, NodeId referenceTypeId, Brow } private void BrowseHierarchy(IEnumerable rootIds, uint nodeClassMask) { - var visitedNodes = new HashSet(); - visitedNodes.Add(ObjectIds.Server); + var visitedNodes = new HashSet + { + ObjectIds.Server + }; var nextIds = new HashSet(); foreach (var id in rootIds) diff --git a/Extractor/NodeTransformation.cs b/Extractor/NodeTransformation.cs index b42d15df6..938a6ac5b 100644 --- a/Extractor/NodeTransformation.cs +++ b/Extractor/NodeTransformation.cs @@ -43,24 +43,15 @@ private bool ShouldSkip(BaseUANode node, FullConfig config) { if (node == null) return true; - switch (Type) + return Type switch { - case TransformationType.Property: - // Already a property - return node.IsRawProperty; - case TransformationType.TimeSeries: - // No need to transform to timeseries if node is not property, or node cannot be a timeseries. - return !node.IsRawProperty || node.NodeClass != NodeClass.Variable; - case TransformationType.DropSubscriptions: - // No need to drop subscriptions if we are not subscribing to this node. - return !(node is UAVariable variable && variable.FullAttributes.ShouldSubscribe(config)) - && !(node is UAObject obj && obj.FullAttributes.ShouldSubscribeToEvents(config)); - case TransformationType.AsEvents: - // If not a variable or already publishing values as events we skip here. - return node is not UAVariable evtvariable || evtvariable.AsEvents; - } - - return false; + TransformationType.Property => node.IsRawProperty,// Already a property + TransformationType.TimeSeries => !node.IsRawProperty || node.NodeClass != NodeClass.Variable,// No need to transform to timeseries if node is not property, or node cannot be a timeseries. + TransformationType.DropSubscriptions => !(node is UAVariable variable && variable.FullAttributes.ShouldSubscribe(config)) + && !(node is UAObject obj && obj.FullAttributes.ShouldSubscribeToEvents(config)),// No need to drop subscriptions if we are not subscribing to this node. + TransformationType.AsEvents => node is not UAVariable evtvariable || evtvariable.AsEvents,// If not a variable or already publishing values as events we skip here. + _ => false, + }; } /// diff --git a/Extractor/Nodes/UAObject.cs b/Extractor/Nodes/UAObject.cs index 30c6baa98..dc38bda42 100644 --- a/Extractor/Nodes/UAObject.cs +++ b/Extractor/Nodes/UAObject.cs @@ -143,10 +143,7 @@ public override void Format(StringBuilder builder, int indent, bool writeParent builder.AppendFormat(CultureInfo.InvariantCulture, "{0}EventNotifier: {1}", indt, FullAttributes.EventNotifier); builder.AppendLine(); } - if (FullAttributes.TypeDefinition != null) - { - FullAttributes.TypeDefinition.Format(builder, indent + 4, false, false); - } + FullAttributes.TypeDefinition?.Format(builder, indent + 4, false, false); } } } diff --git a/Extractor/Nodes/UAVariable.cs b/Extractor/Nodes/UAVariable.cs index 420d63aec..ed88f63c4 100644 --- a/Extractor/Nodes/UAVariable.cs +++ b/Extractor/Nodes/UAVariable.cs @@ -28,7 +28,6 @@ You should have received a copy of the GNU General Public License using Opc.Ua; using System; using System.Collections.Generic; -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Linq; @@ -153,7 +152,7 @@ public void LoadFromNodeState(BaseVariableState state, TypeManager typeManager) ValueRank = state.ValueRank; DataType = typeManager.GetDataType(state.DataType); ArrayDimensions = state.ArrayDimensions.Select(Convert.ToInt32).ToArray(); - if (!ArrayDimensions.Any()) + if (ArrayDimensions.Length == 0) { ArrayDimensions = null; } @@ -214,10 +213,7 @@ public IEnumerable CreateTimeseries() } else if (IsObject) { - if (TimeSeries == null) - { - TimeSeries = new UAVariableMember(this, -1); - } + TimeSeries ??= new UAVariableMember(this, -1); return new[] { TimeSeries }; } else @@ -253,7 +249,7 @@ public struct VariableGroups public bool IsDestinationObject; public bool IsDestinationVariable; - public bool Any() + public readonly bool Any() { return IsSourceObject || IsSourceVariable || IsDestinationObject || IsDestinationVariable; } @@ -360,10 +356,7 @@ public override void Format(StringBuilder builder, int indent, bool writeParent base.Format(builder, indent + 4, writeParent); var indt = new string(' ', indent + 4); - if (FullAttributes.DataType != null) - { - FullAttributes.DataType.Format(builder, indent + 4, false); - } + FullAttributes.DataType?.Format(builder, indent + 4, false); if (FullAttributes.ValueRank != ValueRanks.Scalar) { builder.AppendFormat(CultureInfo.InvariantCulture, "{0}ValueRank: {1}", indt, FullAttributes.ValueRank); @@ -453,9 +446,9 @@ private void HandleMetaMap( LegacyName = externalId, IsString = FullAttributes.DataType.IsString, IsStep = FullAttributes.DataType.IsStep, - DataSetId = dataSetId + DataSetId = dataSetId, + Metadata = BuildMetadata(config, client, true) }; - writePoco.Metadata = BuildMetadata(config, client, true); HandleMetaMap(metaMap, writePoco, value => writePoco.AssetExternalId = value, client.StringConverter); diff --git a/Extractor/Nodes/UAVariableType.cs b/Extractor/Nodes/UAVariableType.cs index 390f33b57..7ec479931 100644 --- a/Extractor/Nodes/UAVariableType.cs +++ b/Extractor/Nodes/UAVariableType.cs @@ -26,7 +26,6 @@ You should have received a copy of the GNU General Public License using System.Globalization; using System.Linq; using System.Text; -using System.Threading.Tasks; namespace Cognite.OpcUa.Nodes { @@ -95,7 +94,7 @@ public void LoadFromNodeState(BaseVariableTypeState state, TypeManager typeManag ValueRank = state.ValueRank; DataType = typeManager.GetDataType(state.DataType); ArrayDimensions = state.ArrayDimensions.Select(Convert.ToInt32).ToArray(); - if (!ArrayDimensions.Any()) + if (ArrayDimensions.Length == 0) { ArrayDimensions = null; } @@ -183,10 +182,7 @@ public override void Format(StringBuilder builder, int indent, bool writeParent base.Format(builder, indent + 4, writeParent); var indt = new string(' ', indent + 4); - if (FullAttributes.DataType != null) - { - FullAttributes.DataType.Format(builder, indent + 4, false); - } + FullAttributes.DataType?.Format(builder, indent + 4, false); if (FullAttributes.ValueRank != ValueRanks.Scalar && FullAttributes.ValueRank > 0) { builder.AppendFormat(CultureInfo.InvariantCulture, "{0}ValueRank: {1}", indt, FullAttributes.ValueRank); diff --git a/Extractor/PubSub/ServerPubSubConfigurator.cs b/Extractor/PubSub/ServerPubSubConfigurator.cs index 011848130..52a9e80c1 100644 --- a/Extractor/PubSub/ServerPubSubConfigurator.cs +++ b/Extractor/PubSub/ServerPubSubConfigurator.cs @@ -438,7 +438,7 @@ public InternalNode( NodeId = id; TypeDefinition = typeDefinitionId; ReferenceType = referenceTypeId; - if (parent != null) parent.AddChild(this); + parent?.AddChild(this); } public void AddChild(InternalNode node) diff --git a/Extractor/Pushers/CDFPusher.cs b/Extractor/Pushers/CDFPusher.cs index 6294a0407..8682614e7 100644 --- a/Extractor/Pushers/CDFPusher.cs +++ b/Extractor/Pushers/CDFPusher.cs @@ -16,8 +16,6 @@ You should have received a copy of the GNU General Public License Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ using Cognite.Extensions; -using Cognite.Extensions.DataModels; -using Cognite.Extractor.Utils; using Cognite.Extractor.Utils.Beta; using Cognite.OpcUa.Config; using Cognite.OpcUa.History; @@ -28,10 +26,8 @@ You should have received a copy of the GNU General Public License using CogniteSdk; using CogniteSdk.Alpha; using CogniteSdk.Beta.DataModels; -using CogniteSdk.Beta.DataModels.Core; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using Opc.Ua; using Prometheus; using System; using System.Collections.Generic; @@ -67,8 +63,6 @@ public sealed class CDFPusher : IPusher private readonly BrowseCallback? callback; private RawMetadataTargetConfig? RawMetadataTargetConfig => fullConfig.Cognite?.MetadataTargets?.Raw; - private CleanMetadataTargetConfig? CleanMetadataTargetConfig => fullConfig.Cognite?.MetadataTargets?.Clean; - public CDFPusher( ILogger log, diff --git a/Extractor/Pushers/FDM/BaseDataModelDefinitions.cs b/Extractor/Pushers/FDM/BaseDataModelDefinitions.cs index 430583124..eb5ae5006 100644 --- a/Extractor/Pushers/FDM/BaseDataModelDefinitions.cs +++ b/Extractor/Pushers/FDM/BaseDataModelDefinitions.cs @@ -76,7 +76,7 @@ public static ContainerCreate BaseVariable(string space) Nullable = true } }, { "ArrayDimensions", new ContainerPropertyDefinition - { + { Type = BasePropertyType.Create(PropertyTypeVariant.int32, true), Nullable = true, Name = "ArrayDimensions" diff --git a/Extractor/Pushers/FDM/DMSValueConverter.cs b/Extractor/Pushers/FDM/DMSValueConverter.cs index 7deea43e3..6f82ea228 100644 --- a/Extractor/Pushers/FDM/DMSValueConverter.cs +++ b/Extractor/Pushers/FDM/DMSValueConverter.cs @@ -75,28 +75,19 @@ public DMSValueConverter(StringConverter converter, FdmDestinationConfig.ModelIn { if (value.Value is not IEnumerable enm) return ConvertArrayVariant(variant, new Variant(new[] { value.Value }), context); - switch (variant) + return variant switch { - case PropertyTypeVariant.int32: - return new RawPropertyValue(enm.Cast().Select(v => Convert.ToInt32(v)).ToArray()); - case PropertyTypeVariant.int64: - return new RawPropertyValue(enm.Cast().Select(v => Convert.ToInt64(v)).ToArray()); - case PropertyTypeVariant.float32: - return new RawPropertyValue(enm.Cast().Select(v => Convert.ToSingle(v)).ToArray()); - case PropertyTypeVariant.float64: - return new RawPropertyValue(enm.Cast().Select(v => Convert.ToDouble(v)).ToArray()); - case PropertyTypeVariant.timestamp: - case PropertyTypeVariant.date: - return new RawPropertyValue(enm.Cast().Select(v => Convert.ToDateTime(v)).ToArray()); - case PropertyTypeVariant.text: - return new RawPropertyValue(enm.Cast() - .Select(v => converter.ConvertToString(value.Value, null, null, StringConverterMode.Simple, context)) - .ToArray()); - case PropertyTypeVariant.boolean: - return new RawPropertyValue(Convert.ToBoolean(value.Value)); - } - - return null; + PropertyTypeVariant.int32 => new RawPropertyValue(enm.Cast().Select(v => Convert.ToInt32(v)).ToArray()), + PropertyTypeVariant.int64 => new RawPropertyValue(enm.Cast().Select(v => Convert.ToInt64(v)).ToArray()), + PropertyTypeVariant.float32 => new RawPropertyValue(enm.Cast().Select(v => Convert.ToSingle(v)).ToArray()), + PropertyTypeVariant.float64 => new RawPropertyValue(enm.Cast().Select(v => Convert.ToDouble(v)).ToArray()), + PropertyTypeVariant.timestamp or PropertyTypeVariant.date => new RawPropertyValue(enm.Cast().Select(v => Convert.ToDateTime(v)).ToArray()), + PropertyTypeVariant.text => new RawPropertyValue(enm.Cast() + .Select(v => converter.ConvertToString(value.Value, null, null, StringConverterMode.Simple, context)) + .ToArray()), + PropertyTypeVariant.boolean => new RawPropertyValue(Convert.ToBoolean(value.Value)), + _ => null, + }; } } } diff --git a/Extractor/Pushers/FDM/FDMUtils.cs b/Extractor/Pushers/FDM/FDMUtils.cs index eb2001ddd..4307a9cad 100644 --- a/Extractor/Pushers/FDM/FDMUtils.cs +++ b/Extractor/Pushers/FDM/FDMUtils.cs @@ -1,14 +1,11 @@ -using Serilog; -using System; -using System.Collections.Generic; -using System.Text; +using System; using System.Text.RegularExpressions; namespace Cognite.OpcUa.Pushers.FDM { public static class FDMUtils { - private static Regex extIdRegex = new Regex("^[a-zA-Z]([a-zA-Z0-9_]{0,253}[a-zA-Z0-9])?$", RegexOptions.Compiled); + private static readonly Regex extIdRegex = new Regex("^[a-zA-Z]([a-zA-Z0-9_]{0,253}[a-zA-Z0-9])?$", RegexOptions.Compiled); public static string SanitizeExternalId(string raw) { diff --git a/Extractor/Pushers/FDM/FDMWriter.cs b/Extractor/Pushers/FDM/FDMWriter.cs index 182a819e5..b97711d8c 100644 --- a/Extractor/Pushers/FDM/FDMWriter.cs +++ b/Extractor/Pushers/FDM/FDMWriter.cs @@ -38,12 +38,12 @@ namespace Cognite.OpcUa.Pushers.FDM { public class FDMWriter { - private CogniteDestination destination; - private FullConfig config; - private ILogger log; + private readonly CogniteDestination destination; + private readonly FullConfig config; + private readonly ILogger log; private NodeIdContext? context; - private FdmDestinationConfig.ModelInfo modelInfo; - private FdmDestinationConfig fdmConfig; + private readonly FdmDestinationConfig.ModelInfo modelInfo; + private readonly FdmDestinationConfig fdmConfig; public FDMWriter(FullConfig config, CogniteDestination destination, ILogger log) { this.config = config; @@ -103,7 +103,7 @@ private async Task InitializeSpaceAndServer(CancellationToken token) await destination.CogniteClient.Beta.DataModels.UpsertViews(new[] { serverMetaContainer.ToView(modelInfo.ModelVersion) }, token); } - private bool IsConnectionDefEqual(ConnectionDefinition lh, ConnectionDefinition rh) + private static bool IsConnectionDefEqual(ConnectionDefinition lh, ConnectionDefinition rh) { if (lh.Name != rh.Name) return false; if (lh.Description != rh.Description) return false; @@ -116,7 +116,7 @@ private bool IsConnectionDefEqual(ConnectionDefinition lh, ConnectionDefinition return true; } - private bool IsViewPropertyEqual(ViewPropertyDefinition lh, ViewPropertyCreate rh) + private static bool IsViewPropertyEqual(ViewPropertyDefinition lh, ViewPropertyCreate rh) { if (lh.Name != rh.Name) return false; if (lh.Container.Space != rh.Container.Space diff --git a/Extractor/Pushers/FDM/InstanceBuilder.cs b/Extractor/Pushers/FDM/InstanceBuilder.cs index 347b26a06..719b73131 100644 --- a/Extractor/Pushers/FDM/InstanceBuilder.cs +++ b/Extractor/Pushers/FDM/InstanceBuilder.cs @@ -1,12 +1,8 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; using System.Text.Json; using System.Text.Json.Serialization; -using System.Xml.Linq; using Cognite.OpcUa.Config; using Cognite.OpcUa.Nodes; using Cognite.OpcUa.Pushers.FDM.Types; @@ -356,7 +352,7 @@ public void Build() } } - private string SerializeStoreSize(BaseInstanceWrite data, JsonSerializerOptions options, ref long size) + private static string SerializeStoreSize(BaseInstanceWrite data, JsonSerializerOptions options, ref long size) { var res = JsonSerializer.Serialize(data, options); if (res.Length > size) diff --git a/Extractor/Pushers/FDM/NodeHierarchy.cs b/Extractor/Pushers/FDM/NodeHierarchy.cs index d334a05fa..73e06bf6b 100644 --- a/Extractor/Pushers/FDM/NodeHierarchy.cs +++ b/Extractor/Pushers/FDM/NodeHierarchy.cs @@ -1,8 +1,6 @@ using Cognite.OpcUa.Nodes; using Cognite.OpcUa.Types; using Opc.Ua; -using Serilog; -using System; using System.Collections.Generic; using System.Linq; diff --git a/Extractor/Pushers/FDM/NodeIdContext.cs b/Extractor/Pushers/FDM/NodeIdContext.cs index c3c7c6f15..7def7a13e 100644 --- a/Extractor/Pushers/FDM/NodeIdContext.cs +++ b/Extractor/Pushers/FDM/NodeIdContext.cs @@ -1,5 +1,4 @@ using Opc.Ua; -using Serilog; using System; using System.Collections.Generic; using System.Linq; @@ -9,11 +8,11 @@ namespace Cognite.OpcUa.Pushers.FDM { public class NodeIdContext { - private Dictionary namespaceIndexMap { get; } + private Dictionary NamespaceIndexMap { get; } public NodeIdContext(Dictionary namespaceIndexMap) { - this.namespaceIndexMap = namespaceIndexMap; + NamespaceIndexMap = namespaceIndexMap; } public NodeIdContext(List finalNamespaces, IEnumerable serverNamespaces) @@ -26,14 +25,14 @@ public NodeIdContext(List finalNamespaces, IEnumerable serverNam if (mappedIndex == -1) throw new InvalidOperationException("Failed to map namespace indices"); namespaceIndexMap.Add((ushort)idx, (ushort)mappedIndex); } - this.namespaceIndexMap = namespaceIndexMap; + NamespaceIndexMap = namespaceIndexMap; } public string NodeIdToString(NodeId id) { var buf = new StringBuilder(); - var idx = namespaceIndexMap[id.NamespaceIndex]; + var idx = NamespaceIndexMap[id.NamespaceIndex]; NodeId.Format(buf, id.Identifier, id.IdType, idx); return buf.ToString(); } diff --git a/Extractor/Pushers/FDM/NodeTypeCollector.cs b/Extractor/Pushers/FDM/NodeTypeCollector.cs index 352daab3b..5be8c8b85 100644 --- a/Extractor/Pushers/FDM/NodeTypeCollector.cs +++ b/Extractor/Pushers/FDM/NodeTypeCollector.cs @@ -1,7 +1,6 @@ using Cognite.OpcUa.Config; using Cognite.OpcUa.Nodes; using Cognite.OpcUa.Pushers.FDM.Types; -using Cognite.OpcUa.TypeCollectors; using Cognite.OpcUa.Types; using Microsoft.Extensions.Logging; using Opc.Ua; diff --git a/Extractor/Pushers/FDM/SimpleTypeCollector.cs b/Extractor/Pushers/FDM/SimpleTypeCollector.cs index b11ec539a..f235b28e5 100644 --- a/Extractor/Pushers/FDM/SimpleTypeCollector.cs +++ b/Extractor/Pushers/FDM/SimpleTypeCollector.cs @@ -27,6 +27,8 @@ public class SimpleTypeCollector private readonly HashSet mappedReferences = new(); private readonly NodeHierarchy typeHierarchy; + + [System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0052:Remove unread private members", Justification = "Logger is handy")] private readonly ILogger log; public SimpleTypeCollector(ILogger log, IEnumerable nodes, IEnumerable references, NodeHierarchy typeHierarchy) { diff --git a/Extractor/Pushers/FDM/TypeHierarchyBuilder.cs b/Extractor/Pushers/FDM/TypeHierarchyBuilder.cs index 233249e67..5b6f70f7b 100644 --- a/Extractor/Pushers/FDM/TypeHierarchyBuilder.cs +++ b/Extractor/Pushers/FDM/TypeHierarchyBuilder.cs @@ -1,6 +1,4 @@ -using System; using System.Collections.Generic; -using System.Linq; using Cognite.Extensions.DataModels; using Cognite.OpcUa.Config; using Cognite.OpcUa.Pushers.FDM.Types; @@ -33,7 +31,7 @@ public void Add(ContainerCreate container, string? baseView = null) Views.Add(container.Name, container.ToView(modelInfo.ModelVersion, baseView == null - ? new ViewIdentifier[0] + ? System.Array.Empty() : new[] { modelInfo.ViewIdentifier(baseView) } ) ); @@ -273,7 +271,7 @@ public FDMTypeBatch ConstructTypes(IReadOnlyDictionary t return batch; } - private bool IsEventType(FullUANodeType node) + private static bool IsEventType(FullUANodeType node) { if (node.Node.Id == ObjectTypeIds.BaseEventType) return true; if (node.Parent != null) diff --git a/Extractor/Pushers/FDM/TypeMetadata.cs b/Extractor/Pushers/FDM/TypeMetadata.cs index ce4af078b..d2fc5aa4a 100644 --- a/Extractor/Pushers/FDM/TypeMetadata.cs +++ b/Extractor/Pushers/FDM/TypeMetadata.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Text.Json.Serialization; +using System.Collections.Generic; namespace Cognite.OpcUa.Pushers.FDM { diff --git a/Extractor/Pushers/FDM/Types/NodeTypes.cs b/Extractor/Pushers/FDM/Types/NodeTypes.cs index ff39c788d..2c6c58ea8 100644 --- a/Extractor/Pushers/FDM/Types/NodeTypes.cs +++ b/Extractor/Pushers/FDM/Types/NodeTypes.cs @@ -1,11 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Xml.Linq; using Cognite.OpcUa.Nodes; using Cognite.OpcUa.Types; using Opc.Ua; -using Serilog; namespace Cognite.OpcUa.Pushers.FDM.Types { @@ -42,8 +40,8 @@ public TypeMetadata GetTypeMetadata(NodeIdContext context) pathEnum.MoveNext(); while (node.Id != NodeId) { - var pair = pathEnum.Current; - collectedNodes.Add((node, kvp.Value.ModellingRule == ModellingRule.Mandatory, pair.Reference)); + var (Reference, Name) = pathEnum.Current; + collectedNodes.Add((node, kvp.Value.ModellingRule == ModellingRule.Mandatory, Reference)); pathEnum.MoveNext(); node = node.Parent; if (node == null) throw new InvalidOperationException("Expected property to be proper child of type, followed parents to nothing"); @@ -91,7 +89,7 @@ public void Build(IReadOnlyDictionary types) } } - private string GetPath(IEnumerable<(UAReference Reference, QualifiedName Name)> path, string name) + private static string GetPath(IEnumerable<(UAReference Reference, QualifiedName Name)> path, string name) { if (path.Any()) { @@ -197,4 +195,4 @@ public IEnumerable GetAllChildren() } } } -} \ No newline at end of file +} diff --git a/Extractor/Pushers/FDM/Types/ReferenceTypes.cs b/Extractor/Pushers/FDM/Types/ReferenceTypes.cs index 9bc866a87..0ef1247cc 100644 --- a/Extractor/Pushers/FDM/Types/ReferenceTypes.cs +++ b/Extractor/Pushers/FDM/Types/ReferenceTypes.cs @@ -44,4 +44,4 @@ public ReferenceNode(NodeClass nodeClass, QualifiedName browseName, string exter ExternalId = FDMUtils.SanitizeExternalId(externalId); } } -} \ No newline at end of file +} diff --git a/Extractor/Pushers/InfluxPusher.cs b/Extractor/Pushers/InfluxPusher.cs index 8851875bf..08f275f7e 100644 --- a/Extractor/Pushers/InfluxPusher.cs +++ b/Extractor/Pushers/InfluxPusher.cs @@ -157,7 +157,7 @@ public InfluxPusher(ILogger log, FullConfig config) int droppedIdx = iex.Message.LastIndexOf("dropped=", StringComparison.InvariantCulture); if (droppedIdx != -1) { - string droppedRaw = iex.Message.Substring(droppedIdx + 8).Trim(); + string droppedRaw = iex.Message[(droppedIdx + 8)..].Trim(); if (int.TryParse(droppedRaw, out int num) && num > 0) { skippedDatapoints.Inc(num); @@ -663,7 +663,7 @@ private IEnumerable EntriesToEvents(InfluxBufferState state, string nam { if (res is not IDictionary values) continue; var sourceNode = Extractor.State.GetNodeId((string)values["Source"]); - var type = Extractor.State.GetNodeId(name.Substring(state.Id.Length + 1)); + var type = Extractor.State.GetNodeId(name[(state.Id.Length + 1)..]); var evt = new UAEvent { Time = (DateTime)values["Time"], @@ -713,7 +713,7 @@ public async Task> ReadEvents( { if (!series.Entries.Any()) continue; - var name = series.SeriesName.Substring(7); + var name = series.SeriesName[7..]; var state = states.Values.FirstOrDefault(state => name.StartsWith(state.Id, StringComparison.InvariantCulture)); if (state == null) continue; diff --git a/Extractor/Pushers/MqttPusher.cs b/Extractor/Pushers/MqttPusher.cs index 26083eb2c..b3343baaa 100644 --- a/Extractor/Pushers/MqttPusher.cs +++ b/Extractor/Pushers/MqttPusher.cs @@ -23,7 +23,6 @@ You should have received a copy of the GNU General Public License using Cognite.OpcUa.NodeSources; using Cognite.OpcUa.Types; using CogniteSdk; -using Com.Cognite.V1.Timeseries.Proto; using Google.Protobuf; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -224,11 +223,13 @@ async Task TryReconnect(int retries) } count++; - if (!dataPointList.ContainsKey(dp.Id)) + if (!dataPointList.TryGetValue(dp.Id, out List? value)) { - dataPointList[dp.Id] = new List(); + value = new List(); + dataPointList[dp.Id] = value; } - dataPointList[dp.Id].Add(dp); + + value.Add(dp); } if (count == 0) return null; diff --git a/Extractor/Pushers/PusherUtils.cs b/Extractor/Pushers/PusherUtils.cs index 5d5607433..69c818a8c 100644 --- a/Extractor/Pushers/PusherUtils.cs +++ b/Extractor/Pushers/PusherUtils.cs @@ -76,7 +76,7 @@ public static long GetTimestampValue(object value) var fields = new HashSet(); foreach (var row in newObj.RootElement.EnumerateObject()) { - if (!raw.Columns.ContainsKey(row.Name) || raw.Columns[row.Name].ToString() != row.Value.ToString()) + if (!raw.Columns.TryGetValue(row.Name, out JsonElement value) || value.ToString() != row.Value.ToString()) { return newObj.RootElement; } diff --git a/Extractor/Pushers/Writers/CDFWriter.cs b/Extractor/Pushers/Writers/CDFWriter.cs index 1e7abcd62..cc28ffc99 100644 --- a/Extractor/Pushers/Writers/CDFWriter.cs +++ b/Extractor/Pushers/Writers/CDFWriter.cs @@ -3,7 +3,6 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using Cognite.Extractor.Common; using Cognite.OpcUa.Config; using Cognite.OpcUa.Nodes; using Cognite.OpcUa.Pushers.FDM; @@ -102,21 +101,21 @@ public async Task PushNodesAndReferences( tasks.Add(Task.Run(async () => { result.References &= await clean.PushReferences(extractor, references, report, token); - })); + }, token)); } if (raw != null && raw.Relationships) { tasks.Add(Task.Run(async () => { result.RawReferences &= await raw.PushReferences(extractor, references, report, token); - })); + }, token)); } if (idm != null && idm.Relationships) { tasks.Add(Task.Run(async () => { result.References &= await idm.PushReferences(extractor, references, report, token); - })); + }, token)); } } @@ -126,14 +125,14 @@ public async Task PushNodesAndReferences( tasks.Add(Task.Run(async () => { result.RawObjects &= await raw.PushAssets(extractor, assetMap, update.Objects, report, token); - })); + }, token)); } if (assetMap.Count != 0 && idm != null && idm.Assets) { tasks.Add(Task.Run(async () => { result.Objects &= await idm.PushAssets(extractor, assetMap, update.Objects, report, token); - })); + }, token)); } if (timeseriesMap.Count != 0 && raw != null && raw.Timeseries) @@ -141,14 +140,14 @@ public async Task PushNodesAndReferences( tasks.Add(Task.Run(async () => { result.RawVariables &= await raw.PushTimeseries(extractor, timeseriesMap, update.Variables, report, token); - })); + }, token)); } if (timeseriesMap.Count != 0 && idm != null) { tasks.Add(Task.Run(async () => { result.Variables &= await idm.PushTimeseries(extractor, timeseriesMap, report, token); - })); + }, token)); } // FDM diff --git a/Extractor/Pushers/Writers/CleanWriter.cs b/Extractor/Pushers/Writers/CleanWriter.cs index 91a5de502..a7aa4ede7 100644 --- a/Extractor/Pushers/Writers/CleanWriter.cs +++ b/Extractor/Pushers/Writers/CleanWriter.cs @@ -163,7 +163,7 @@ private async Task> CreateAssets(UAExtractor extractor, } } - result.Created += creates.Count(); + result.Created += creates.Count; return creates; }, RetryMode.OnError, SanitationMode.Clean, token); diff --git a/Extractor/Pushers/Writers/IdmWriter.cs b/Extractor/Pushers/Writers/IdmWriter.cs index 43f6ce2be..5c8d4ecdc 100644 --- a/Extractor/Pushers/Writers/IdmWriter.cs +++ b/Extractor/Pushers/Writers/IdmWriter.cs @@ -3,7 +3,6 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; -using AdysTech.InfluxDB.Client.Net.DataContracts; using Cognite.Extensions; using Cognite.Extensions.DataModels.CogniteExtractorExtensions; using Cognite.Extractor.Common; @@ -16,7 +15,6 @@ using CogniteSdk.Resources.Beta; using CogniteSdk.Resources.DataModels; using Microsoft.Extensions.Logging; -using Opc.Ua; namespace Cognite.OpcUa.Pushers.Writers { @@ -103,6 +101,7 @@ CancellationToken token await sources.UpsertAsync(new[] { item }, new UpsertOptions(), token); } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "Temp interface until implemented")] public Task PushAssets( IUAClientAccess client, IDictionary nodes, @@ -116,6 +115,7 @@ CancellationToken token return Task.FromResult(true); } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0060:Remove unused parameter", Justification = "Temp interface until implemented")] public Task PushReferences( IUAClientAccess client, IEnumerable references, @@ -210,4 +210,4 @@ await generators.RunThrottled( } } -} \ No newline at end of file +} diff --git a/Extractor/Pushers/Writers/MinimalTimeseriesWriter.cs b/Extractor/Pushers/Writers/MinimalTimeseriesWriter.cs index 3b983b51e..bbf3cc961 100644 --- a/Extractor/Pushers/Writers/MinimalTimeseriesWriter.cs +++ b/Extractor/Pushers/Writers/MinimalTimeseriesWriter.cs @@ -39,11 +39,11 @@ FullConfig config : base(logger, destination, config) { } protected override IEnumerable BuildTimeseries(IDictionary tsMap, - IEnumerable ids, UAExtractor extractor, IDictionary nodeToAssetIds, Result result) + IEnumerable ids, UAExtractor extractor, IDictionary nodeToAssetIds, Result result) { var tss = ids.Select(id => tsMap[id]); - var creates = tss.Select(ts => ts.ToMinimalTimeseries(extractor, config.Cognite?.DataSet?.Id)) - .Where(ts => ts != null); + var creates = tss.Select(ts => ts.ToMinimalTimeseries(extractor, config.Cognite?.DataSet?.Id)) + .Where(ts => ts != null); result.Created += creates.Count(); return creates; } diff --git a/Extractor/RebrowseTriggerManager.cs b/Extractor/RebrowseTriggerManager.cs index d7ef31e0e..0de213a2f 100644 --- a/Extractor/RebrowseTriggerManager.cs +++ b/Extractor/RebrowseTriggerManager.cs @@ -39,7 +39,7 @@ public class RebrowseTriggerManager private readonly RebrowseTriggersConfig _config; private readonly UAExtractor _extractor; private readonly string _npdStore; - private IDictionary _extractionStates = + private readonly IDictionary _extractionStates = new Dictionary(); public RebrowseTriggerManager( diff --git a/Extractor/SessionManager.cs b/Extractor/SessionManager.cs index a9990d449..523d24f72 100644 --- a/Extractor/SessionManager.cs +++ b/Extractor/SessionManager.cs @@ -1,5 +1,4 @@ using Cognite.OpcUa.Config; -using Cognite.OpcUa.History; using Cognite.OpcUa.Subscriptions; using Microsoft.Extensions.Logging; using Opc.Ua; @@ -18,12 +17,11 @@ namespace Cognite.OpcUa public class SessionManager : IDisposable { private readonly SourceConfig config; - private readonly FullConfig fullConfig; private readonly UAClient client; private ReverseConnectManager? reverseConnectManager; // Initialized late, will be non-null after Initialize is called. private ApplicationConfiguration appConfig = null!; - private ILogger log; + private readonly ILogger log; public byte CurrentServiceLevel { get; private set; } = 255; private DateTime? lastLowSLConnectAttempt = null; @@ -53,7 +51,6 @@ public SessionManager(FullConfig config, UAClient parent, ILogger log) { client = parent; this.config = config.Source; - fullConfig = config; this.log = log; Context = new SessionContext(config, log); } @@ -138,7 +135,7 @@ public void Initialize(ApplicationConfiguration appConfig, CancellationToken tok public async Task Connect() { - Func generator = async () => + async Task generator() { ISession newSession; if (!string.IsNullOrEmpty(config.ReverseConnectUrl)) @@ -170,7 +167,7 @@ public async Task Connect() EndpointUrl = config.EndpointUrl; } SetNewSession(newSession); - }; + } await TryWithBackoff(generator, 6, liveToken); if (!liveToken.IsCancellationRequested) { @@ -310,13 +307,13 @@ private async Task WaitForReverseConnect(ISession? oldSession) } } - private static uint[] statusCodesToAbandon = new[] { + private static readonly uint[] statusCodesToAbandon = new[] { StatusCodes.BadSessionIdInvalid, StatusCodes.BadSessionNotActivated, StatusCodes.BadSessionClosed }; - private bool ShouldAbandonReconnect(Exception ex) + private static bool ShouldAbandonReconnect(Exception ex) { if (ex is AggregateException aex) { diff --git a/Extractor/SourceInformation.cs b/Extractor/SourceInformation.cs index 52d8c6f71..a4c4415ba 100644 --- a/Extractor/SourceInformation.cs +++ b/Extractor/SourceInformation.cs @@ -36,8 +36,7 @@ public SourceInformation(string manufacturer, string name, string version) ), 1, token); var buildInfoValue = res[0]; if (StatusCode.IsNotGood(buildInfoValue.StatusCode)) return null; - var buildInfo = buildInfoValue.GetValue(null)?.Body as BuildInfo; - if (buildInfo == null) return null; + if (buildInfoValue.GetValue(null)?.Body is not BuildInfo buildInfo) return null; return new SourceInformation(buildInfo.ManufacturerName ?? "unknown", buildInfo.ProductName ?? "unknown", buildInfo.SoftwareVersion ?? "unknown") { Uri = buildInfo.ProductUri, @@ -72,4 +71,4 @@ public override string ToString() return b.ToString(); } } -} \ No newline at end of file +} diff --git a/Extractor/Streamer.cs b/Extractor/Streamer.cs index 0968a0b11..4beb77ce4 100644 --- a/Extractor/Streamer.cs +++ b/Extractor/Streamer.cs @@ -15,21 +15,18 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -using Cognite.Extensions.DataModels.QueryBuilder; using Cognite.Extractor.Common; using Cognite.OpcUa.Config; using Cognite.OpcUa.History; using Cognite.OpcUa.Nodes; using Cognite.OpcUa.Types; using Microsoft.Extensions.Logging; -using MQTTnet.Internal; using Opc.Ua; using Opc.Ua.Client; using Prometheus; using System; using System.Collections.Generic; using System.Linq; -using System.Text.RegularExpressions; using System.Threading; using Nito.AsyncEx; using System.Threading.Tasks; @@ -241,7 +238,7 @@ public async Task PushDataPoints(IEnumerable passingPushers, var dataPointList = new List(); var pointRanges = new Dictionary(); - using (await dataPointMutex.EnterAsync()) + using (await dataPointMutex.EnterAsync(token)) { while (dataPointQueue.TryDequeue(out UADataPoint dp)) { @@ -324,7 +321,7 @@ public async Task PushEvents(IEnumerable passingPushers, var eventList = new List(); var eventRanges = new Dictionary(); - using (await eventMutex.EnterAsync()) + using (await eventMutex.EnterAsync(token)) { while (eventQueue.TryDequeue(out UAEvent evt)) { diff --git a/Extractor/Subscriptions/BaseCreateSubscriptionTask.cs b/Extractor/Subscriptions/BaseCreateSubscriptionTask.cs index 5a25cb7f5..e45fe0ecd 100644 --- a/Extractor/Subscriptions/BaseCreateSubscriptionTask.cs +++ b/Extractor/Subscriptions/BaseCreateSubscriptionTask.cs @@ -44,7 +44,7 @@ private async Task CreateItemsWithRetryInner(ILogger logger, int count, UARetryC { throw ExtractorUtils.HandleServiceResult(logger, ex, ExtractorUtils.SourceOp.CreateMonitoredItems); } - }, retries, ex => retries.ShouldRetryException( + }, retries, ex => UARetryConfig.ShouldRetryException( ex, // Do not retry on certain errors here. // If we actually lose connection to the server the subscription will probably be invalidated, @@ -150,7 +150,7 @@ private async Task EnsureSubscriptionExists(ILogger logger, Sessio { try { - await session.RemoveSubscriptionAsync(subscription); + await session.RemoveSubscriptionAsync(subscription, token); } finally { @@ -169,7 +169,7 @@ private async Task RunInternal(ILogger logger, SessionManager sessionManager, Fu $"ensure subscription {SubscriptionName.Name()}", () => EnsureSubscriptionExists(logger, sessionManager, config, subManager, token), config.Source.Retries, - ex => config.Source.Retries.ShouldRetryException( + ex => UARetryConfig.ShouldRetryException( ex, config.Source.Retries.FinalRetryStatusCodes.Except(outerStatusCodes) ), @@ -202,7 +202,7 @@ await RetryUtil.RetryAsync( $"create subscription {SubscriptionName.Name()}", () => RunInternal(logger, sessionManager, config, subManager, token), config.Source.Retries, - ex => config.Source.Retries.ShouldRetryException(ex, outerStatusCodes), + ex => UARetryConfig.ShouldRetryException(ex, outerStatusCodes), logger, token); Callbacks.OnCreatedSubscription(SubscriptionName); diff --git a/Extractor/Subscriptions/NodeMetricsSubscriptionTask.cs b/Extractor/Subscriptions/NodeMetricsSubscriptionTask.cs index d167c8a4d..1dc99bbfb 100644 --- a/Extractor/Subscriptions/NodeMetricsSubscriptionTask.cs +++ b/Extractor/Subscriptions/NodeMetricsSubscriptionTask.cs @@ -1,12 +1,9 @@ using Cognite.OpcUa.Config; using Opc.Ua.Client; using Opc.Ua; -using System; using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; using System.Threading; -using System.Linq; using Microsoft.Extensions.Logging; namespace Cognite.OpcUa.Subscriptions diff --git a/Extractor/Subscriptions/RebrowseTriggerSubscriptionTask.cs b/Extractor/Subscriptions/RebrowseTriggerSubscriptionTask.cs index d000ca5db..2b77c9a90 100644 --- a/Extractor/Subscriptions/RebrowseTriggerSubscriptionTask.cs +++ b/Extractor/Subscriptions/RebrowseTriggerSubscriptionTask.cs @@ -10,7 +10,7 @@ namespace Cognite.OpcUa.Subscriptions { internal class RebrowseTriggerSubscriptionTask : BaseCreateSubscriptionTask<(NodeId, string)> { - private MonitoredItemNotificationEventHandler handler; + private readonly MonitoredItemNotificationEventHandler handler; public RebrowseTriggerSubscriptionTask( MonitoredItemNotificationEventHandler handler, diff --git a/Extractor/Subscriptions/RecreateSubscriptionTask.cs b/Extractor/Subscriptions/RecreateSubscriptionTask.cs index aa80c04f1..d86d3f419 100644 --- a/Extractor/Subscriptions/RecreateSubscriptionTask.cs +++ b/Extractor/Subscriptions/RecreateSubscriptionTask.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -88,7 +87,7 @@ public override async Task Run(ILogger logger, SessionManager sessionManager, Fu { logger.LogWarning("Server is available, but subscription {Name} is not responding to notifications. Attempting to recreate.", SubscriptionName); Callbacks.OnSubscriptionFailure(SubscriptionName); - await session.RemoveSubscriptionAsync(oldSubscription); + await session.RemoveSubscriptionAsync(oldSubscription, token); } catch (ServiceResultException serviceEx) { @@ -97,7 +96,7 @@ public override async Task Run(ILogger logger, SessionManager sessionManager, Fu // Second attempt shouldn't fail, and doesn't seem to, keeping this here as a backup. try { - await session.RemoveSubscriptionAsync(oldSubscription); + await session.RemoveSubscriptionAsync(oldSubscription, token); } catch { diff --git a/Extractor/Subscriptions/ServiceLevelSubscriptionTask.cs b/Extractor/Subscriptions/ServiceLevelSubscriptionTask.cs index 7e7cf569b..d2671e6ff 100644 --- a/Extractor/Subscriptions/ServiceLevelSubscriptionTask.cs +++ b/Extractor/Subscriptions/ServiceLevelSubscriptionTask.cs @@ -2,9 +2,7 @@ using Microsoft.Extensions.Logging; using Opc.Ua; using Opc.Ua.Client; -using System; using System.Collections.Generic; -using System.Text; using System.Threading; using System.Threading.Tasks; @@ -12,7 +10,7 @@ namespace Cognite.OpcUa.Subscriptions { internal class ServiceLevelSubscriptionTask : BaseCreateSubscriptionTask { - private MonitoredItemNotificationEventHandler handler; + private readonly MonitoredItemNotificationEventHandler handler; public ServiceLevelSubscriptionTask(MonitoredItemNotificationEventHandler handler, IClientCallbacks callbacks) : base(SubscriptionName.ServiceLevel, new Dictionary { { VariableIds.Server_ServiceLevel, VariableIds.Server_ServiceLevel } }, callbacks) { diff --git a/Extractor/Subscriptions/SubscriptionManager.cs b/Extractor/Subscriptions/SubscriptionManager.cs index 8ca3402e5..48095da3d 100644 --- a/Extractor/Subscriptions/SubscriptionManager.cs +++ b/Extractor/Subscriptions/SubscriptionManager.cs @@ -1,6 +1,5 @@ using Cognite.Extractor.Common; using Cognite.OpcUa.Config; -using Cognite.OpcUa.History; using Microsoft.Extensions.Logging; using Opc.Ua.Client; using System; @@ -104,7 +103,7 @@ public async Task WaitForAllCurrentlyPendingTasks(CancellationToken token) tasks = taskQueue.Select(t => CommonUtils.WaitAsync(t.TaskFinishedEvent, Timeout.InfiniteTimeSpan, token)).ToArray(); } - if (!tasks.Any()) return; + if (tasks.Length == 0) return; await Task.WhenAll(tasks); } diff --git a/Extractor/TypeCollectors/TypeManager.cs b/Extractor/TypeCollectors/TypeManager.cs index 344accc41..259c82339 100644 --- a/Extractor/TypeCollectors/TypeManager.cs +++ b/Extractor/TypeCollectors/TypeManager.cs @@ -18,7 +18,6 @@ You should have received a copy of the GNU General Public License using System; using System.Collections.Generic; using System.Linq; -using System.Runtime.CompilerServices; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; @@ -100,7 +99,7 @@ public void InitDataTypeConfig() } } - public bool IsTypeNodeClass(NodeClass nodeClass) + public static bool IsTypeNodeClass(NodeClass nodeClass) { return nodeClass == NodeClass.ObjectType || nodeClass == NodeClass.VariableType @@ -287,7 +286,7 @@ private void CollectEventTypes() } var excludeProperties = new HashSet(config.Events.ExcludeProperties); var baseExcludeProperties = new HashSet(config.Events.BaseExcludeProperties); - var whitelist = config.Events.GetWhitelist(client.Context, log); + var whitelist = config.Events.GetWhitelist(client.Context); foreach (var type in NodeMap.Values.OfType()) { diff --git a/Extractor/Types/DummyMessageContext.cs b/Extractor/Types/DummyMessageContext.cs index 8506bedd5..c68db3955 100644 --- a/Extractor/Types/DummyMessageContext.cs +++ b/Extractor/Types/DummyMessageContext.cs @@ -1,8 +1,4 @@ using Opc.Ua; -using System; -using System.Collections.Generic; -using System.Net.Http.Headers; -using System.Text; namespace Cognite.OpcUa.Types { @@ -13,7 +9,7 @@ public DummyMessageContext(NamespaceTable namespaces) NamespaceUris = namespaces; } - public object SyncRoot => new object(); + public static object SyncRoot => new object(); public int MaxStringLength => 10_000; diff --git a/Extractor/Types/UADataPoint.cs b/Extractor/Types/UADataPoint.cs index 47bb2eaa5..1559ffb9a 100644 --- a/Extractor/Types/UADataPoint.cs +++ b/Extractor/Types/UADataPoint.cs @@ -16,9 +16,7 @@ You should have received a copy of the GNU General Public License Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ using Cognite.Extensions; -using CogniteSdk; using Microsoft.Extensions.Logging; -using Opc.Ua; using System; using System.Collections.Generic; using System.Globalization; diff --git a/Extractor/Types/UAEvent.cs b/Extractor/Types/UAEvent.cs index 80a90a583..2213fb286 100644 --- a/Extractor/Types/UAEvent.cs +++ b/Extractor/Types/UAEvent.cs @@ -186,10 +186,12 @@ public byte[] ToStorableBytes(UAExtractor extractor) /// Converted event public static UAEvent? FromStream(Stream stream, UAExtractor extractor) { - var evt = new UAEvent(); - evt.Message = CogniteUtils.StringFromStream(stream); - evt.EventId = CogniteUtils.StringFromStream(stream); - evt.SourceNode = extractor.State.GetNodeId(CogniteUtils.StringFromStream(stream)); + var evt = new UAEvent + { + Message = CogniteUtils.StringFromStream(stream), + EventId = CogniteUtils.StringFromStream(stream), + SourceNode = extractor.State.GetNodeId(CogniteUtils.StringFromStream(stream)) + }; var buffer = new byte[sizeof(long)]; if (stream.Read(buffer, 0, sizeof(long)) < sizeof(long)) return null; @@ -237,9 +239,11 @@ private void ToCDFEventBase(IUAClientAccess client, EventCreate evt, long? dataS : client.GetUniqueId(EventType?.Id); evt.DataSetId = dataSetId; - var finalMetaData = new Dictionary(); - finalMetaData["Emitter"] = client.GetUniqueId(EmittingNode) ?? "null"; - finalMetaData["TypeName"] = EventType?.Name ?? "null"; + var finalMetaData = new Dictionary + { + { "Emitter", client.GetUniqueId(EmittingNode) ?? "null" }, + { "TypeName", EventType?.Name ?? "null" } + }; if (MetaData == null) { evt.Metadata = finalMetaData; diff --git a/Extractor/Types/UAPropertySerializer.cs b/Extractor/Types/UAPropertySerializer.cs index 6835338d7..72d846731 100644 --- a/Extractor/Types/UAPropertySerializer.cs +++ b/Extractor/Types/UAPropertySerializer.cs @@ -206,10 +206,10 @@ public string ConvertToString( if (mode == StringConverterMode.ReversibleJson) { var builder = new StringBuilder(); - builder.Append("{"); + builder.Append('{'); builder.Append(@"""value"":"); builder.Append(uintVal); - builder.Append("}"); + builder.Append('}'); return builder.ToString(); } else @@ -397,7 +397,7 @@ private void WriteProperties(Utf8JsonWriter writer, BaseUANode node, bool getExt if (getExtras) { extras = node.GetExtraMetadata(config, context, converter); - if (extras != null) extras.Remove("Value"); + extras?.Remove("Value"); } // If we should treat this as a key/value pair, or write it as an object if (extras != null && extras.Count != 0 || node.Properties != null && node.Properties.Any()) diff --git a/Extractor/UAClient.cs b/Extractor/UAClient.cs index e70fe6095..e7d3a2634 100644 --- a/Extractor/UAClient.cs +++ b/Extractor/UAClient.cs @@ -308,11 +308,8 @@ private async Task StartNodeMetrics() /// public async Task GetServerNode(CancellationToken token) { - var desc = (await Browser.GetRootNodes(new[] { ObjectIds.Server }, token)).FirstOrDefault(); - if (desc == null) throw new ExtractorFailureException("Server node is null. Invalid server configuration"); - - var node = BaseUANode.Create(desc, NodeId.Null, null, this, TypeManager); - if (node == null) throw new ExtractorFailureException($"Root node {desc.NodeId} is unexpected node class: {desc.NodeClass}"); + var desc = (await Browser.GetRootNodes(new[] { ObjectIds.Server }, token)).FirstOrDefault() ?? throw new ExtractorFailureException("Server node is null. Invalid server configuration"); + var node = BaseUANode.Create(desc, NodeId.Null, null, this, TypeManager) ?? throw new ExtractorFailureException($"Root node {desc.NodeId} is unexpected node class: {desc.NodeClass}"); await ReadNodeData(new[] { node }, token, "the server node"); return node; } @@ -834,9 +831,9 @@ public EventFilter BuildEventFilter(Dictionary eventFields var operand = new SimpleAttributeOperand { AttributeId = Attributes.Value, - TypeDefinitionId = ObjectTypeIds.BaseEventType + TypeDefinitionId = ObjectTypeIds.BaseEventType, + BrowsePath = field.BrowsePath }; - operand.BrowsePath = field.BrowsePath; selectClauses.Add(operand); } @@ -928,4 +925,4 @@ protected virtual void Dispose(bool disposing) } #endregion } -} \ No newline at end of file +} diff --git a/Extractor/UAExtractor.cs b/Extractor/UAExtractor.cs index e7d4bc555..3a34bf548 100644 --- a/Extractor/UAExtractor.cs +++ b/Extractor/UAExtractor.cs @@ -32,7 +32,6 @@ You should have received a copy of the GNU General Public License using Opc.Ua; using Opc.Ua.Client; using Prometheus; -using Serilog.Debugging; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -108,7 +107,7 @@ public class UAExtractor : BaseExtractor, IUAClientAccess, IClientCa || uaClient.SessionManager.CurrentServiceLevel >= Config.Source.Redundancy.ServiceLevelThreshold; // Active subscriptions, used in tests for WaitForSubscription(). - private HashSet activeSubscriptions = new(); + private readonly HashSet activeSubscriptions = new(); /// /// Construct extractor with list of pushers @@ -247,10 +246,7 @@ public async Task OnServerReconnect(UAClient source) protected override void Init(CancellationToken token) { base.Init(token); - if (historyReader != null) - { - historyReader.Dispose(); - } + historyReader?.Dispose(); Looper = new Looper(Provider.GetRequiredService>(), Scheduler, this, Config, pushers); historyReader = new HistoryReader(Provider.GetRequiredService>(), uaClient, this, TypeManager, Config, Source.Token); @@ -431,7 +427,7 @@ public async Task FinishExtractorRestart() /// public async Task PushExtraNodes() { - if (extraNodesToBrowse.Any()) + if (!extraNodesToBrowse.IsEmpty) { var nodesToBrowse = new List(); while (extraNodesToBrowse.TryDequeue(out NodeId id)) @@ -682,7 +678,7 @@ private async Task>> MapUAToDestinatio { if (result == null) return Enumerable.Empty>(); - Streamer.AllowData = State.NodeStates.Any(); + Streamer.AllowData = State.NodeStates.Count != 0; var toPush = await PusherInput.FromNodeSourceResult(result, Context, deletesManager, Source.Token); @@ -840,8 +836,8 @@ private async Task ConfigureExtractor() if (Config.Events.EmitterIds != null && Config.Events.EmitterIds.Any() || Config.Events.HistorizingEmitterIds != null && Config.Events.HistorizingEmitterIds.Any()) { - var histEmitterIds = Config.Events.GetHistorizingEmitterIds(uaClient.Context, log); - var emitterIds = Config.Events.GetEmitterIds(uaClient.Context, log); + var histEmitterIds = Config.Events.GetHistorizingEmitterIds(uaClient.Context); + var emitterIds = Config.Events.GetEmitterIds(uaClient.Context); var eventEmitterIds = new HashSet(histEmitterIds.Concat(emitterIds)); foreach (var id in eventEmitterIds) @@ -854,8 +850,7 @@ private async Task ConfigureExtractor() } if (Config.Events.ReadServer) { - var serverNode = await uaClient.GetServerNode(Source.Token) as UAObject; - if (serverNode == null) throw new ExtractorFailureException("Server node is not an object, or does not exist"); + var serverNode = await uaClient.GetServerNode(Source.Token) as UAObject ?? throw new ExtractorFailureException("Server node is not an object, or does not exist"); if (serverNode.FullAttributes.EventNotifier != 0) { var history = serverNode.FullAttributes.ShouldReadEventHistory(Config); @@ -1105,7 +1100,7 @@ await uaClient.SubscriptionManager.EnqueueTaskAndWait(new EventSubscriptionTask( subscribeStates, uaClient.BuildEventFilter(TypeManager.EventFields), this), - Source.Token); + token); } } @@ -1125,7 +1120,7 @@ await uaClient.SubscriptionManager.EnqueueTaskAndWait(new DataPointSubscriptionT Streamer.DataSubscriptionHandler, subscribeStates, this), - Source.Token); + token); } } @@ -1147,7 +1142,7 @@ private IEnumerable> CreateSubscriptions(IEnumerab { tasks.Add(token => SubscribeToDataPoints(states, token)); } - if (State.EmitterStates.Any()) + if (State.EmitterStates.Count != 0) { tasks.Add(SubscribeToEvents); } diff --git a/ExtractorLauncher/ExtractorStarter.cs b/ExtractorLauncher/ExtractorStarter.cs index f6cf9255b..8efd8c9c0 100644 --- a/ExtractorLauncher/ExtractorStarter.cs +++ b/ExtractorLauncher/ExtractorStarter.cs @@ -134,7 +134,7 @@ public static class ExtractorStarter { return "cognite.raw-metadata and cognite.metadata-targets cannot be set at the same time."; } - if (config.Cognite == null) config.Cognite = new CognitePusherConfig(); + config.Cognite ??= new CognitePusherConfig(); var rawMetadata = config.Cognite.RawMetadata; var useCleanAssets = (rawMetadata?.Database == null || rawMetadata?.AssetsTable == null) || config.Cognite.SkipMetadata; var useCleanTimeseries = rawMetadata?.Database == null || rawMetadata?.TimeseriesTable == null; @@ -165,7 +165,7 @@ public static class ExtractorStarter else { log.LogWarning("Default writing to clean is deprecated, in the future not setting a metadata target will not write metadata to CDF at all"); - if (config.Cognite == null) config.Cognite = new CognitePusherConfig(); + config.Cognite ??= new CognitePusherConfig(); if (config.Cognite.MetadataTargets == null) config.Cognite.MetadataTargets = new MetadataTargetsConfig(); if (config.Cognite.MetadataTargets.Clean == null) config.Cognite.MetadataTargets.Clean = new CleanMetadataTargetConfig(); config.Cognite.MetadataTargets.Clean.Timeseries = true; @@ -264,10 +264,7 @@ public static async Task RunConfigTool(ILogger? log, ConfigToolParams setup, Ser SetWorkingDir(setup); - if (log == null) - { - log = LoggingUtils.GetDefault(); - } + log ??= LoggingUtils.GetDefault(); if (setup.NoConfig) { @@ -305,15 +302,12 @@ public static async Task RunConfigTool(ILogger? log, ConfigToolParams setup, Ser private static Serilog.ILogger BuildConfigToolLogger(LoggerConfig config) { - if (config == null) config = new LoggerConfig(); - if (config.Console == null) + config ??= new LoggerConfig(); + config.Console ??= new ConsoleConfig { - config.Console = new ConsoleConfig - { - Level = "information" - }; - } - var path = $"config-tool-{DateTime.Now.ToString("yyyy-MM-dd-HHmmss")}.log"; + Level = "information" + }; + var path = $"config-tool-{DateTime.Now:yyyy-MM-dd-HHmmss}.log"; return LoggingUtils.GetConfiguration(config) .WriteTo.Async(p => p.File( path: path, @@ -328,10 +322,7 @@ public static async Task RunExtractor(ILogger? log, ExtractorParams setup, Servi SetWorkingDir(setup); - if (log == null) - { - log = LoggingUtils.GetDefault(); - } + log ??= LoggingUtils.GetDefault(); version.Set(0); var ver = Extractor.Metrics.Version.GetVersion(Assembly.GetExecutingAssembly()); diff --git a/ExtractorLauncher/Worker.cs b/ExtractorLauncher/Worker.cs index 6d930358a..8f95938b9 100644 --- a/ExtractorLauncher/Worker.cs +++ b/ExtractorLauncher/Worker.cs @@ -28,11 +28,12 @@ public class Worker : BackgroundService private readonly ExtractorParams setup; private readonly ILogger eventLog; private readonly ServiceCollection services; + public Worker(ILogger eventLog, ServiceCollection services, ExtractorParams setup) { this.setup = setup; - this.eventLog = eventLog; this.services = services; + this.eventLog = eventLog; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) diff --git a/MQTTCDFBridge/Config.cs b/MQTTCDFBridge/Config.cs index 642db0ba7..d0a2ad40f 100644 --- a/MQTTCDFBridge/Config.cs +++ b/MQTTCDFBridge/Config.cs @@ -33,13 +33,13 @@ public class BridgeConfig : VersionedConfig public override void GenerateDefaults() { - if (Logger == null) Logger = new LoggerConfig(); - if (Cognite == null) Cognite = new CogniteDestConfig(); + Logger ??= new LoggerConfig(); + Cognite ??= new CogniteDestConfig(); if (Cognite.CdfChunking == null) Cognite.CdfChunking = new ChunkingConfig(); if (Cognite.CdfRetries == null) Cognite.CdfRetries = new RetryConfig(); if (Cognite.CdfThrottling == null) Cognite.CdfThrottling = new ThrottlingConfig(); if (Cognite.SdkLogging == null) Cognite.SdkLogging = new SdkLoggingConfig(); - if (Mqtt == null) Mqtt = new MQTTConfig(); + Mqtt ??= new MQTTConfig(); } } } diff --git a/MQTTCDFBridge/Destination.cs b/MQTTCDFBridge/Destination.cs index 97a0fe1e1..56fc419b6 100644 --- a/MQTTCDFBridge/Destination.cs +++ b/MQTTCDFBridge/Destination.cs @@ -22,23 +22,16 @@ namespace Cognite.Bridge /// /// Contains methods for pushing contents of MQTT payload to CDF. /// - public sealed class Destination + public sealed class Destination(CogniteDestConfig config, IServiceProvider provider) { - private readonly CogniteDestConfig config; + private readonly CogniteDestConfig config = config; private readonly ConcurrentDictionary assetIds = new ConcurrentDictionary(); private readonly ConcurrentDictionary tsIsString = new ConcurrentDictionary(); - private readonly ILogger log; + private readonly ILogger log = provider.GetRequiredService>(); - private readonly CogniteDestination destination; - - public Destination(CogniteDestConfig config, IServiceProvider provider) - { - this.config = config; - destination = provider.GetRequiredService(); - log = provider.GetRequiredService>(); - } + private readonly CogniteDestination destination = provider.GetRequiredService(); /// /// Create an asset update from a new asset and an old. diff --git a/MQTTCDFBridge/Program.cs b/MQTTCDFBridge/Program.cs index fae05de77..08f2ca38b 100644 --- a/MQTTCDFBridge/Program.cs +++ b/MQTTCDFBridge/Program.cs @@ -15,10 +15,7 @@ internal sealed class Program private static void Main(string[] args) { var configPath = Environment.GetEnvironmentVariable("MQTT_BRIDGE_CONFIG_DIR"); - if (configPath == null) - { - configPath = args.Length > 0 ? args[0] : "config/config.bridge.yml"; - } + configPath ??= args.Length > 0 ? args[0] : "config/config.bridge.yml"; var services = new ServiceCollection(); var config = services.AddConfig(configPath, 1); services.AddCogniteClient("MQTT-CDF Bridge"); diff --git a/Server/DebugMasterNodeManager.cs b/Server/DebugMasterNodeManager.cs index bf727abc8..6a971a1e3 100644 --- a/Server/DebugMasterNodeManager.cs +++ b/Server/DebugMasterNodeManager.cs @@ -37,7 +37,7 @@ public class DebugMasterNodeManager : MasterNodeManager private readonly TestServer server; - private IServerRequestCallbacks callbacks => server.Callbacks; + private IServerRequestCallbacks Callbacks => server.Callbacks; public DebugMasterNodeManager( IServerInternal server, @@ -60,7 +60,7 @@ public override void Read( { ArgumentNullException.ThrowIfNull(nodesToRead); - callbacks.OnRead(context, nodesToRead); + Callbacks.OnRead(context, nodesToRead); base.Read(context, maxAge, timestampsToReturn, nodesToRead, out values, out diagnosticInfos); } @@ -78,7 +78,7 @@ public override void CreateMonitoredItems( ArgumentNullException.ThrowIfNull(itemsToCreate); ArgumentNullException.ThrowIfNull(errors); - callbacks.OnCreateMonitoredItems(context, subscriptionId, itemsToCreate); + Callbacks.OnCreateMonitoredItems(context, subscriptionId, itemsToCreate); base.CreateMonitoredItems(context, subscriptionId, publishingInterval, timestampsToReturn, itemsToCreate, errors, filterResults, monitoredItems); } @@ -94,7 +94,7 @@ public override void HistoryRead( { ArgumentNullException.ThrowIfNull(nodesToRead); - callbacks.OnHistoryRead(context, historyReadDetails, nodesToRead); + Callbacks.OnHistoryRead(context, historyReadDetails, nodesToRead); base.HistoryRead(context, historyReadDetails, timestampsToReturn, releaseContinuationPoints, nodesToRead, out results, out diagnosticInfos); } @@ -110,7 +110,7 @@ public override void Browse( ArgumentNullException.ThrowIfNull(context); ArgumentNullException.ThrowIfNull(nodesToBrowse); - callbacks.OnBrowse(context, nodesToBrowse); + Callbacks.OnBrowse(context, nodesToBrowse); base.Browse(context, view, maxReferencesPerNode, nodesToBrowse, out results, out diagnosticInfos); @@ -137,7 +137,7 @@ public override void Browse( public override void BrowseNext(OperationContext context, bool releaseContinuationPoints, ByteStringCollection continuationPoints, out BrowseResultCollection results, out DiagnosticInfoCollection diagnosticInfos) { - callbacks.OnBrowseNext(context, continuationPoints); + Callbacks.OnBrowseNext(context, continuationPoints); base.BrowseNext(context, releaseContinuationPoints, continuationPoints, out results, out diagnosticInfos); } diff --git a/Server/ErrorCallbacks.cs b/Server/ErrorCallbacks.cs index 09131f0f2..b2005d03d 100644 --- a/Server/ErrorCallbacks.cs +++ b/Server/ErrorCallbacks.cs @@ -205,4 +205,4 @@ public void OnCreateSubscription(OperationContext context, double requestedPubli } } } -} \ No newline at end of file +} diff --git a/Server/IServerRequestCallbacks.cs b/Server/IServerRequestCallbacks.cs index dfdbd2a4e..6a83d5011 100644 --- a/Server/IServerRequestCallbacks.cs +++ b/Server/IServerRequestCallbacks.cs @@ -23,7 +23,7 @@ public class EmptyServerCallbacks : IServerRequestCallbacks { } public class AggregateCallbacks : IServerRequestCallbacks { - private IEnumerable children; + private readonly IEnumerable children; public AggregateCallbacks(params IServerRequestCallbacks[] children) { @@ -60,4 +60,4 @@ public void OnCreateSubscription(OperationContext context, double requestedPubli foreach (var child in children) child.OnCreateSubscription(context, requestedPublishingInterval, requestedLifetimeCount, requestedMaxKeepAliveCount, maxNotificationsPerPublish, publishingEnabled, priority); } } -} \ No newline at end of file +} diff --git a/Server/NodeManager.cs b/Server/NodeManager.cs index 367908089..1cda9f2a7 100644 --- a/Server/NodeManager.cs +++ b/Server/NodeManager.cs @@ -467,13 +467,15 @@ public void SetEventConfig(bool auditing, bool server, bool serverAuditing) [System.Diagnostics.CodeAnalysis.SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "NodeStates are disposed in CustomNodeManager2, so long as they are added to the list of predefined nodes")] - private void CreateNamespaceMetadataNode(IDictionary> externalReferences) + private void CreateNamespaceMetadataNode() { var serverNamespacesNode = Server.NodeManager.ConfigurationNodeManager .FindPredefinedNode(ObjectIds.Server_Namespaces, typeof(NamespacesState)) as NamespacesState; var namespaceUri = "opc.tcp://test.localhost"; - var namespaceMetadataState = new NamespaceMetadataState(serverNamespacesNode); - namespaceMetadataState.BrowseName = new QualifiedName(namespaceUri, NamespaceIndex); + var namespaceMetadataState = new NamespaceMetadataState(serverNamespacesNode) + { + BrowseName = new QualifiedName(namespaceUri, NamespaceIndex) + }; namespaceMetadataState.Create(SystemContext, null, namespaceMetadataState.BrowseName, null, true); namespaceMetadataState.DisplayName = namespaceUri; namespaceMetadataState.SymbolicName = namespaceUri; @@ -598,7 +600,7 @@ public override void CreateAddressSpace(IDictionary> e LoadAddressSpaceFiles(externalReferences); - CreateNamespaceMetadataNode(externalReferences); + CreateNamespaceMetadataNode(); } catch (Exception ex) { diff --git a/Server/Program.cs b/Server/Program.cs index a21c13aa8..4fc397ee0 100644 --- a/Server/Program.cs +++ b/Server/Program.cs @@ -19,7 +19,6 @@ You should have received a copy of the GNU General Public License using Cognite.Extractor.Utils.CommandLine; using Microsoft.Extensions.DependencyInjection; using Opc.Ua; -using Serilog; using System; using System.Collections.Generic; using System.CommandLine; diff --git a/Server/PubSubManager.cs b/Server/PubSubManager.cs index 983624bc8..6fd6fe841 100644 --- a/Server/PubSubManager.cs +++ b/Server/PubSubManager.cs @@ -32,7 +32,7 @@ public sealed class PubSubManager : IDisposable private readonly PublishedDataItemsDataType[] items = new PublishedDataItemsDataType[2]; private UaPubSubApplication app; - private ILogger log; + private readonly ILogger log; public PubSubManager(string mqttUrl, ILogger log) { diff --git a/Server/ServerController.cs b/Server/ServerController.cs index beb5b04a9..a3c1e04e8 100644 --- a/Server/ServerController.cs +++ b/Server/ServerController.cs @@ -44,7 +44,7 @@ sealed public class ServerController : IDisposable private readonly bool logTrace; private readonly IServiceProvider provider; private bool running; - private IEnumerable nodeSetFiles; + private readonly IEnumerable nodeSetFiles; private readonly string certPath; public ServerController( @@ -385,7 +385,7 @@ public void UpdateCustomNodes(int idx, StatusCode? code = null) ? new[] { 123, 123, 321, 123 } : new[] { 123, 123, 123, 321 }, code); } - private static Random random = new Random(); + private static readonly Random random = new Random(); public void UpdateVeryManyVariables(int idx) { var num = (double)idx; diff --git a/Test/AssemblyInfo.cs b/Test/AssemblyInfo.cs index c24077a11..63bf3d35d 100644 --- a/Test/AssemblyInfo.cs +++ b/Test/AssemblyInfo.cs @@ -1,2 +1,2 @@ using Xunit; -[assembly: CollectionBehavior(DisableTestParallelization = true)] \ No newline at end of file +[assembly: CollectionBehavior(DisableTestParallelization = true)] diff --git a/Test/CDFMockHandler.cs b/Test/CDFMockHandler.cs index 151b8cd55..849f7b709 100644 --- a/Test/CDFMockHandler.cs +++ b/Test/CDFMockHandler.cs @@ -15,7 +15,6 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -using Cognite.OpcUa; using CogniteSdk; using CogniteSdk.Beta.DataModels; using Com.Cognite.V1.Timeseries.Proto; @@ -888,10 +887,7 @@ private HttpResponseMessage HandleUpdateAssets(string content) { old.metadata = upd.metadata.set; } - else if (old.metadata == null) - { - old.metadata = new Dictionary(); - } + else old.metadata ??= new Dictionary(); if (upd.metadata.remove != null) { foreach (var field in upd.metadata.remove) @@ -968,10 +964,7 @@ private HttpResponseMessage HandleUpdateTimeSeries(string content) { old.metadata = upd.metadata.set; } - else if (old.metadata == null) - { - old.metadata = new Dictionary(); - } + else old.metadata ??= new Dictionary(); if (upd.metadata.remove != null) { foreach (var field in upd.metadata.remove) diff --git a/Test/CommonTestUtils.cs b/Test/CommonTestUtils.cs index cc0a755ae..85d257042 100644 --- a/Test/CommonTestUtils.cs +++ b/Test/CommonTestUtils.cs @@ -215,7 +215,7 @@ public static void VerifyStartingConditions( { ArgumentNullException.ThrowIfNull(assets); ArgumentNullException.ThrowIfNull(timeseries); - if (upd == null) upd = new UpdateConfig(); + upd ??= new UpdateConfig(); ArgumentNullException.ThrowIfNull(client); ArgumentNullException.ThrowIfNull(ids); Assert.Equal(6, assets.Count); @@ -287,7 +287,7 @@ public static void VerifyModified( { ArgumentNullException.ThrowIfNull(assets); ArgumentNullException.ThrowIfNull(timeseries); - if (upd == null) upd = new UpdateConfig(); + upd ??= new UpdateConfig(); ArgumentNullException.ThrowIfNull(client); ArgumentNullException.ThrowIfNull(ids); Assert.Equal(6, assets.Count); diff --git a/Test/Integration/LauncherTests.cs b/Test/Integration/LauncherTests.cs index 3a9565cf9..266feddad 100644 --- a/Test/Integration/LauncherTests.cs +++ b/Test/Integration/LauncherTests.cs @@ -71,10 +71,7 @@ public LauncherTests(ITestOutputHelper output, LauncherTestFixture tester) { lock (tester) { - if (extractor != null) - { - extractor.Dispose(); - } + extractor?.Dispose(); extractor = e; } }; @@ -466,10 +463,12 @@ public void TestVerifyAndBuildConfig() config.GenerateDefaults(); config.Logger.File = new FileConfig { Level = "debug" }; config.Source.EndpointUrl = tester.EndpointUrl; - setup = new ExtractorParams(); - setup.NoConfig = true; - setup.LogDir = "logs2"; - setup.Exit = true; + setup = new ExtractorParams + { + NoConfig = true, + LogDir = "logs2", + Exit = true + }; var options = new ExtractorRunnerParams(); method.Invoke(typeof(ExtractorStarter), new object[] { log, config, setup, options, "config", services }); diff --git a/Test/Integration/NodeExtractionTests.cs b/Test/Integration/NodeExtractionTests.cs index 25d95ace4..5b0133d16 100644 --- a/Test/Integration/NodeExtractionTests.cs +++ b/Test/Integration/NodeExtractionTests.cs @@ -4,7 +4,6 @@ using Cognite.OpcUa.Nodes; using Cognite.OpcUa.Subscriptions; using Cognite.OpcUa.Types; -using CogniteSdk; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Opc.Ua; @@ -30,7 +29,6 @@ public NodeExtractionTestFixture() : base() public class NodeExtractionTests : IClassFixture { private readonly NodeExtractionTestFixture tester; - private readonly ITestOutputHelper _output; public NodeExtractionTests(ITestOutputHelper output, NodeExtractionTestFixture tester) { @@ -39,7 +37,6 @@ public NodeExtractionTests(ITestOutputHelper output, NodeExtractionTestFixture t tester.ResetConfig(); tester.Config.History.Enabled = false; tester.Client.TypeManager.Reset(); - _output = output; } #region datatypeconfig [Fact] diff --git a/Test/Integration/RebrowseTriggerManagerTests.cs b/Test/Integration/RebrowseTriggerManagerTests.cs index 3b6013de9..8aed7d57f 100644 --- a/Test/Integration/RebrowseTriggerManagerTests.cs +++ b/Test/Integration/RebrowseTriggerManagerTests.cs @@ -22,7 +22,7 @@ public class RebrowseTriggerManagerTests { private readonly StaticServerTestFixture tester; private readonly ITestOutputHelper _output; - private Dictionary _extractionStates = new(); + private readonly Dictionary _extractionStates = new(); public RebrowseTriggerManagerTests(ITestOutputHelper output, StaticServerTestFixture tester) { diff --git a/Test/Unit/CDFPusherTest.cs b/Test/Unit/CDFPusherTest.cs index b798a48be..5f7c40ca3 100644 --- a/Test/Unit/CDFPusherTest.cs +++ b/Test/Unit/CDFPusherTest.cs @@ -37,7 +37,6 @@ public CDFPusherTestFixture() : base() public sealed class CDFPusherTest : IClassFixture, IDisposable { private readonly CDFPusherTestFixture tester; - private readonly ITestOutputHelper _output; private CDFMockHandler handler; private CDFPusher pusher; public CDFPusherTest(ITestOutputHelper output, CDFPusherTestFixture tester) @@ -47,7 +46,6 @@ public CDFPusherTest(ITestOutputHelper output, CDFPusherTestFixture tester) tester.ResetConfig(); (handler, pusher) = tester.GetCDFPusher(); tester.Client.TypeManager.Reset(); - _output = output; } public void Dispose() @@ -1160,9 +1158,9 @@ public async Task TestCDFAsSourceData() tester.Config.Cognite.RawNodeBuffer.BrowseOnEmpty = true; await extractor.RunExtractor(true); Assert.True(extractor.State.NodeStates.Count > 0); - Assert.True(handler.AssetsRaw.Count != 0); - Assert.True(handler.TimeseriesRaw.Count != 0); - Assert.True(handler.Timeseries.Count != 0); + Assert.NotEmpty(handler.AssetsRaw); + Assert.NotEmpty(handler.TimeseriesRaw); + Assert.NotEmpty(handler.Timeseries); Assert.Empty(handler.Assets); await extractor.WaitForSubscription(SubscriptionName.DataPoints); @@ -1252,9 +1250,9 @@ public async Task TestCDFAsSourceEvents() tester.Config.Cognite.RawNodeBuffer.BrowseOnEmpty = true; await extractor.RunExtractor(true); Assert.True(extractor.State.NodeStates.Count > 0); - Assert.True(handler.AssetsRaw.Count != 0); - Assert.True(handler.TimeseriesRaw.Count != 0); - Assert.True(handler.Timeseries.Count != 0); + Assert.NotEmpty(handler.AssetsRaw); + Assert.NotEmpty(handler.TimeseriesRaw); + Assert.NotEmpty(handler.Timeseries); Assert.Empty(handler.Assets); await extractor.WaitForSubscription(SubscriptionName.Events); @@ -1325,9 +1323,9 @@ public async Task TestCDFNodeSetBackground() tester.Config.Cognite.RawNodeBuffer.BrowseOnEmpty = true; await extractor.RunExtractor(true); Assert.True(extractor.State.NodeStates.Count > 0); - Assert.True(handler.AssetsRaw.Count != 0); - Assert.True(handler.TimeseriesRaw.Count != 0); - Assert.True(handler.Timeseries.Count != 0); + Assert.NotEmpty(handler.AssetsRaw); + Assert.NotEmpty(handler.TimeseriesRaw); + Assert.NotEmpty(handler.Timeseries); Assert.Empty(handler.Assets); await extractor.WaitForSubscription(SubscriptionName.Events); diff --git a/Test/Unit/FDMTests.cs b/Test/Unit/FDMTests.cs index d8117617c..29d12577c 100644 --- a/Test/Unit/FDMTests.cs +++ b/Test/Unit/FDMTests.cs @@ -3,10 +3,8 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Opc.Ua; -using Serilog; using Server; using System; -using System.CommandLine; using System.IO; using System.Linq; using System.Text.Json.Nodes; @@ -111,7 +109,7 @@ public async Task TestMapCustomTypes() // 4 total variable types (1 custom + property type + data variable type + base) // 11 total reference types // 7 (?) data types - uint? GetNodeClass(JsonNode node) + static uint? GetNodeClass(JsonNode node) { return GetPropertyStruct(node, "NodeClass", "BaseNode"); } diff --git a/Test/Unit/HistoryReaderTest.cs b/Test/Unit/HistoryReaderTest.cs index 8eb8dc792..f3b03b7ef 100644 --- a/Test/Unit/HistoryReaderTest.cs +++ b/Test/Unit/HistoryReaderTest.cs @@ -101,18 +101,22 @@ public void TestHistoryDataHandler() historyData.DataValues = frontfillDataValues; - node = new HistoryReadNode(HistoryReadType.FrontfillData, new NodeId("badstate", 0)); - node.LastResult = historyData; - node.ContinuationPoint = null; + node = new HistoryReadNode(HistoryReadType.FrontfillData, new NodeId("badstate", 0)) + { + LastResult = historyData, + ContinuationPoint = null + }; historyDataHandler.Invoke(reader, new object[] { node }); Assert.Equal(0, node.TotalRead); Assert.False(state1.IsFrontfilling); state1.RestartHistory(); // Test frontfill OK - node = new HistoryReadNode(HistoryReadType.FrontfillData, new NodeId("state1", 0)); - node.LastResult = historyData; - node.ContinuationPoint = null; + node = new HistoryReadNode(HistoryReadType.FrontfillData, new NodeId("state1", 0)) + { + LastResult = historyData, + ContinuationPoint = null + }; historyDataHandler.Invoke(reader, new object[] { node }); Assert.Equal(100, node.TotalRead); Assert.Equal(start.AddSeconds(99), state1.SourceExtractedRange.Last); @@ -124,9 +128,11 @@ public void TestHistoryDataHandler() .Select(idx => new DataValue(idx, StatusCodes.Good, start.AddSeconds(-idx)))); historyData.DataValues = backfillDataValues; Assert.True(state1.IsBackfilling); - node = new HistoryReadNode(HistoryReadType.BackfillData, new NodeId("state1", 0)); - node.LastResult = historyData; - node.ContinuationPoint = null; + node = new HistoryReadNode(HistoryReadType.BackfillData, new NodeId("state1", 0)) + { + LastResult = historyData, + ContinuationPoint = null + }; historyDataHandler.Invoke(backfillReader, new object[] { node }); Assert.Equal(100, node.TotalRead); Assert.Equal(new TimeRange(start.AddSeconds(-99), start.AddSeconds(99)), state1.SourceExtractedRange); @@ -140,9 +146,11 @@ public void TestHistoryDataHandler() historyData.DataValues = badDps; state1.RestartHistory(); queue.Clear(); - node = new HistoryReadNode(HistoryReadType.FrontfillData, new NodeId("state1", 0)); - node.LastResult = historyData; - node.ContinuationPoint = new byte[] { 1, 2, 3 }; + node = new HistoryReadNode(HistoryReadType.FrontfillData, new NodeId("state1", 0)) + { + LastResult = historyData, + ContinuationPoint = new byte[] { 1, 2, 3 } + }; historyDataHandler.Invoke(reader, new object[] { node }); Assert.Equal(100, node.TotalRead); Assert.Equal(start.AddSeconds(99), state1.SourceExtractedRange.Last); @@ -157,9 +165,11 @@ public void TestHistoryDataHandler() // Get a datapoint from stream that happened after the last history point was read from the server, but arrived // at the extractor before the history data was parsed. This is an edge-case, but a potential lost datapoint state1.UpdateFromStream(new[] { new UADataPoint(start.AddSeconds(100), "state1", 1.0, StatusCodes.Good) }); - node = new HistoryReadNode(HistoryReadType.FrontfillData, new NodeId("state1", 0)); - node.LastResult = historyData; - node.ContinuationPoint = null; + node = new HistoryReadNode(HistoryReadType.FrontfillData, new NodeId("state1", 0)) + { + LastResult = historyData, + ContinuationPoint = null + }; historyDataHandler.Invoke(reader, new object[] { node }); Assert.Equal(100, node.TotalRead); Assert.False(state1.IsFrontfilling); @@ -171,8 +181,10 @@ public void TestHistoryDataHandler() state1.RestartHistory(); queue.Clear(); cfg.IgnoreContinuationPoints = true; - node = new HistoryReadNode(HistoryReadType.FrontfillData, new NodeId("state1", 0)); - node.LastResult = historyData; + node = new HistoryReadNode(HistoryReadType.FrontfillData, new NodeId("state1", 0)) + { + LastResult = historyData + }; historyDataHandler.Invoke(reader, new object[] { node }); Assert.Equal(100, node.TotalRead); Assert.True(state1.IsFrontfilling); @@ -180,9 +192,11 @@ public void TestHistoryDataHandler() Assert.Equal(start.AddSeconds(99), state1.SourceExtractedRange.Last); historyData.DataValues = null; - node = new HistoryReadNode(HistoryReadType.FrontfillData, new NodeId("state1", 0)); - node.LastResult = historyData; - node.ContinuationPoint = new byte[] { 1, 2, 3 }; + node = new HistoryReadNode(HistoryReadType.FrontfillData, new NodeId("state1", 0)) + { + LastResult = historyData, + ContinuationPoint = new byte[] { 1, 2, 3 } + }; historyDataHandler.Invoke(reader, new object[] { node }); Assert.Equal(0, node.TotalRead); Assert.False(state1.IsFrontfilling); @@ -237,21 +251,27 @@ public void TestHistoryEventHandler() .Select(idx => EventUtils.GetEventValues(start.AddSeconds(idx))) .Select(values => new HistoryEventFieldList { EventFields = values })); var historyEvents = new HistoryEvent { Events = frontfillEvents }; - node = new HistoryReadNode(HistoryReadType.FrontfillEvents, new NodeId("emitter", 0)); - node.LastResult = historyEvents; + node = new HistoryReadNode(HistoryReadType.FrontfillEvents, new NodeId("emitter", 0)) + { + LastResult = historyEvents + }; historyEventHandler.Invoke(reader, new object[] { node, null }); Assert.Equal(0, node.TotalRead); // Test bad emitter historyEvents.Events = frontfillEvents; - node = new HistoryReadNode(HistoryReadType.FrontfillEvents, new NodeId("bademitter", 0)); - node.LastResult = historyEvents; + node = new HistoryReadNode(HistoryReadType.FrontfillEvents, new NodeId("bademitter", 0)) + { + LastResult = historyEvents + }; historyEventHandler.Invoke(reader, new object[] { node, details }); Assert.Equal(0, node.TotalRead); // Test frontfill OK - node = new HistoryReadNode(HistoryReadType.FrontfillEvents, new NodeId("emitter", 0)); - node.LastResult = historyEvents; + node = new HistoryReadNode(HistoryReadType.FrontfillEvents, new NodeId("emitter", 0)) + { + LastResult = historyEvents + }; historyEventHandler.Invoke(reader, new object[] { node, details }); Assert.Equal(100, node.TotalRead); Assert.Equal(start.AddSeconds(99), state.SourceExtractedRange.Last); @@ -264,8 +284,10 @@ public void TestHistoryEventHandler() .Select(values => new HistoryEventFieldList { EventFields = values })); historyEvents.Events = backfillEvents; Assert.True(state.IsBackfilling); - node = new HistoryReadNode(HistoryReadType.BackfillEvents, new NodeId("emitter", 0)); - node.LastResult = historyEvents; + node = new HistoryReadNode(HistoryReadType.BackfillEvents, new NodeId("emitter", 0)) + { + LastResult = historyEvents + }; historyEventHandler.Invoke(backfillReader, new object[] { node, details }); Assert.Equal(100, node.TotalRead); Assert.Equal(new TimeRange(start.AddSeconds(-99), start.AddSeconds(99)), state.SourceExtractedRange); @@ -286,9 +308,11 @@ public void TestHistoryEventHandler() historyEvents.Events = badEvts; state.RestartHistory(); queue.Clear(); - node = new HistoryReadNode(HistoryReadType.FrontfillEvents, new NodeId("emitter", 0)); - node.LastResult = historyEvents; - node.ContinuationPoint = new byte[] { 1, 2, 3 }; + node = new HistoryReadNode(HistoryReadType.FrontfillEvents, new NodeId("emitter", 0)) + { + LastResult = historyEvents, + ContinuationPoint = new byte[] { 1, 2, 3 } + }; historyEventHandler.Invoke(reader, new object[] { node, details }); Assert.Equal(0, node.TotalRead); Assert.Equal(start.AddSeconds(99), state.SourceExtractedRange.Last); @@ -301,8 +325,10 @@ public void TestHistoryEventHandler() state.RestartHistory(); queue.Clear(); state.UpdateFromStream(new UAEvent { Time = start.AddSeconds(100) }); - node = new HistoryReadNode(HistoryReadType.FrontfillEvents, new NodeId("emitter", 0)); - node.LastResult = historyEvents; + node = new HistoryReadNode(HistoryReadType.FrontfillEvents, new NodeId("emitter", 0)) + { + LastResult = historyEvents + }; historyEventHandler.Invoke(reader, new object[] { node, details }); Assert.Equal(100, node.TotalRead); Assert.False(state.IsFrontfilling); @@ -314,8 +340,10 @@ public void TestHistoryEventHandler() state.RestartHistory(); queue.Clear(); cfg.IgnoreContinuationPoints = true; - node = new HistoryReadNode(HistoryReadType.FrontfillEvents, new NodeId("emitter", 0)); - node.LastResult = historyEvents; + node = new HistoryReadNode(HistoryReadType.FrontfillEvents, new NodeId("emitter", 0)) + { + LastResult = historyEvents + }; historyEventHandler.Invoke(reader, new object[] { node, details }); Assert.Equal(100, node.TotalRead); Assert.True(state.IsFrontfilling); @@ -323,8 +351,11 @@ public void TestHistoryEventHandler() Assert.Equal(start.AddSeconds(99), state.SourceExtractedRange.Last); historyEvents.Events = null; - node = new HistoryReadNode(HistoryReadType.FrontfillEvents, new NodeId("emitter", 0)) { Completed = false }; - node.LastResult = historyEvents; + node = new HistoryReadNode(HistoryReadType.FrontfillEvents, new NodeId("emitter", 0)) + { + Completed = false, + LastResult = historyEvents + }; historyEventHandler.Invoke(reader, new object[] { node, details }); Assert.Equal(0, node.TotalRead); Assert.False(state.IsFrontfilling); diff --git a/Test/Unit/TransformationTest.cs b/Test/Unit/TransformationTest.cs index 3bf5fb0a4..9d04596bf 100644 --- a/Test/Unit/TransformationTest.cs +++ b/Test/Unit/TransformationTest.cs @@ -7,15 +7,11 @@ using Microsoft.Extensions.Logging; using Opc.Ua; using System; -using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using Xunit; using Xunit.Abstractions; -using YamlDotNet.Serialization; -using YamlDotNet.Serialization.NamingConventions; -using YamlDotNet.Serialization.TypeInspectors; namespace Test.Unit { @@ -350,7 +346,7 @@ public void TestMultipleFilter() { node = new UAVariable(id, i == 4 ? "not" : "target", null, i == 5 ? parent2 : parent1, NodeId.Null, new UAVariableType(i == 2 ? new NodeId(2) : new NodeId(1))); (node as UAVariable).FullAttributes.ArrayDimensions = i == 3 ? null : new[] { 4 }; - (node as UAVariable).FullAttributes.Historizing = i == 8 ? true : false; + (node as UAVariable).FullAttributes.Historizing = i == 8; } else { diff --git a/Test/Unit/TypeManagerTest.cs b/Test/Unit/TypeManagerTest.cs index 248bb5e2e..6f1da811b 100644 --- a/Test/Unit/TypeManagerTest.cs +++ b/Test/Unit/TypeManagerTest.cs @@ -190,8 +190,10 @@ public void TestAllowTsMap() Assert.True(node.AllowTSMap(tester.Log, config)); // Ignored datatype - node.FullAttributes.DataType = new UADataType(new NodeId("ignore", 0)); - node.FullAttributes.DataType.ShouldIgnore = true; + node.FullAttributes.DataType = new UADataType(new NodeId("ignore", 0)) + { + ShouldIgnore = true + }; Assert.False(node.AllowTSMap(tester.Log, config)); // Non-scalar value rank diff --git a/Test/Unit/UAClientTest.cs b/Test/Unit/UAClientTest.cs index 2297e9058..5c9c31ce9 100644 --- a/Test/Unit/UAClientTest.cs +++ b/Test/Unit/UAClientTest.cs @@ -1357,13 +1357,15 @@ public void TestGetUniqueId() [Fact] public void TestRetryConfig() { - var retryConfig = new UARetryConfig(); - retryConfig.RetryStatusCodes = new[] + var retryConfig = new UARetryConfig + { + RetryStatusCodes = new[] { "BadNotConnected", "BadWouldBlock", 0x80B60000.ToString(), "0x80890000" + } }; Assert.Contains(StatusCodes.BadNotConnected, retryConfig.FinalRetryStatusCodes); diff --git a/Test/Unit/UAExtractorTest.cs b/Test/Unit/UAExtractorTest.cs index 1e942a0fe..6fe437623 100644 --- a/Test/Unit/UAExtractorTest.cs +++ b/Test/Unit/UAExtractorTest.cs @@ -75,7 +75,7 @@ public async Task TestRestartOnReconnect() var task = extractor.RunExtractor(); await extractor.WaitForSubscription(SubscriptionName.DataPoints); - Assert.True(pusher.PushedNodes.Count != 0); + Assert.NotEmpty(pusher.PushedNodes); pusher.PushedNodes.Clear(); await extractor.OnServerReconnect(tester.Client); diff --git a/Test/Utils/BaseExtractorTestFixture.cs b/Test/Utils/BaseExtractorTestFixture.cs index bb5d8cf45..ac331f04d 100644 --- a/Test/Utils/BaseExtractorTestFixture.cs +++ b/Test/Utils/BaseExtractorTestFixture.cs @@ -58,12 +58,9 @@ protected BaseExtractorTestFixture(PredefinedSetup[] setups = null) Log = Provider.GetRequiredService>(); - if (setups == null) - { - setups = new[] { + setups ??= new[] { PredefinedSetup.Custom, PredefinedSetup.Base, PredefinedSetup.Events, PredefinedSetup.Wrong, PredefinedSetup.Full, PredefinedSetup.Auditing }; - } Setups = setups; } diff --git a/Test/Utils/EventUtils.cs b/Test/Utils/EventUtils.cs index 3304b6f1e..a83379ed7 100644 --- a/Test/Utils/EventUtils.cs +++ b/Test/Utils/EventUtils.cs @@ -29,8 +29,10 @@ public static EventExtractionState PopulateEventData(UAExtractor extractor, Base var fields = baseFields.Select(field => new TypeField(new UAVariable(new NodeId(field, 0), field, new QualifiedName(field), null, null, null))); fields = fields.Append(new TypeField(new UAVariable(new NodeId("EUProp", 0), "EUProp", new QualifiedName("EUProp"), null, null, null))); - var type = new UAObjectType(new NodeId("test", 0), "TestEvent", null, null, null); - type.AllCollectedFields = fields.ToHashSet(); + var type = new UAObjectType(new NodeId("test", 0), "TestEvent", null, null, null) + { + AllCollectedFields = fields.ToHashSet() + }; extractor.State.ActiveEvents[new NodeId("test", 0)] = type; return state;