protected override void ProcessMessageImpl(IMessageHeader header, DicomFileMessage message, ulong tag) { DicomDataset dataset; try { dataset = DicomTypeTranslater.DeserializeJsonToDataset(message.DicomDataset); } catch (Exception e) { ErrorAndNack(header, tag, "Could not rebuild DicomDataset from message", e); return; } var toQueue = new QueuedImage(header, tag, message, dataset); lock (_oQueueLock) _imageQueue.Enqueue(toQueue); }
private void RunDleIfRequired() { //if there are a decent number ready to go or we haven't run in a while (and there is at least 1) if (GetQueueCount() < (DateTime.Now.Subtract(_lastRanDle) > _maximumRunDelayInSeconds ? 1 : _minimumBatchSize)) { return; } var toProcess = new List <QueuedImage>(); var duplicates = new List <QueuedImage>(); var seenSoFar = new HashSet <string>(); // Get the messages we will start this DLE with, accounting for duplicates lock (_oQueueLock) { while (_imageQueue.Count > 0) { QueuedImage queuedImage = _imageQueue.Dequeue(); if (seenSoFar.Contains(queuedImage.DicomFileMessage.DicomDataset)) { duplicates.Add(queuedImage); } else { toProcess.Add(queuedImage); seenSoFar.Add(queuedImage.DicomFileMessage.DicomDataset); } } } //All messages were rejected if (!toProcess.Any()) { return; } if (duplicates.Any()) { Logger.Log(LogLevel.Warn, "Acking " + duplicates.Count + " duplicate Datasets"); duplicates.ForEach(x => Ack(x.Header, x.tag)); } var parallelDleHost = new ParallelDLEHost(_repositoryLocator, DatabaseNamer, _useInsertIntoForRawMigration); Logger.Info("Starting DLE with " + toProcess.Count + " messages"); if (RunChecks) { RunDleChecks(); } int remainingRetries = _retryOnFailureCount; Exception firstException = null; ExitCodeType exitCode; var datasetProvider = new DicomFileMessageToDatasetListWorklist(toProcess); do { Logger.Debug("Starting a ParallelDLEHost"); // We last ran now! _lastRanDle = DateTime.Now; //reset the progress e.g. if we crashed later on in the load datasetProvider.ResetProgress(); try { exitCode = parallelDleHost.RunDLE(_lmd, datasetProvider); } catch (Exception e) { Logger.Debug(e, "ParallelDLEHost threw exception of type " + e.GetType()); _dleExceptions.Add(e); exitCode = ExitCodeType.Error; if (remainingRetries > 0) { //wait a random length of time averaging the _retryDelayInSeconds to avoid retrying at the same time as other processes //where there is resource contention that results in simultaneous failures. var r = new Random(); var wait = r.Next(_retryDelayInSeconds * 2); Logger.Info("Sleeping " + wait + "s after failure"); Task.Delay(new TimeSpan(0, 0, 0, wait)).Wait(); if (RunChecks) { Logger.Warn(e, "Running checks before we retry"); RunDleChecks(); } } firstException = firstException ?? e; } }while (remainingRetries-- > 0 && (exitCode == ExitCodeType.Error || exitCode == ExitCodeType.Abort)); Logger.Info("DLE exited with code " + exitCode); switch (exitCode) { case ExitCodeType.Success: case ExitCodeType.OperationNotRequired: { foreach (QueuedImage corrupt in datasetProvider.CorruptMessages) { ErrorAndNack(corrupt.Header, corrupt.tag, "Nacking Corrupt image", null); } QueuedImage[] successes = toProcess.Except(datasetProvider.CorruptMessages).ToArray(); Ack(successes.Select(x => x.Header).ToList(), successes.Select(x => x.tag).Max(x => x)); break; } case ExitCodeType.Error: case ExitCodeType.Abort: { _stopTokenSource.Cancel(); Fatal("DLE Crashed " + (_retryOnFailureCount + 1) + " time(s) on the same batch", firstException); break; } default: { _stopTokenSource.Cancel(); Fatal("No case for DLE exit code " + exitCode, null); break; } } }