/// <summary> /// Method that runs asynchronously to connect to event hub and check /// a) if all expected value changes are delivered /// b) that time between value changes is expected /// </summary> /// <param name="token">Token to cancel the operation</param> /// <returns>Task that run until token is canceled</returns> public async Task <StartResult> StartAsync(ValidatorConfiguration configuration) { if (_cancellationTokenSource != null) { return(new StartResult()); } if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); } if (configuration.ExpectedValueChangesPerTimestamp < 0) { throw new ArgumentNullException("Invalid configuration detected, expected value changes per timestamp can't be lower than zero"); } if (configuration.ExpectedIntervalOfValueChanges < 0) { throw new ArgumentNullException("Invalid configuration detected, expected interval of value changes can't be lower than zero"); } if (configuration.ExpectedMaximalDuration < 0) { throw new ArgumentNullException("Invalid configuration detected, maximal total duration can't be lower than zero"); } if (configuration.ThresholdValue <= 0) { throw new ArgumentNullException("Invalid configuration detected, threshold can't be negative or zero"); } if (string.IsNullOrWhiteSpace(configuration.IoTHubEventHubEndpointConnectionString)) { throw new ArgumentNullException(nameof(configuration.IoTHubEventHubEndpointConnectionString)); } if (string.IsNullOrWhiteSpace(configuration.StorageConnectionString)) { throw new ArgumentNullException(nameof(configuration.StorageConnectionString)); } if (string.IsNullOrWhiteSpace(configuration.BlobContainerName)) { throw new ArgumentNullException(nameof(configuration.BlobContainerName)); } if (string.IsNullOrWhiteSpace(configuration.EventHubConsumerGroup)) { throw new ArgumentNullException(nameof(configuration.EventHubConsumerGroup)); } if (configuration.ExpectedMaximalDuration == 0) { configuration.ExpectedMaximalDuration = uint.MaxValue; } Interlocked.Exchange(ref _shuttingDown, 0); _currentConfiguration = configuration; _valueChangesPerTimestamp = new ConcurrentDictionary <DateTime, int>(4, 500); _valueChangesPerNodeId = new ConcurrentDictionary <string, int>(4, 500); _iotHubMessageEnqueuedTimes = new ConcurrentDictionary <DateTime, DateTime>(4, 500); _observedTimestamps = new ConcurrentQueue <DateTime>(); Interlocked.Exchange(ref _totalValueChangesCount, 0); _cancellationTokenSource = new CancellationTokenSource(); var token = _cancellationTokenSource.Token; token.ThrowIfCancellationRequested(); _logger.LogInformation("Connecting to blob storage..."); var blobContainerClient = new BlobContainerClient(configuration.StorageConnectionString, configuration.BlobContainerName); _logger.LogInformation("Connecting to IoT Hub..."); _client = new EventProcessorClient(blobContainerClient, configuration.EventHubConsumerGroup, configuration.IoTHubEventHubEndpointConnectionString); _client.PartitionInitializingAsync += Client_PartitionInitializingAsync; _client.ProcessEventAsync += Client_ProcessEventAsync; _client.ProcessErrorAsync += Client_ProcessErrorAsync; _logger.LogInformation("Starting monitoring of events..."); await _client.StartProcessingAsync(token); _startTime = DateTime.UtcNow; CheckForMissingValueChangesAsync(token).Start(); CheckForMissingTimestampsAsync(token).Start(); return(new StartResult()); }
/// <summary> /// Method that runs asynchronously to connect to event hub and check /// a) if all expected value changes are delivered /// b) that time between value changes is expected /// </summary> /// <param name="token">Token to cancel the operation</param> /// <returns>Task that run until token is canceled</returns> public async Task <StartResult> StartAsync(ValidatorConfiguration configuration) { _logger.LogInformation("StartAsync called."); var sw = Stopwatch.StartNew(); try { // Check if already started. if (_cancellationTokenSource != null) { return(new StartResult()); } // Check provided configuration. if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); } if (configuration.ExpectedValueChangesPerTimestamp < 0) { throw new ArgumentNullException("Invalid configuration detected, expected value changes per timestamp can't be lower than zero"); } if (configuration.ExpectedIntervalOfValueChanges < 0) { throw new ArgumentNullException("Invalid configuration detected, expected interval of value changes can't be lower than zero"); } if (configuration.ExpectedMaximalDuration < 0) { throw new ArgumentNullException("Invalid configuration detected, maximal total duration can't be lower than zero"); } if (configuration.ThresholdValue <= 0) { throw new ArgumentNullException("Invalid configuration detected, threshold can't be negative or zero"); } if (string.IsNullOrWhiteSpace(configuration.IoTHubEventHubEndpointConnectionString)) { throw new ArgumentNullException(nameof(configuration.IoTHubEventHubEndpointConnectionString)); } if (string.IsNullOrWhiteSpace(configuration.StorageConnectionString)) { throw new ArgumentNullException(nameof(configuration.StorageConnectionString)); } if (string.IsNullOrWhiteSpace(configuration.BlobContainerName)) { throw new ArgumentNullException(nameof(configuration.BlobContainerName)); } if (string.IsNullOrWhiteSpace(configuration.EventHubConsumerGroup)) { throw new ArgumentNullException(nameof(configuration.EventHubConsumerGroup)); } if (configuration.ExpectedMaximalDuration == 0) { configuration.ExpectedMaximalDuration = uint.MaxValue; } _currentConfiguration = configuration; Interlocked.Exchange(ref _totalValueChangesCount, 0); _cancellationTokenSource = new CancellationTokenSource(); //// Initialize EventProcessorWrapper if (_clientWrapper == null || _clientWrapper.GetHashCode() != EventProcessorWrapper.GetHashCode(_currentConfiguration)) { _clientWrapper = new EventProcessorWrapper(_currentConfiguration, _logger); await _clientWrapper.InitializeClient(_cancellationTokenSource.Token).ConfigureAwait(false); } _clientWrapper.ProcessEventAsync += Client_ProcessEventAsync; await _clientWrapper.StartProcessingAsync(_cancellationTokenSource.Token).ConfigureAwait(false); _startTime = DateTime.UtcNow; // Initialize checkers. _missingTimestampsChecker = new MissingTimestampsChecker( TimeSpan.FromMilliseconds(_currentConfiguration.ExpectedIntervalOfValueChanges), TimeSpan.FromMilliseconds(_currentConfiguration.ThresholdValue), _logger ); _missingTimestampsChecker.StartAsync( TimeSpan.FromMilliseconds(kCheckerDelayMilliseconds), _cancellationTokenSource.Token ).Start(); _messageProcessingDelayChecker = new MessageProcessingDelayChecker( TimeSpan.FromMilliseconds(_currentConfiguration.ThresholdValue), _logger ); _messageDeliveryDelayChecker = new MessageDeliveryDelayChecker( TimeSpan.FromMilliseconds(_currentConfiguration.ExpectedMaximalDuration), _logger ); _valueChangeCounterPerNodeId = new ValueChangeCounterPerNodeId(_logger); _missingValueChangesChecker = new MissingValueChangesChecker( _currentConfiguration.ExpectedValueChangesPerTimestamp, _logger ); _missingValueChangesChecker.StartAsync( TimeSpan.FromMilliseconds(kCheckerDelayMilliseconds), _cancellationTokenSource.Token ).Start(); _incrementalIntValueChecker = new IncrementalIntValueChecker(_logger); _incrementalSequenceChecker = new SequenceNumberChecker(_logger); _restartAnnouncementReceived = false; return(new StartResult()); } finally { _logger.LogInformation("StartAsync finished in {elapsed}", sw.Elapsed); } }
/// <summary> /// Method that runs asynchronously to connect to event hub and check /// a) if all expected value changes are delivered /// b) that time between value changes is expected /// </summary> /// <param name="token">Token to cancel the operation</param> /// <returns>Task that run until token is canceled</returns> public async Task <StartResult> StartAsync(ValidatorConfiguration configuration) { // Check if already started. if (_cancellationTokenSource != null) { return(new StartResult()); } // Check provided configuration. if (configuration == null) { throw new ArgumentNullException(nameof(configuration)); } if (configuration.ExpectedValueChangesPerTimestamp < 0) { throw new ArgumentNullException("Invalid configuration detected, expected value changes per timestamp can't be lower than zero"); } if (configuration.ExpectedIntervalOfValueChanges < 0) { throw new ArgumentNullException("Invalid configuration detected, expected interval of value changes can't be lower than zero"); } if (configuration.ExpectedMaximalDuration < 0) { throw new ArgumentNullException("Invalid configuration detected, maximal total duration can't be lower than zero"); } if (configuration.ThresholdValue <= 0) { throw new ArgumentNullException("Invalid configuration detected, threshold can't be negative or zero"); } if (string.IsNullOrWhiteSpace(configuration.IoTHubEventHubEndpointConnectionString)) { throw new ArgumentNullException(nameof(configuration.IoTHubEventHubEndpointConnectionString)); } if (string.IsNullOrWhiteSpace(configuration.StorageConnectionString)) { throw new ArgumentNullException(nameof(configuration.StorageConnectionString)); } if (string.IsNullOrWhiteSpace(configuration.BlobContainerName)) { throw new ArgumentNullException(nameof(configuration.BlobContainerName)); } if (string.IsNullOrWhiteSpace(configuration.EventHubConsumerGroup)) { throw new ArgumentNullException(nameof(configuration.EventHubConsumerGroup)); } if (configuration.ExpectedMaximalDuration == 0) { configuration.ExpectedMaximalDuration = uint.MaxValue; } Interlocked.Exchange(ref _shuttingDown, 0); _currentConfiguration = configuration; Interlocked.Exchange(ref _totalValueChangesCount, 0); _cancellationTokenSource = new CancellationTokenSource(); // Initialize EventProcessorClient _logger.LogInformation("Connecting to blob storage..."); var blobContainerClient = new BlobContainerClient(configuration.StorageConnectionString, configuration.BlobContainerName); _logger.LogInformation("Connecting to IoT Hub..."); _client = new EventProcessorClient(blobContainerClient, configuration.EventHubConsumerGroup, configuration.IoTHubEventHubEndpointConnectionString); _client.PartitionInitializingAsync += Client_PartitionInitializingAsync; _client.ProcessEventAsync += Client_ProcessEventAsync; _client.ProcessErrorAsync += Client_ProcessErrorAsync; _logger.LogInformation("Starting monitoring of events..."); await _client.StartProcessingAsync(_cancellationTokenSource.Token); _startTime = DateTime.UtcNow; // Initialize checkers. _missingTimestampsChecker = new MissingTimestampsChecker( TimeSpan.FromMilliseconds(_currentConfiguration.ExpectedIntervalOfValueChanges), TimeSpan.FromMilliseconds(_currentConfiguration.ThresholdValue), _logger ); _missingTimestampsChecker.StartAsync( TimeSpan.FromMilliseconds(kCheckerDelayMilliseconds), _cancellationTokenSource.Token ).Start(); _messageProcessingDelayChecker = new MessageProcessingDelayChecker( TimeSpan.FromMilliseconds(_currentConfiguration.ThresholdValue), _logger ); _messageDeliveryDelayChecker = new MessageDeliveryDelayChecker( TimeSpan.FromMilliseconds(_currentConfiguration.ExpectedMaximalDuration), _logger ); _valueChangeCounterPerNodeId = new ValueChangeCounterPerNodeId(_logger); _missingValueChangesChecker = new MissingValueChangesChecker( _currentConfiguration.ExpectedValueChangesPerTimestamp, _logger ); _missingValueChangesChecker.StartAsync( TimeSpan.FromMilliseconds(kCheckerDelayMilliseconds), _cancellationTokenSource.Token ).Start(); _incrementalIntValueChecker = new IncrementalIntValueChecker(_logger); return(new StartResult()); }