Ejemplo n.º 1
0
        /// <summary>
        /// Processes the model configuration.
        /// </summary>
        /// <param name="uploadQueueItem">The upload queue item.</param>
        /// <param name="dicomFiles">The dicom files.</param>
        /// <param name="queueTransaction">The queue transaction.</param>
        /// <param name="clientConfiguration">The client configuration.</param>
        /// <returns>The waitable task.</returns>
        private async Task ProcessModelConfig(
            IEnumerable <DicomFile> dicomFiles,
            UploadQueueItem uploadQueueItem,
            IQueueTransaction queueTransaction,
            ClientAETConfig clientConfiguration)
        {
            var modelMatchResult = ApplyAETModelConfigProvider.ApplyAETModelConfig(clientConfiguration.Config.ModelsConfig, dicomFiles);

            if (modelMatchResult.Matched)
            {
                var model     = modelMatchResult.Result;
                var queueItem = await StartSegmentationAsync(model.ChannelData, uploadQueueItem, model.ModelId, model.TagReplacements.ToArray(), clientConfiguration).ConfigureAwait(false);

                EnqueueMessage(queueItem, _downloadQueuePath, queueTransaction);
            }
            else
            {
                var failedDicomTags = modelMatchResult.GetDicomConstraintsDicomTags();

                // Log all the tags that did not match
                LogError(LogEntry.Create(AssociationStatus.UploadErrorTagsDoNotMatch,
                                         uploadQueueItem: uploadQueueItem,
                                         failedDicomTags: string.Join(",", failedDicomTags.Select(x => x.DictionaryEntry.Name))),
                         new ProcessorServiceException("Failed to find a model for the received Dicom data."));
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Load T or Ts from a JSON file or folder.
        /// </summary>
        protected void Load()
        {
            if (File.Exists(_settingsFileOrFolderName))
            {
                _ts = null;

                (_t, _) = LoadFile(_settingsFileOrFolderName);
            }
            else if (Directory.Exists(_settingsFileOrFolderName))
            {
                _t = default(T);
                var ts = new List <T>();

                foreach (var file in Directory.EnumerateFiles(_settingsFileOrFolderName, "*.json"))
                {
                    var(t, loaded) = LoadFile(file);
                    if (loaded)
                    {
                        ts.Add(t);
                    }
                }

                _ts = ts.ToArray();
            }
            else
            {
                var logEntry = LogEntry.Create(ServiceStatus.NewConfigurationError,
                                               string.Format("Settings is neither a file nor a folder: {0}", _settingsFileOrFolderName));
                logEntry.Log(_logger, LogLevel.Error);
            }
        }
        /// <summary>
        /// Entry point for the worker thread. This invokes the update method and pauses depending on the defined interval.
        /// </summary>
        /// <param name="cancellationToken">The cancellation token.</param>
        private void Execute(CancellationToken cancellationToken)
        {
            // Main execution loop - if we encounter an exception during start-up, this will be false
            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    OnUpdateTickAsync(cancellationToken).Wait(cancellationToken);
                }
                catch (OperationCanceledException e)
                {
                    if (!cancellationToken.IsCancellationRequested)
                    {
                        // If we got this error when the cancellation token has not been set, this needs to be logged.
                        // Otherwise, the service is shutting down normally and the wait has thrown an operation canceled exception.
                        LogError(LogEntry.Create(ServiceStatus.ExecuteError), e);
                    }
                }
#pragma warning disable CA1031 // Do not catch general exception types
                catch (Exception e)
#pragma warning restore CA1031 // Do not catch general exception types
                {
                    LogError(LogEntry.Create(ServiceStatus.ExecuteError), e);
                }
            }
        }
        /// <summary>
        /// Load T from a JSON file.
        /// </summary>
        /// <param name="path">Path to file.</param>
        /// <returns>New <see cref="LoadJsonResult"/>.</returns>
        private LoadJsonResult LoadFile(string path)
        {
            try
            {
                var jsonText = File.ReadAllText(path);

                return(new LoadJsonResult(true, true, JsonConvert.DeserializeObject <T>(jsonText)));
            }
            catch (JsonSerializationException e)
            {
                var logEntry = LogEntry.Create(ServiceStatus.NewConfigurationError,
                                               string.Format(CultureInfo.InvariantCulture, "Unable to parse settings file {0}", path));
                logEntry.Log(_logger, LogLevel.Error, e);

                return(new LoadJsonResult(true, false, default(T)));
            }
            catch (IOException e)
            {
                var logEntry = LogEntry.Create(ServiceStatus.NewConfigurationError,
                                               string.Format(CultureInfo.InvariantCulture, "Unable to load settings file {0}", path));
                logEntry.Log(_logger, LogLevel.Error, e);

                return(new LoadJsonResult(false, false, default(T)));
            }
        }
        /// <summary>
        /// Begins the message queue transaction.
        /// MessageQueueTransaction.Begin() can throw exceptions. This method wraps the retry logic.
        /// </summary>
        /// <param name="queueTransaction">The queue transaction.</param>
        /// <param name="retrySeconds">The time delay between every retry.</param>
        /// <param name="maximumRetry">The maximum number of retries.</param>
        /// <exception cref="InvalidOperationException">If the transaction has already been started.</exception>
        /// <exception cref="MessageQueueTransactionBeginException">If we failed to start a transaction after retrying.</exception>
        protected void BeginMessageQueueTransaction(IQueueTransaction queueTransaction, int retrySeconds = 30, int maximumRetry = 120)
        {
            if (queueTransaction == null)
            {
                throw new ArgumentNullException(nameof(queueTransaction), "The queue transaction is null.");
            }

            try
            {
                queueTransaction.Begin();
                return;
            }
            catch (MessageQueueTransactionBeginException e)
            {
                LogError(LogEntry.Create(MessageQueueStatus.BeginTransactionError),
                         e);

                // Throw if we reach the retry limit or cancellation has been requested (service stop)
                if (maximumRetry <= 0 || _cancellationTokenSource.IsCancellationRequested)
                {
                    throw;
                }
            }

            // Delay before retrying
            _cancellationTokenSource.Token.WaitHandle.WaitOne(TimeSpan.FromSeconds(retrySeconds));

            BeginMessageQueueTransaction(queueTransaction, retrySeconds, maximumRetry - 1);
        }
        /// <summary>
        /// Gets a message queue or throws an exception.
        /// </summary>
        /// <param name="messageQueuePath">The message queue path.</param>
        /// <returns>The message queue.</returns>
        /// <exception cref="Exception">If any exception occured when getting the message queue.</exception>
        protected IMessageQueue GetMessageQueue(string messageQueuePath)
        {
            if (!_messageQueues.ContainsKey(messageQueuePath))
            {
                try
                {
                    var messageQueue = GatewayMessageQueue.Get(messageQueuePath);

                    LogInformation(LogEntry.Create(MessageQueueStatus.InitialisedQueue,
                                                   sourceMessageQueuePath: messageQueuePath));

                    _messageQueues[messageQueuePath] = messageQueue;
                }
                catch (Exception e)
                {
                    LogError(LogEntry.Create(MessageQueueStatus.InitialiseQueueError,
                                             sourceMessageQueuePath: messageQueuePath),
                             e);

                    throw;
                }
            }

            return(_messageQueues[messageQueuePath]);
        }
        /// <summary>
        /// Disposes of all managed resources.
        /// </summary>
        /// <param name="disposing">If we are disposing.</param>
        protected virtual void Dispose(bool disposing)
        {
            if (_isDisposed || !disposing)
            {
                return;
            }

            OnStop();

            if (_cancellationTokenSource != null)
            {
                _cancellationTokenSource.Dispose();
                _cancellationTokenSource = null;
            }

            foreach (var queue in _messageQueues)
            {
                try
                {
                    queue.Value.Dispose();
                }
#pragma warning disable CA1031 // Do not catch general exception types
                catch (Exception e)
#pragma warning restore CA1031 // Do not catch general exception types
                {
                    LogError(LogEntry.Create(MessageQueueStatus.DisposeError,
                                             sourceMessageQueuePath: queue.Value.QueuePath),
                             e);
                }
            }

            _messageQueues.Clear();

            _isDisposed = true;
        }
        /// <summary>
        /// Enqueues the message onto the message queue.
        /// Note: This method will not commit or abort the queue transaction.
        /// </summary>
        /// <typeparam name="TMessageType">The enqueue message type.</typeparam>
        /// <param name="message">The message to enqueue.</param>
        /// <param name="messageQueuePath">The queue path to enqueue the message onto.</param>
        /// <param name="queueTransaction">The queue transaction.</param>
        /// <exception cref="ArgumentException">If the queue path is not correct.</exception>
        /// <exception cref="MessageQueuePermissionsException">If we do not have permissions to write to the message queue.</exception>
        /// <exception cref="MessageQueueWriteException">If the message queue could not write to the queue.</exception>
        protected void EnqueueMessage <TMessageType>(
            TMessageType message,
            string messageQueuePath,
            IQueueTransaction queueTransaction) where TMessageType : QueueItemBase
        {
            try
            {
                GetMessageQueue(messageQueuePath).Enqueue(message, queueTransaction);

                LogInformation(LogEntry.Create(MessageQueueStatus.Enqueued,
                                               queueItemBase: message,
                                               sourceMessageQueuePath: messageQueuePath));
            }
            catch (MessageQueuePermissionsException e)
            {
                LogError(LogEntry.Create(MessageQueueStatus.EnqueueError,
                                         queueItemBase: message,
                                         sourceMessageQueuePath: messageQueuePath),
                         e);

                // We cannot recover from access violations. We should stop the service.
                StopServiceAsync();

                throw;
            }
        }
        /// <summary>
        /// Disposes of all managed resources.
        /// </summary>
        /// <param name="disposing">If we are disposing.</param>
        protected virtual void Dispose(bool disposing)
        {
            if (_isDisposed || !disposing)
            {
                return;
            }

            OnStop();

            if (_cancellationTokenSource != null)
            {
                _cancellationTokenSource.Dispose();
                _cancellationTokenSource = null;
            }

            foreach (var queue in _messageQueues)
            {
                try
                {
                    queue.Value.Dispose();
                }
                catch (Exception e)
                {
                    LogError(LogEntry.Create(MessageQueueStatus.DisposeError,
                                             sourceMessageQueuePath: queue.Value.QueuePath),
                             e);
                }
            }

            _messageQueues.Clear();

            _isDisposed = true;
        }
        /// <summary>
        /// Starts the service.
        /// </summary>
        public void Start()
        {
            _cancellationTokenSource = new CancellationTokenSource();

            try
            {
                LogInformation(LogEntry.Create(ServiceStatus.Starting));

                // Start the service
                OnServiceStart();

                // Note: We should only start-up the worker task and return. We should not execute any long running operations here.
                for (var i = 0; i < _executionTasks.Length; i++)
                {
                    _executionTasks[i] = Task.Run(() => Execute(_cancellationTokenSource.Token), _cancellationTokenSource.Token);
                    _startCount++;
                }

                _isRunning = true;

                LogInformation(LogEntry.Create(ServiceStatus.Started));
            }
#pragma warning disable CA1031 // Do not catch general exception types
            catch (Exception e)
#pragma warning restore CA1031 // Do not catch general exception types
            {
                LogError(LogEntry.Create(ServiceStatus.StartError), e);

                // Stop the service on any start-up failure
                StopServiceAsync();
            }
        }
        /// <summary>
        /// Called when the service is stopping.
        /// </summary>
        public void OnStop()
        {
            LogInformation(LogEntry.Create(ServiceStatus.Stopping));

            try
            {
                _cancellationTokenSource?.Cancel();
            }
            catch (Exception e)
            {
                LogError(LogEntry.Create(ServiceStatus.StoppingError,
                                         information: "Cancellation token source cancel exception."),
                         e);
            }

            try
            {
                // Will only wait 10 seconds for all tasks to finish nicely
                Task.WaitAll(_executionTasks.Where(x => x != null).ToArray(), TimeSpan.FromSeconds(10));
            }
            catch (Exception e)
            {
                LogError(LogEntry.Create(ServiceStatus.StoppingError,
                                         information: "Unknown exception waiting for all execution tasks to end."),
                         e);
            }

            OnServiceStop();

            _isRunning = false;

            LogInformation(LogEntry.Create(ServiceStatus.Stopped));
        }
        protected void HandleExceptionForTransaction(T queueItem, IQueueTransaction queueTransaction, Action oldQueueItemAction = null)
        {
            if (queueTransaction == null)
            {
                throw new ArgumentNullException(nameof(queueTransaction), "The queue transaction is null.");
            }

            // The queue item is null, commit the transaction.
            if (queueItem == null)
            {
                oldQueueItemAction?.Invoke();
                queueTransaction.Commit();

                return;
            }

            try
            {
                var isMessageOld = DateTime.UtcNow - queueItem.AssociationDateTime > _dequeueServiceConfig.MaximumQueueMessageAge;

                // If the item is not null and we haven't dequeued too many times, add to the queue at the back
                if (queueItem.DequeueCount < DequeueServiceConfig.MaxDequeueCount && !isMessageOld)
                {
                    EnqueueMessage(queueItem, _dequeueQueuePath, queueTransaction);
                }
                // Enqueue onto the dead letter queue if the message isn't old
                else if (!isMessageOld)
                {
                    EnqueueMessage(queueItem, _deadLetterQueuePath, queueTransaction);

                    LogInformation(LogEntry.Create(MessageQueueStatus.EnqueuedDeadLetter,
                                                   queueItemBase: queueItem,
                                                   sourceMessageQueuePath: _deadLetterQueuePath));
                }
                // Remove from all queues if the dequeue count has been reached and the message is old. Invoke any clean-up
                // tasks in the action.
                else
                {
                    // Make sure this is called before commiting the transaction. This will most likely use the transaction
                    // to enqueue to the delete service queue.
                    oldQueueItemAction?.Invoke();

                    LogError(LogEntry.Create(MessageQueueStatus.TooOldForDeadLetterError,
                                             queueItemBase: queueItem,
                                             sourceMessageQueuePath: _dequeueQueuePath),
                             new Exception("Message dequeued too many times. Remove from all queues."));
                }

                queueTransaction.Commit();
            }
            catch (Exception e)
            {
                LogError(LogEntry.Create(MessageQueueStatus.TransactionExceptionHandlerError,
                                         queueItemBase: queueItem,
                                         sourceMessageQueuePath: _dequeueQueuePath),
                         e);

                queueTransaction.Abort();
            }
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Uploads the files.
        /// </summary>
        /// <param name="dicomFiles">The dicom files.</param>
        /// <param name="uploadQueueItem">The upload queue item.</param>
        /// <param name="queueTransaction">The queue transaction.</param>
        /// <returns>The async task.</returns>
        private async Task ProcessUploadQueueItem(UploadQueueItem uploadQueueItem, IQueueTransaction queueTransaction)
        {
            var clientConfiguration = ApplyAETModelConfigProvider.GetAETConfigs(
                _aetConfigModels,
                uploadQueueItem.CalledApplicationEntityTitle,
                uploadQueueItem.CallingApplicationEntityTitle);

            LogTrace(LogEntry.Create(AssociationStatus.UploadProcessQueueItem));

            switch (clientConfiguration.Config.AETConfigType)
            {
            // ML Model or ML Model with Dry Run Result
            case AETConfigType.Model:
            case AETConfigType.ModelWithResultDryRun:
                // Load all DICOM files in the received folder.
                var dicomFiles = ReadDicomFiles(uploadQueueItem.AssociationFolderPath, uploadQueueItem);
                await ProcessModelConfig(dicomFiles, uploadQueueItem, queueTransaction, clientConfiguration).ConfigureAwait(false);

                break;

            // ML Model dry run
            case AETConfigType.ModelDryRun:
                // Anonymize and save the files locally for the dry run using the segmentation anonymisation protocol
                await AnonymiseAndSaveDicomFilesAsync(
                    anonymisationProtocolId : _innerEyeSegmentationClient.SegmentationAnonymisationProtocolId,
                    anonymisationProtocol : _innerEyeSegmentationClient.SegmentationAnonymisationProtocol,
                    uploadQueueItem : uploadQueueItem,
                    aETConfigType : clientConfiguration.Config.AETConfigType).ConfigureAwait(false);

                break;
            }
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Given a set of possible relative paths, find one that is a directory.
        /// </summary>
        /// <param name="relativePaths">List of relative paths to test.</param>
        /// <param name="logger">Logger.</param>
        /// <returns>Full path to existing directory or Empty if none exist.</returns>
        public static string FindRelativeDirectory(IEnumerable <string> relativePaths, ILogger logger)
        {
            relativePaths = relativePaths ?? throw new ArgumentNullException(nameof(relativePaths));

            var parentDirectory = new DirectoryInfo(Assembly.GetExecutingAssembly().Location).Parent.FullName;

            foreach (var relativePath in relativePaths)
            {
                var configurationPath = Path.GetFullPath(Path.Combine(parentDirectory, relativePath));

                if (Directory.Exists(configurationPath))
                {
                    var logEntry = LogEntry.Create(ServiceStatus.Starting,
                                                   string.Format(CultureInfo.InvariantCulture, "Settings location: {0}", configurationPath));
                    logEntry.Log(logger, LogLevel.Information);

                    return(configurationPath);
                }
            }

            var logEntry2 = LogEntry.Create(ServiceStatus.Starting);

            logEntry2.Log(logger, LogLevel.Error, new ConfigurationException("Cannot find configuration directory."));

            return(string.Empty);
        }
        /// <summary>
        /// Moves the queue messages from the source queue to the destination queue.
        /// </summary>
        /// <param name="sourceQueuePath">The source queue path.</param>
        /// <param name="destinationQueuePath">The destination queue path.</param>
        /// <exception cref="ArgumentException">If the queue path is not correct.</exception>
        private void MoveQueueMessages(string sourceQueuePath, string destinationQueuePath)
        {
            // Move messages from the source queue to the destination
            var sourceQueue      = GetMessageQueue(sourceQueuePath);
            var destinationQueue = GetMessageQueue(destinationQueuePath);

            var moreMessages = true;

            // Keep de-queueing until no more messages on the dead letter queue
            while (moreMessages)
            {
                // Create a new transaction for-each move request
                using (var transaction = CreateQueueTransaction(sourceQueuePath))
                {
                    transaction.Begin();

                    try
                    {
                        var message = sourceQueue.DequeueNextMessage <T>(transaction);

                        LogInformation(LogEntry.Create(MessageQueueStatus.Moved,
                                                       queueItemBase: message,
                                                       destinationMessageQueuePath: destinationQueuePath,
                                                       sourceMessageQueuePath: sourceQueuePath));

                        destinationQueue.Enqueue(message, transaction);
                        transaction.Commit();
                    }
                    catch (MessageQueueReadException)
                    {
                        // No more messages
                        moreMessages = false;
                        transaction.Commit();
                    }
                    catch (MessageQueueWriteException e)
                    {
                        LogError(LogEntry.Create(MessageQueueStatus.MoveError,
                                                 information: "Failed to wite a message from the dead letter queue to origin queue",
                                                 destinationMessageQueuePath: destinationQueuePath,
                                                 sourceMessageQueuePath: sourceQueuePath),
                                 e);
                        // Abort on a write exception
                        transaction.Abort();
                    }
#pragma warning disable CA1031 // Do not catch general exception types
                    catch (Exception e)
#pragma warning restore CA1031 // Do not catch general exception types
                    {
                        LogError(LogEntry.Create(MessageQueueStatus.MoveError,
                                                 information: "Failed to dequeue a message from the dead letter queue",
                                                 destinationMessageQueuePath: destinationQueuePath,
                                                 sourceMessageQueuePath: sourceQueuePath),
                                 e);

                        transaction.Commit();
                    }
                }
            }
        }
Ejemplo n.º 16
0
        /// <summary>
        /// receive unity log message. see
        /// <see cref="UnityEngine.Application.logMessageReceived"/>
        /// </summary>
        /// <param name="logString"></param>
        /// <param name="stackTrace"></param>
        /// <param name="logType"></param>
        private void Application_logMessageReceived(string logString, string stackTrace, UnityEngine.LogType logType)
        {
            var entry = LogEntry.Create(logString, stackTrace, logType);

            lock (m_LogQueueLock)
            {
                m_LogQueue.Enqueue(entry);
            }
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Called when [update tick] is called. This will wait for all work to execute then will pause for desired interval delay.
        /// </summary>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>
        /// The async task.
        /// </returns>
        protected override async Task OnUpdateTickAsync(CancellationToken cancellationToken)
        {
            using (var transaction = CreateQueueTransaction())
            {
                BeginMessageQueueTransaction(transaction);

                UploadQueueItem queueItem = null;

                try
                {
                    queueItem = await DequeueNextMessageAsync(transaction, cancellationToken).ConfigureAwait(false);

                    // If the directory does not exist we cannot process this queue item.
                    // Lets log but remove this queue item.
                    if (Directory.Exists(queueItem.AssociationFolderPath))
                    {
                        await ProcessUploadQueueItem(queueItem, transaction).ConfigureAwait(false);

                        // Enqueue the message to delete the association folder
                        CleanUp(queueItem, transaction);
                    }
                    else
                    {
                        LogError(LogEntry.Create(AssociationStatus.UploadErrorAssocationFolderDeleted, uploadQueueItem: queueItem),
                                 new ProcessorServiceException("The association folder has been deleted."));
                    }

                    transaction.Commit();
                }
                catch (MessageQueueReadException)
                {
                    // We timed out trying to de-queue (no items on the queue).
                    // This exception doesn't need to be logged.
                    transaction.Abort();
                }
                catch (OperationCanceledException)
                {
                    // Throw operation canceled exceptions up to the worker thread. It will handle
                    // logging correctly.
                    transaction.Abort();
                    throw;
                }
#pragma warning disable CA1031 // Do not catch general exception types
                catch (Exception e)
#pragma warning restore CA1031 // Do not catch general exception types
                {
                    LogError(LogEntry.Create(AssociationStatus.UploadError, uploadQueueItem: queueItem),
                             e);

                    HandleExceptionForTransaction(
                        queueItem: queueItem,
                        queueTransaction: transaction,
                        oldQueueItemAction: () => CleanUp(queueItem, transaction));
                }
            }
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Gets the segmentation result.
        /// </summary>
        /// <param name="downloadQueueItem">The download queue item.</param>
        /// <param name="retryDelay">The delay between getting segmentation progress.</param>
        /// <param name="timeout">The maximum time we will wait for a segmentation result.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>The segmentation result Dicom file or null.</returns>
        private async Task <DicomFile> GetSegmentationResultAsync(DownloadQueueItem downloadQueueItem, TimeSpan retryDelay, TimeSpan timeout, CancellationToken cancellationToken)
        {
            var referenceDicomFiles = OpenDicomFiles(downloadQueueItem.ReferenceDicomFiles);

            // Attempting to download result
            LogInformation(LogEntry.Create(AssociationStatus.Downloading,
                                           downloadQueueItem: downloadQueueItem,
                                           downloadProgress: 0,
                                           downloadError: string.Empty));

            var tagReplacements = JsonConvert.DeserializeObject <IEnumerable <TagReplacement> >(downloadQueueItem.TagReplacementJsonString);

            // Create a new token for the maximum time we will sit and wait for a result.
            // Note: We need to check both the passed cancellation token and this new token for cancellation requests
            using (var cancellationTokenSource = new CancellationTokenSource(timeout))
            {
                while (!cancellationTokenSource.IsCancellationRequested && !cancellationToken.IsCancellationRequested)
                {
                    var modelResult = await _innerEyeSegmentationClient.SegmentationResultAsync(
                        modelId : downloadQueueItem.ModelId,
                        segmentationId : downloadQueueItem.SegmentationID,
                        referenceDicomFiles : referenceDicomFiles,
                        userReplacements : tagReplacements);

                    if (modelResult.Progress == 100 && modelResult.DicomResult != null)
                    {
                        return(modelResult.DicomResult);
                    }
                    else if (!string.IsNullOrEmpty(modelResult.Error))
                    {
                        LogError(LogEntry.Create(AssociationStatus.Downloading,
                                                 downloadQueueItem: downloadQueueItem,
                                                 downloadProgress: modelResult.Progress,
                                                 downloadError: modelResult.Error),
                                 new Exception("Failed to get a segmentation result."));

                        // We cannot recover from this error, so we log and continue.
                        return(null);
                    }
                    else
                    {
                        LogInformation(LogEntry.Create(AssociationStatus.Downloading,
                                                       downloadQueueItem: downloadQueueItem,
                                                       downloadProgress: modelResult.Progress,
                                                       downloadError: modelResult.Error));
                    }

                    // Make sure you pass the cancellation token, not the timeout token, so the service can stop timely
                    await Task.Delay(retryDelay, cancellationToken);
                }
            }

            return(null);
        }
Ejemplo n.º 19
0
        protected List <LogEntry> CreateLogEntries(IEnumerable <JObject> jObjects)
        {
            var logEntries = new List <LogEntry>();

            foreach (var jObject in jObjects)
            {
                if (string.Equals(_type, jObject.Value <string>("type"), StringComparison.Ordinal))
                {
                    logEntries.Add(LogEntry.Create(jObject));
                }
            }

            return(logEntries);
        }
        /// <summary>
        /// Load T from a JSON file or folder.
        /// </summary>
        /// <returns>True if new config has been loaded, false otherwise.</returns>
        private bool Load()
        {
            if (File.Exists(_settingsFileOrFolderName))
            {
                var loadJsonResult = LoadFile(_settingsFileOrFolderName);

                if (!loadJsonResult.Loaded || !loadJsonResult.Parsed)
                {
                    return(false);
                }

                Config = loadJsonResult.Result;

                return(true);
            }
            else if (Directory.Exists(_settingsFileOrFolderName))
            {
                var ts = new List <T>();

                foreach (var file in Directory.EnumerateFiles(_settingsFileOrFolderName, "*.json"))
                {
                    var loadJsonResult = LoadFile(file);
                    if (!loadJsonResult.Loaded)
                    {
                        // File still in use, FileWatcher has reported file changed but
                        // the other process has not finished yet.
                        return(false);
                    }

                    if (loadJsonResult.Parsed)
                    {
                        ts.Add(loadJsonResult.Result);
                    }
                }

                Config = _flatMap(ts);

                return(true);
            }
            else
            {
                var logEntry = LogEntry.Create(ServiceStatus.NewConfigurationError,
                                               string.Format(CultureInfo.InvariantCulture, "Settings is neither a file nor a folder: {0}", _settingsFileOrFolderName));
                logEntry.Log(_logger, LogLevel.Error);

                return(false);
            }
        }
Ejemplo n.º 21
0
        /// <summary>
        /// Called when [update tick] is called. This will wait for all work to execute then will pause for desired interval delay.
        /// </summary>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>
        /// The async task.
        /// </returns>
        protected override async Task OnUpdateTickAsync(CancellationToken cancellationToken)
        {
            using (var transaction = CreateQueueTransaction())
            {
                BeginMessageQueueTransaction(transaction);

                DeleteQueueItem deleteQueueItem = null;

                try
                {
                    deleteQueueItem = await DequeueNextMessageAsync(transaction, cancellationToken).ConfigureAwait(false);

                    // Delete every path in the queue item. Each path could be a directory or a file.
                    foreach (var path in deleteQueueItem.Paths)
                    {
                        DeletePath(path);
                    }

                    LogInformation(LogEntry.Create(AssociationStatus.Deleted,
                                                   deleteQueueItem: deleteQueueItem));

                    transaction.Commit();
                }
                catch (MessageQueueReadException)
                {
                    // We timed out trying to de-queue (no items on the queue).
                    // This exception doesn't need to be logged.
                    transaction.Abort();
                }
                catch (OperationCanceledException)
                {
                    // Throw operation canceled exceptions up to the worker thread. It will handle
                    // logging correctly.
                    transaction.Abort();
                    throw;
                }
#pragma warning disable CA1031 // Do not catch general exception types
                catch (Exception e)
#pragma warning restore CA1031 // Do not catch general exception types
                {
                    LogError(LogEntry.Create(AssociationStatus.DeleteError,
                                             deleteQueueItem: deleteQueueItem),
                             e);
                    HandleExceptionForTransaction(deleteQueueItem, transaction);
                }
            }
        }
        /// <summary>
        /// Create a new <see cref="IInnerEyeSegmentationClient"/> based on settings in JSON file.
        /// </summary>
        /// <param name="logger">Optional logger for client.</param>
        /// <returns>New <see cref="IInnerEyeSegmentationClient"/>.</returns>
        public Func <IInnerEyeSegmentationClient> CreateInnerEyeSegmentationClient(ILogger logger = null) =>
        () =>
        {
            var processorSettings = ProcessorSettings();

            var licenseKey = processorSettings.LicenseKey;

            if (string.IsNullOrEmpty(licenseKey))
            {
                var message = string.Format(CultureInfo.InvariantCulture, "License key for the service `{0}` has not been set correctly in environment variable `{1}`. It needs to be a system variable.",
                                            processorSettings.InferenceUri, processorSettings.LicenseKeyEnvVar);
                var logEntry = LogEntry.Create(ServiceStatus.Starting);
                logEntry.Log(logger, LogLevel.Error, new ConfigurationException(message));
            }

            return(new InnerEyeSegmentationClient(processorSettings.InferenceUri, licenseKey));
        };
Ejemplo n.º 23
0
        /// <summary>
        /// Load T from a JSON file.
        /// </summary>
        /// <param name="path">Path to file.</param>
        /// <returns>Pair of T and true if file loaded correctly, false otherwise.</returns>
        private (T, bool) LoadFile(string path)
        {
            try
            {
                var jsonText = File.ReadAllText(path);

                return(JsonConvert.DeserializeObject <T>(jsonText), true);
            }
            catch (Exception e)
            {
                var logEntry = LogEntry.Create(ServiceStatus.NewConfigurationError,
                                               string.Format("Unable to load settings file {0}", path));
                logEntry.Log(_logger, LogLevel.Error, e);

                return(default(T), false);
            }
        }
Ejemplo n.º 24
0
        public TestLogService()
        {
            _logEntries = new List <LogEntry>();

            using (StreamReader reader = new StreamReader("..\\..\\sampleMessages.txt"))
            {
                int index = 0;
                while (!reader.EndOfStream)
                {
                    var line     = reader.ReadLine();
                    var logEntry = LogEntry.Create(false, index++, DateTime.Now);
                    logEntry.Message = line;

                    _logEntries.Add(logEntry);
                }
            }
        }
Ejemplo n.º 25
0
 public void RecordLog(PacketObject rPacket, bool rStack, int rFrame)
 {
     lock (logQueue)
     {
         StackTrace st = null;
         if (rStack)
         {
             st = new StackTrace(false);
         }
         if (m_useThread)
         {
             logQueue.Enqueue(LogEntry.Create(rPacket, rFrame, st));
         }
         else
         {
             gameLogger.Log(rPacket, rFrame, st);
         }
     }
 }
        /// <summary>
        /// File watcher Changed event handler. Filter the events, reload the config and if successful invoke ConfigChanged.
        /// </summary>
        /// <param name="sender">Sender.</param>
        /// <param name="e">File system event args.</param>
        private void OnChanged(object sender, FileSystemEventArgs e)
        {
            if (e.ChangeType != WatcherChangeTypes.Changed)
            {
                return;
            }

            var logEntry = LogEntry.Create(ServiceStatus.NewConfigurationDetetected,
                                           string.Format(CultureInfo.InvariantCulture, "Settings have changed: {0}", e.FullPath));

            logEntry.Log(_logger, LogLevel.Information);

            if (!Load())
            {
                return;
            }

            ConfigChanged?.Invoke(this, new EventArgs());
        }
        /// <summary>
        /// Dequeues the next message from the queue.
        /// Note: This method will not commit or abort the queue transaction.
        /// </summary>
        /// <param name="queueTransaction">The queue transaction.</param>
        /// <param name="cancellationToken">The cancellation token.</param>
        /// <returns>The de-queued object.</returns>
        /// <exception cref="ArgumentException">If the queue path is not correct.</exception>
        /// <exception cref="MessageQueueReadException">The queue timed out when reading.</exception>
        /// <exception cref="MessageQueuePermissionsException">The queue does not have permissions to read.</exception>
        protected async Task <T> DequeueNextMessageAsync(
            IQueueTransaction queueTransaction,
            CancellationToken cancellationToken)
        {
            // Check if we should move all the dead letter messages on every dequeue.
            CheckMoveDeadLetterMessages();

            try
            {
                // Note: We do not put the message queue in a using block. The service manages the lifecycle
                // of message queues.
                var messageItem = GetMessageQueue(_dequeueQueuePath)
                                  .DequeueNextMessage <T>(queueTransaction);

                // Increase the count on the message.
                // Note: We should not check if the maximum dequeue count has been reached here. We should do that on handling exceptions.
                messageItem.DequeueCount++;

                LogInformation(LogEntry.Create(MessageQueueStatus.Dequeued,
                                               queueItemBase: messageItem,
                                               sourceMessageQueuePath: _dequeueQueuePath));

                return(messageItem);
            }
            catch (MessageQueueReadException)
            {
                // Delay here before throw the exception up the next level to delay message queue reads.
                await Task.Delay(DequeueServiceConfig.DequeueTimeout, cancellationToken);

                throw;
            }
            catch (MessageQueuePermissionsException e)
            {
                LogError(LogEntry.Create(MessageQueueStatus.DequeueError, sourceMessageQueuePath: _dequeueQueuePath),
                         e);

                // We cannot recover from access violations. We should stop the service.
                StopServiceAsync();

                throw;
            }
        }
        /// <summary>
        /// Enqueues the message using its own message queue transaction.
        /// </summary>
        /// <typeparam name="MessageType">The enqueue message type.</typeparam>
        /// <param name="message">The message to enqueue.</param>
        /// <param name="messageQueuePath">The queue path to enqueue the message onto.</param>
        protected void EnqueueMessage <TMessageType>(TMessageType message, string messageQueuePath) where TMessageType : QueueItemBase
        {
            using (var transaction = CreateQueueTransaction(messageQueuePath))
            {
                BeginMessageQueueTransaction(transaction);

                try
                {
                    EnqueueMessage(message, messageQueuePath, transaction);
                    transaction.Commit();
                }
                catch (Exception e)
                {
                    LogError(LogEntry.Create(AssociationStatus.BaseEnqueueMessageError,
                                             queueItemBase: message),
                             e);
                    transaction.Abort();
                }
            }
        }
Ejemplo n.º 29
0
        /// <summary>
        /// Pings the segmentation client and stops the service on authentication exceptions.
        /// </summary>
        /// <param name="stopServiceOnAuthFailures">Will stop the service on any authentication failures.</param>
        /// <exception cref="AuthenticationException">If the license key is incorrect for the segmentation client.</exception>
        private async Task PingAsync(bool stopServiceOnAuthFailures = true)
        {
            try
            {
                if (_innerEyeSegmentationClient != null)
                {
                    await _innerEyeSegmentationClient.PingAsync().ConfigureAwait(false);
                }
            }
            catch (AuthenticationException e)
            {
                LogError(LogEntry.Create(ServiceStatus.PingError), e);

                if (stopServiceOnAuthFailures)
                {
                    StopServiceAsync();
                }

                throw;
            }
        }
Ejemplo n.º 30
0
        /// <summary>
        /// Gets the accepted SOP classes and transfer syntaxes.
        /// </summary>
        /// <returns>The accepted SOP classes and transfer syntaxes.</returns>
        private IReadOnlyDictionary <DicomUID, DicomTransferSyntax[]> GetAcceptedSopClassesAndTransferSyntaxes()
        {
            try
            {
                var gatewayReceiveConfig = _getReceiveServiceConfig();

                if (gatewayReceiveConfig != null)
                {
                    _receiveServiceConfig = gatewayReceiveConfig;
                }
            }
            // We catch all exceptions and return the latest cached result on error. We do not want to stop accepting data
            // just because we cannot communicate with our API. We should stop processing further down the chain.
            catch (Exception e)
            {
                LogError(LogEntry.Create(ServiceStatus.GetAcceptedSopClassesAndTransferSyntaxesError),
                         e);
            }

            return(_receiveServiceConfig.AcceptedSopClassesAndTransferSyntaxes);
        }