diff --git a/src/Api/Storage/RemoteAppExecution.cs b/src/Api/Storage/RemoteAppExecution.cs index 6e27f425c..66ea8cb09 100755 --- a/src/Api/Storage/RemoteAppExecution.cs +++ b/src/Api/Storage/RemoteAppExecution.cs @@ -16,22 +16,24 @@ using System; using System.Collections.Generic; -using FellowOakDicom; +using System.Text.Json.Serialization; using Monai.Deploy.Messaging.Events; namespace Monai.Deploy.InformaticsGateway.Api.Storage { public class RemoteAppExecution { + [JsonPropertyName("_id")] + public string Id { get; set; } = default!; public DateTime RequestTime { get; set; } = DateTime.UtcNow; public string ExportTaskId { get; set; } = string.Empty; public string WorkflowInstanceId { get; set; } = string.Empty; public string CorrelationId { get; set; } = string.Empty; public string? StudyUid { get; set; } - public string? OutgoingUid { get; set; } + public string? OutgoingUid { get { return Id; } set { Id = value ?? ""; } } public List ExportDetails { get; set; } = new(); public List Files { get; set; } = new(); public FileExportStatus Status { get; set; } - public Dictionary OriginalValues { get; set; } = new(); + public Dictionary OriginalValues { get; set; } = new(); } } diff --git a/src/Database/MongoDB/Configurations/MongoDBOptions.cs b/src/Database/MongoDB/Configurations/MongoDBOptions.cs old mode 100644 new mode 100755 index 34a49ef7e..70e0d35bc --- a/src/Database/MongoDB/Configurations/MongoDBOptions.cs +++ b/src/Database/MongoDB/Configurations/MongoDBOptions.cs @@ -21,6 +21,6 @@ namespace Monai.Deploy.InformaticsGateway.Database.MongoDB.Configurations public class MongoDBOptions { [ConfigurationKeyName("DatabaseName")] - public string DaatabaseName { get; set; } = string.Empty; + public string DatabaseName { get; set; } = string.Empty; } } diff --git a/src/Database/MongoDB/Integration.Test/MongoDatabaseFixture.cs b/src/Database/MongoDB/Integration.Test/MongoDatabaseFixture.cs old mode 100644 new mode 100755 index 8dbc0d33a..9702595b7 --- a/src/Database/MongoDB/Integration.Test/MongoDatabaseFixture.cs +++ b/src/Database/MongoDB/Integration.Test/MongoDatabaseFixture.cs @@ -40,8 +40,8 @@ public class MongoDatabaseFixture public MongoDatabaseFixture() { Client = new MongoClient("mongodb://root:rootpassword@localhost:27017"); - Options = Microsoft.Extensions.Options.Options.Create(new MongoDBOptions { DaatabaseName = $"IGTest" }); - Database = Client.GetDatabase(Options.Value.DaatabaseName); + Options = Microsoft.Extensions.Options.Options.Create(new MongoDBOptions { DatabaseName = $"IGTest" }); + Database = Client.GetDatabase(Options.Value.DatabaseName); var migration = new MongoDatabaseMigrationManager(); migration.Migrate(null!); diff --git a/src/Database/MongoDB/Integration.Test/RemoteAppRepositoryTest.cs b/src/Database/MongoDB/Integration.Test/RemoteAppRepositoryTest.cs new file mode 100755 index 000000000..0d0f1326c --- /dev/null +++ b/src/Database/MongoDB/Integration.Test/RemoteAppRepositoryTest.cs @@ -0,0 +1,106 @@ +/* + * Copyright 2022 MONAI Consortium + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +using FellowOakDicom; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Microsoft.VisualBasic; +using Monai.Deploy.InformaticsGateway.Api.Storage; +using Monai.Deploy.InformaticsGateway.Configuration; +using Monai.Deploy.InformaticsGateway.Database.EntityFramework.Test; +using Monai.Deploy.InformaticsGateway.Database.MongoDB.Repositories; +using MongoDB.Driver; +using Moq; +namespace Monai.Deploy.InformaticsGateway.Database.MongoDB.Integration.Test +{ + [Collection("MongoDatabase")] + public class RemoteAppRepositoryTest + { + private readonly MongoDatabaseFixture _databaseFixture; + + private readonly Mock _serviceScopeFactory; + private readonly Mock> _logger; + private readonly IOptions _options; + + private readonly Mock _serviceScope; + private readonly IServiceProvider _serviceProvider; + + public RemoteAppRepositoryTest(MongoDatabaseFixture databaseFixture) + { + _databaseFixture = databaseFixture ?? throw new ArgumentNullException(nameof(databaseFixture)); + + _serviceScopeFactory = new Mock(); + _logger = new Mock>(); + _options = Options.Create(new InformaticsGatewayConfiguration()); + + _serviceScope = new Mock(); + var services = new ServiceCollection(); + services.AddScoped(p => _logger.Object); + services.AddScoped(p => databaseFixture.Client); + + _serviceProvider = services.BuildServiceProvider(); + _serviceScopeFactory.Setup(p => p.CreateScope()).Returns(_serviceScope.Object); + _serviceScope.Setup(p => p.ServiceProvider).Returns(_serviceProvider); + + _options.Value.Database.Retries.DelaysMilliseconds = new[] { 1, 1, 1 }; + _logger.Setup(p => p.IsEnabled(It.IsAny())).Returns(true); + } + + [Fact] + public async Task GivenAexecution_WhenAddingToDatabase_ExpectItToBeSaved() + { + var outgoingUid = Guid.NewGuid().ToString(); + var dataset = new DicomDataset(); + var date = new DateTime(2023, 5, 21, 6, 7, 8).ToUniversalTime(); + + var execution = new RemoteAppExecution + { + CorrelationId = Guid.NewGuid().ToString(), + ExportTaskId = "ExportTaskId", + WorkflowInstanceId = "WorkflowInstanceId", + OutgoingUid = outgoingUid, + StudyUid = Guid.NewGuid().ToString(), + RequestTime = date, + OriginalValues = new Dictionary { + { DicomTag.StudyInstanceUID.ToString(), "StudyInstanceUID" }, + { DicomTag.SeriesInstanceUID.ToString(), "SeriesInstanceUID" } + } + }; + + + var store = new RemoteAppExecutionRepository(_serviceScopeFactory.Object, _logger.Object, _options, _databaseFixture.Options); + await store.AddAsync(execution).ConfigureAwait(false); + + var collection = _databaseFixture.Database.GetCollection(nameof(RemoteAppExecution)); + var actual = await collection.Find(p => p.OutgoingUid == execution.OutgoingUid).FirstOrDefaultAsync().ConfigureAwait(false); + + Task.Delay(1000).Wait(); + Assert.NotNull(actual); + Assert.Equal(execution.CorrelationId, actual!.CorrelationId); + Assert.Equal(execution.ExportTaskId, actual!.ExportTaskId); + Assert.Equal(execution.WorkflowInstanceId, actual!.WorkflowInstanceId); + Assert.Equal(execution.OutgoingUid, actual!.OutgoingUid); + Assert.Equal(execution.CorrelationId, actual!.CorrelationId); + Assert.Equal(execution.WorkflowInstanceId, actual!.WorkflowInstanceId); + Assert.Equal(execution.StudyUid, actual!.StudyUid); + Assert.Equal(execution.RequestTime, actual!.RequestTime); + Assert.Equal(execution.OriginalValues, actual!.OriginalValues); + Assert.Equal(2, actual!.OriginalValues.Count); + } + } +} diff --git a/src/Database/MongoDB/Repositories/DestinationApplicationEntityRepository.cs b/src/Database/MongoDB/Repositories/DestinationApplicationEntityRepository.cs old mode 100644 new mode 100755 index 4e10ef186..0fd5f8fac --- a/src/Database/MongoDB/Repositories/DestinationApplicationEntityRepository.cs +++ b/src/Database/MongoDB/Repositories/DestinationApplicationEntityRepository.cs @@ -57,7 +57,7 @@ public DestinationApplicationEntityRepository( (exception, timespan, count, context) => _logger.DatabaseErrorRetry(timespan, count, exception)); var mongoDbClient = _scope.ServiceProvider.GetRequiredService(); - var mongoDatabase = mongoDbClient.GetDatabase(mongoDbOptions.Value.DaatabaseName); + var mongoDatabase = mongoDbClient.GetDatabase(mongoDbOptions.Value.DatabaseName); _collection = mongoDatabase.GetCollection(nameof(DestinationApplicationEntity)); CreateIndexes(); } diff --git a/src/Database/MongoDB/Repositories/DicomAssociationInfoRepository.cs b/src/Database/MongoDB/Repositories/DicomAssociationInfoRepository.cs old mode 100644 new mode 100755 index 350bf1d47..87b4e82eb --- a/src/Database/MongoDB/Repositories/DicomAssociationInfoRepository.cs +++ b/src/Database/MongoDB/Repositories/DicomAssociationInfoRepository.cs @@ -55,7 +55,7 @@ public DicomAssociationInfoRepository( (exception, timespan, count, context) => _logger.DatabaseErrorRetry(timespan, count, exception)); var mongoDbClient = _scope.ServiceProvider.GetRequiredService(); - var mongoDatabase = mongoDbClient.GetDatabase(mongoDbOptions.Value.DaatabaseName); + var mongoDatabase = mongoDbClient.GetDatabase(mongoDbOptions.Value.DatabaseName); _collection = mongoDatabase.GetCollection(nameof(DicomAssociationInfo)); } diff --git a/src/Database/MongoDB/Repositories/InferenceRequestRepository.cs b/src/Database/MongoDB/Repositories/InferenceRequestRepository.cs old mode 100644 new mode 100755 index 1686ec48d..7deb0a3e0 --- a/src/Database/MongoDB/Repositories/InferenceRequestRepository.cs +++ b/src/Database/MongoDB/Repositories/InferenceRequestRepository.cs @@ -59,7 +59,7 @@ public InferenceRequestRepository( (exception, timespan, count, context) => _logger.DatabaseErrorRetry(timespan, count, exception)); var mongoDbClient = _scope.ServiceProvider.GetRequiredService(); - var mongoDatabase = mongoDbClient.GetDatabase(mongoDbOptions.Value.DaatabaseName); + var mongoDatabase = mongoDbClient.GetDatabase(mongoDbOptions.Value.DatabaseName); _collection = mongoDatabase.GetCollection(nameof(InferenceRequest)); CreateIndexes(); } diff --git a/src/Database/MongoDB/Repositories/MonaiApplicationEntityRepository.cs b/src/Database/MongoDB/Repositories/MonaiApplicationEntityRepository.cs old mode 100644 new mode 100755 index c4e67cb20..7a9f2996f --- a/src/Database/MongoDB/Repositories/MonaiApplicationEntityRepository.cs +++ b/src/Database/MongoDB/Repositories/MonaiApplicationEntityRepository.cs @@ -57,7 +57,7 @@ public MonaiApplicationEntityRepository( (exception, timespan, count, context) => _logger.DatabaseErrorRetry(timespan, count, exception)); var mongoDbClient = _scope.ServiceProvider.GetRequiredService(); - var mongoDatabase = mongoDbClient.GetDatabase(mongoDbOptions.Value.DaatabaseName); + var mongoDatabase = mongoDbClient.GetDatabase(mongoDbOptions.Value.DatabaseName); _collection = mongoDatabase.GetCollection(nameof(MonaiApplicationEntity)); CreateIndexes(); } diff --git a/src/Database/MongoDB/Repositories/PayloadRepository.cs b/src/Database/MongoDB/Repositories/PayloadRepository.cs old mode 100644 new mode 100755 index f48714e8a..0a67a585b --- a/src/Database/MongoDB/Repositories/PayloadRepository.cs +++ b/src/Database/MongoDB/Repositories/PayloadRepository.cs @@ -57,7 +57,7 @@ public PayloadRepository( (exception, timespan, count, context) => _logger.DatabaseErrorRetry(timespan, count, exception)); var mongoDbClient = _scope.ServiceProvider.GetRequiredService(); - var mongoDatabase = mongoDbClient.GetDatabase(mongoDbOptions.Value.DaatabaseName); + var mongoDatabase = mongoDbClient.GetDatabase(mongoDbOptions.Value.DatabaseName); _collection = mongoDatabase.GetCollection(nameof(Payload)); CreateIndexes(); } diff --git a/src/Database/MongoDB/Repositories/RemoteAppExecutionRepository.cs b/src/Database/MongoDB/Repositories/RemoteAppExecutionRepository.cs index 7f6007d6d..b0c3d1c4c 100755 --- a/src/Database/MongoDB/Repositories/RemoteAppExecutionRepository.cs +++ b/src/Database/MongoDB/Repositories/RemoteAppExecutionRepository.cs @@ -54,7 +54,7 @@ public RemoteAppExecutionRepository(IServiceScopeFactory serviceScopeFactory, (exception, timespan, count, context) => _logger.DatabaseErrorRetry(timespan, count, exception)); var mongoDbClient = _scope.ServiceProvider.GetRequiredService(); - var mongoDatabase = mongoDbClient.GetDatabase(mongoDbOptions.Value.DaatabaseName); + var mongoDatabase = mongoDbClient.GetDatabase(mongoDbOptions.Value.DatabaseName); _collection = mongoDatabase.GetCollection(nameof(RemoteAppExecution)); CreateIndexes(); } diff --git a/src/Database/MongoDB/Repositories/SourceApplicationEntityRepository.cs b/src/Database/MongoDB/Repositories/SourceApplicationEntityRepository.cs old mode 100644 new mode 100755 index 997378042..9f747928f --- a/src/Database/MongoDB/Repositories/SourceApplicationEntityRepository.cs +++ b/src/Database/MongoDB/Repositories/SourceApplicationEntityRepository.cs @@ -57,7 +57,7 @@ public SourceApplicationEntityRepository( (exception, timespan, count, context) => _logger.DatabaseErrorRetry(timespan, count, exception)); var mongoDbClient = _scope.ServiceProvider.GetRequiredService(); - var mongoDatabase = mongoDbClient.GetDatabase(mongoDbOptions.Value.DaatabaseName); + var mongoDatabase = mongoDbClient.GetDatabase(mongoDbOptions.Value.DatabaseName); _collection = mongoDatabase.GetCollection(nameof(SourceApplicationEntity)); CreateIndexes(); } diff --git a/src/Database/MongoDB/Repositories/StorageMetadataWrapperRepository.cs b/src/Database/MongoDB/Repositories/StorageMetadataWrapperRepository.cs old mode 100644 new mode 100755 index da1a97a66..48427a9f6 --- a/src/Database/MongoDB/Repositories/StorageMetadataWrapperRepository.cs +++ b/src/Database/MongoDB/Repositories/StorageMetadataWrapperRepository.cs @@ -59,7 +59,7 @@ public StorageMetadataWrapperRepository( (exception, timespan, count, context) => _logger.DatabaseErrorRetry(timespan, count, exception)); var mongoDbClient = _scope.ServiceProvider.GetRequiredService(); - var mongoDatabase = mongoDbClient.GetDatabase(mongoDbOptions.Value.DaatabaseName); + var mongoDatabase = mongoDbClient.GetDatabase(mongoDbOptions.Value.DatabaseName); _collection = mongoDatabase.GetCollection(nameof(StorageMetadataWrapper)); CreateIndexes(); } diff --git a/src/InformaticsGateway/ExecutionPlugins/ExternalAppIncoming.cs b/src/InformaticsGateway/ExecutionPlugins/ExternalAppIncoming.cs index 849a25d98..095661a86 100755 --- a/src/InformaticsGateway/ExecutionPlugins/ExternalAppIncoming.cs +++ b/src/InformaticsGateway/ExecutionPlugins/ExternalAppIncoming.cs @@ -62,7 +62,8 @@ public ExternalAppIncoming( } foreach (var key in remoteAppExecution.OriginalValues.Keys) { - dicomFile.Dataset.AddOrUpdate(key, remoteAppExecution.OriginalValues[key]); + var (group, element) = Parse(key); + dicomFile.Dataset.AddOrUpdate(new DicomTag(group, element), remoteAppExecution.OriginalValues[key]); } fileMetadata.WorkflowInstanceId = remoteAppExecution.WorkflowInstanceId; @@ -71,6 +72,13 @@ public ExternalAppIncoming( return (dicomFile, fileMetadata); } + private (ushort group, ushort element) Parse(string input) + { + var trim = input.Substring(1, input.Length - 2); + var array = trim.Split(',', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries); + return (Convert.ToUInt16(array[0], 16), Convert.ToUInt16(array[1], 16)); + } + private static DicomTag[] GetTags(string values) { var names = values.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); diff --git a/src/InformaticsGateway/ExecutionPlugins/ExternalAppOutgoing.cs b/src/InformaticsGateway/ExecutionPlugins/ExternalAppOutgoing.cs index 9fbbdc3b6..0c2183f85 100755 --- a/src/InformaticsGateway/ExecutionPlugins/ExternalAppOutgoing.cs +++ b/src/InformaticsGateway/ExecutionPlugins/ExternalAppOutgoing.cs @@ -15,6 +15,7 @@ */ using System; +using System.Data; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -61,7 +62,7 @@ public ExternalAppOutgoing( { if (dicomFile.Dataset.TryGetString(tag, out var value)) { - remoteAppExecution.OriginalValues.Add(tag, value); + remoteAppExecution.OriginalValues.Add(tag.ToString(), value); SetTag(dicomFile, tag); } } diff --git a/src/InformaticsGateway/Test/Services/Common/ExternalAppPluginTest.cs b/src/InformaticsGateway/Test/Services/Common/ExternalAppPluginTest.cs index 81a7276ed..9223d9bfc 100755 --- a/src/InformaticsGateway/Test/Services/Common/ExternalAppPluginTest.cs +++ b/src/InformaticsGateway/Test/Services/Common/ExternalAppPluginTest.cs @@ -211,7 +211,7 @@ public async Task ExternalAppPlugin_Should_Repare_StudyUid() { OutgoingUid = outboundStudyUid, StudyUid = originalStudyUid, - OriginalValues = { { DicomTag.StudyInstanceUID, originalStudyUid } } + OriginalValues = { { DicomTag.StudyInstanceUID.ToString(), originalStudyUid } } }; _repository.Setup(r => r.GetAsync(It.IsAny(), It.IsAny()))