/// <summary> /// Starts up service and begins listening with the <see cref="Consumer"/> /// </summary> public override void Start() { FansiImplementations.Load(); IRDMPPlatformRepositoryServiceLocator repositoryLocator = Globals.RDMPOptions.GetRepositoryProvider(); var startup = new Startup(new EnvironmentInfo("netcoreapp2.2"), repositoryLocator); var toMemory = new ToMemoryCheckNotifier(); startup.DoStartup(toMemory); foreach (CheckEventArgs args in toMemory.Messages.Where(m => m.Result == CheckResult.Fail)) { Logger.Log(LogLevel.Warn, args.Ex, args.Message); } _fileMessageProducer = RabbitMqAdapter.SetupProducer(Globals.CohortExtractorOptions.ExtractFilesProducerOptions, isBatch: true); IProducerModel fileMessageInfoProducer = RabbitMqAdapter.SetupProducer(Globals.CohortExtractorOptions.ExtractFilesInfoProducerOptions, isBatch: false); InitializeExtractionSources(repositoryLocator); Consumer = new ExtractionRequestQueueConsumer(Globals.CohortExtractorOptions, _fulfiller, _auditor, _pathResolver, _fileMessageProducer, fileMessageInfoProducer); RabbitMqAdapter.StartConsumer(_consumerOptions, Consumer, isSolo: false); }
public MicroserviceTester(RabbitOptions rabbitOptions, params ConsumerOptions[] peopleYouWantToSendMessagesTo) { CleanUpAfterTest = true; _adapter = new RabbitMqAdapter(rabbitOptions.CreateConnectionFactory(), "TestHost"); Factory = new ConnectionFactory { HostName = rabbitOptions.RabbitMqHostName, Port = rabbitOptions.RabbitMqHostPort, VirtualHost = rabbitOptions.RabbitMqVirtualHost, UserName = rabbitOptions.RabbitMqUserName, Password = rabbitOptions.RabbitMqPassword }; using (var con = Factory.CreateConnection()) using (var model = con.CreateModel()) { //get rid of old exchanges model.ExchangeDelete(rabbitOptions.RabbitMqControlExchangeName); //create a new one model.ExchangeDeclare(rabbitOptions.RabbitMqControlExchangeName, ExchangeType.Topic, true); //setup a sender chanel for each of the consumers you want to test sending messages to foreach (ConsumerOptions consumer in peopleYouWantToSendMessagesTo) { if (!consumer.QueueName.Contains("TEST.")) { consumer.QueueName = consumer.QueueName.Insert(0, "TEST."); } var exchangeName = consumer.QueueName.Replace("Queue", "Exchange"); //terminate any old queues / exchanges model.ExchangeDelete(exchangeName); model.QueueDelete(consumer.QueueName); _declaredExchanges.Add(exchangeName); //Create a binding between the exchange and the queue model.ExchangeDeclare(exchangeName, ExchangeType.Direct, true); //durable seems to be needed because RabbitMQAdapter wants it? model.QueueDeclare(consumer.QueueName, true, false, false); //shared with other users model.QueueBind(consumer.QueueName, exchangeName, ""); _declaredQueues.Add(consumer.QueueName); //Create a producer which can send to the var producerOptions = new ProducerOptions { ExchangeName = exchangeName }; _sendToConsumers.Add(consumer, _adapter.SetupProducer(producerOptions, true)); } } }
public IdentifierMapperHost(GlobalOptions options, ISwapIdentifiers swapper = null) : base(options) { _consumerOptions = options.IdentifierMapperOptions; FansiImplementations.Load(); if (swapper == null) { Logger.Info("Not passed a swapper, creating one of type " + options.IdentifierMapperOptions.SwapperType); _swapper = ObjectFactory.CreateInstance <ISwapIdentifiers>(options.IdentifierMapperOptions.SwapperType, typeof(ISwapIdentifiers).Assembly); } else { _swapper = swapper; } // If we want to use a Redis server to cache answers then wrap the mapper in a Redis caching swapper if (!string.IsNullOrWhiteSpace(options.IdentifierMapperOptions.RedisConnectionString)) { try { _swapper = new RedisSwapper(options.IdentifierMapperOptions.RedisConnectionString, _swapper); } catch (RedisConnectionException e) { // NOTE(rkm 2020-03-30) Log & throw! I hate this, but if we don't log here using NLog, then the exception will bubble-up // and only be printed to STDERR instead of to the log file and may be lost Logger.Error(e, "Could not connect to Redis"); throw; } } _swapper.Setup(_consumerOptions); Logger.Info($"Swapper of type {_swapper.GetType()} created"); // Batching now handled implicitly as backlog demands _producerModel = RabbitMqAdapter.SetupProducer(options.IdentifierMapperOptions.AnonImagesProducerOptions, isBatch: true); Consumer = new IdentifierMapperQueueConsumer(_producerModel, _swapper) { AllowRegexMatching = options.IdentifierMapperOptions.AllowRegexMatching }; // Add our event handler for control messages AddControlHandler(new IdentifierMapperControlMessageHandler(_swapper)); }
public DicomTagReaderHost(GlobalOptions options) : base(options) { if (!Directory.Exists(options.FileSystemOptions.FileSystemRoot)) { throw new ArgumentException("Cannot find the FileSystemRoot specified in the given MicroservicesOptions (" + options.FileSystemOptions.FileSystemRoot + ")"); } Logger.Debug("Creating DicomTagReaderHost with FileSystemRoot: " + options.FileSystemOptions.FileSystemRoot); Logger.Debug("NackIfAnyFileErrors option set to " + options.DicomTagReaderOptions.NackIfAnyFileErrors); IProducerModel seriesProducerModel; IProducerModel imageProducerModel; try { Logger.Debug("Creating seriesProducerModel with ExchangeName: " + options.DicomTagReaderOptions.SeriesProducerOptions.ExchangeName); seriesProducerModel = RabbitMqAdapter.SetupProducer(options.DicomTagReaderOptions.SeriesProducerOptions, true); Logger.Debug("Creating imageProducerModel with ExchangeName: " + options.DicomTagReaderOptions.ImageProducerOptions.ExchangeName); imageProducerModel = RabbitMqAdapter.SetupProducer(options.DicomTagReaderOptions.ImageProducerOptions, true); } catch (Exception e) { throw new ApplicationException("Couldn't create series producer model on startup", e); } Logger.Debug("Creating AccessionDirectoryMessageConsumer"); switch (options.DicomTagReaderOptions.TagProcessorMode) { case TagProcessorMode.Serial: _tagReader = new SerialTagReader(options.DicomTagReaderOptions, options.FileSystemOptions, seriesProducerModel, imageProducerModel, new FileSystem()); break; case TagProcessorMode.Parallel: _tagReader = new ParallelTagReader(options.DicomTagReaderOptions, options.FileSystemOptions, seriesProducerModel, imageProducerModel, new FileSystem()); break; default: throw new ArgumentException($"No case for mode {options.DicomTagReaderOptions.TagProcessorMode}"); } // Setup our consumer AccessionDirectoryMessageConsumer = new DicomTagReaderConsumer(_tagReader, options); }
public DicomReprocessorHost(GlobalOptions options, DicomReprocessorCliOptions cliOptions) : base(options) { string key = cliOptions.ReprocessingRoutingKey; if (string.IsNullOrWhiteSpace(key)) { throw new ArgumentException("ReprocessingRoutingKey"); } // Set the initial sleep time Globals.DicomReprocessorOptions.SleepTime = TimeSpan.FromMilliseconds(cliOptions.SleepTimeMs); IProducerModel reprocessingProducerModel = RabbitMqAdapter.SetupProducer(options.DicomReprocessorOptions.ReprocessingProducerOptions, true); Logger.Info("Documents will be reprocessed to " + options.DicomReprocessorOptions.ReprocessingProducerOptions.ExchangeName + " on vhost " + options.RabbitOptions.RabbitMqVirtualHost + " with routing key \"" + key + "\""); if (!string.IsNullOrWhiteSpace(cliOptions.QueryFile)) { _queryString = File.ReadAllText(cliOptions.QueryFile); } //TODO Make this into a CreateInstance<> call switch (options.DicomReprocessorOptions.ProcessingMode) { case ProcessingMode.TagPromotion: _processor = new TagPromotionProcessor(options.DicomReprocessorOptions, reprocessingProducerModel, key); break; case ProcessingMode.ImageReprocessing: _processor = new DicomFileProcessor(options.DicomReprocessorOptions, reprocessingProducerModel, key); break; default: throw new ArgumentException("ProcessingMode " + options.DicomReprocessorOptions.ProcessingMode + " not supported"); } _mongoReader = new MongoDbReader(options.MongoDatabases.DicomStoreOptions, cliOptions, HostProcessName + "-" + HostProcessID); AddControlHandler(new DicomReprocessorControlMessageHandler(Globals.DicomReprocessorOptions)); }
public FileCopierHost( [NotNull] GlobalOptions options, [CanBeNull] IFileSystem fileSystem = null ) : base( options ) { Logger.Debug("Creating FileCopierHost with FileSystemRoot: " + Globals.FileSystemOptions.FileSystemRoot); IProducerModel copyStatusProducerModel = RabbitMqAdapter.SetupProducer(Globals.FileCopierOptions.CopyStatusProducerOptions, isBatch: false); var fileCopier = new ExtractionFileCopier( Globals.FileCopierOptions, copyStatusProducerModel, Globals.FileSystemOptions.FileSystemRoot, Globals.FileSystemOptions.ExtractRoot, fileSystem ); _consumer = new FileCopyQueueConsumer(fileCopier); }
/// <summary> /// Constructor /// </summary> /// <param name="cliOptions">Common microservices options. Must contain details for an message exchange labelled as "accessionDirectories"</param> /// <param name="globals">Configuration settings for the program</param> public DicomDirectoryProcessorHost(GlobalOptions globals, DicomDirectoryProcessorCliOptions cliOptions) : base(globals) { _cliOptions = cliOptions; if (!cliOptions.DirectoryFormat.ToLower().Equals("list")) { // TODO(rkm 2020-02-12) I think we want to check this regardless of the mode // (bp 2020-02-13) By not doing this check on list means that the list of paths is not required to be in PACS and can be imported from anywhere if (!Directory.Exists(globals.FileSystemOptions.FileSystemRoot)) { throw new ArgumentException("Cannot find the FileSystemRoot specified in the given MicroservicesOptions (" + globals.FileSystemOptions.FileSystemRoot + ")"); } if (!cliOptions.ToProcessDir.Exists) { throw new ArgumentException("Could not find directory " + cliOptions.ToProcessDir.FullName); } if (!cliOptions.ToProcessDir.FullName.StartsWith(globals.FileSystemOptions.FileSystemRoot, true, CultureInfo.CurrentCulture)) { throw new ArgumentException("Directory parameter (" + cliOptions.ToProcessDir.FullName + ") must be below the FileSystemRoot (" + globals.FileSystemOptions.FileSystemRoot + ")"); } } else { if (!File.Exists(cliOptions.ToProcessDir.FullName)) { throw new ArgumentException("Could not find accession directory list file (" + cliOptions.ToProcessDir.FullName + ")"); } if (!Path.GetExtension(cliOptions.ToProcessDir.FullName).Equals(".csv")) { throw new ArgumentException("When in 'list' mode, path to accession directory file of format .csv expected (" + cliOptions.ToProcessDir.FullName + ")"); } } if (cliOptions.DirectoryFormat.ToLower().Equals("pacs")) { Logger.Info("Creating PACS directory finder"); _ddf = new PacsDirectoryFinder(globals.FileSystemOptions.FileSystemRoot, globals.FileSystemOptions.DicomSearchPattern, RabbitMqAdapter.SetupProducer(globals.ProcessDirectoryOptions.AccessionDirectoryProducerOptions, isBatch: false)); } else if (cliOptions.DirectoryFormat.ToLower().Equals("list")) { Logger.Info("Creating accession directory lister"); _ddf = new AccessionDirectoryLister(globals.FileSystemOptions.FileSystemRoot, globals.FileSystemOptions.DicomSearchPattern, RabbitMqAdapter.SetupProducer(globals.ProcessDirectoryOptions.AccessionDirectoryProducerOptions, isBatch: false)); } else if (cliOptions.DirectoryFormat.ToLower().Equals("default")) { Logger.Info("Creating basic directory finder"); _ddf = new BasicDicomDirectoryFinder(globals.FileSystemOptions.FileSystemRoot, globals.FileSystemOptions.DicomSearchPattern, RabbitMqAdapter.SetupProducer(globals.ProcessDirectoryOptions.AccessionDirectoryProducerOptions, isBatch: false)); } else if (cliOptions.DirectoryFormat.ToLower().Equals("zips")) { Logger.Info("Creating zip directory finder"); _ddf = new ZipDicomDirectoryFinder(globals.FileSystemOptions.FileSystemRoot, globals.FileSystemOptions.DicomSearchPattern, RabbitMqAdapter.SetupProducer(globals.ProcessDirectoryOptions.AccessionDirectoryProducerOptions, isBatch: false)); } else { throw new ArgumentException("Could not match directory format " + cliOptions.DirectoryFormat + " to an directory scan implementation"); } }
public TriggerUpdatesHost(GlobalOptions options, ITriggerUpdatesSource source, IRabbitMqAdapter rabbitMqAdapter = null) : base(options, rabbitMqAdapter) { this._source = source; _producer = RabbitMqAdapter.SetupProducer(options.TriggerUpdatesOptions, isBatch: false); }