Skip to content

Commit 2bda3cb

Browse files
authored
Store & notify HL7 messages (#113)
* gh-102 Queue to upload received HL7 messages & notify payload assembler * gh-102 Update CLI to export HL7 port with Docker * gh-102 Add new test feature for HL7 * Update license scan settings Signed-off-by: Victor Chang <[email protected]>
1 parent a30d5b3 commit 2bda3cb

File tree

70 files changed

+1450
-265
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+1450
-265
lines changed

.github/workflows/ci.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ jobs:
4545
with:
4646
fetch-depth: 0
4747

48+
- uses: actions/setup-dotnet@v1
49+
with:
50+
dotnet-version: "6.0.x"
51+
4852
- name: Install GitVersion
4953
run: dotnet tool install --global GitVersion.Tool
5054

@@ -199,7 +203,7 @@ jobs:
199203
needs: [build]
200204
strategy:
201205
matrix:
202-
feature: [AcrApi, DicomDimseScp, DicomDimseScu, DicomWebExport, DicomWebStow]
206+
feature: [AcrApi, DicomDimseScp, DicomDimseScu, DicomWebExport, DicomWebStow, HealthLevel7]
203207
fail-fast: false
204208
env:
205209
TAG: ${{ needs.build.outputs.TAG }}

.licenserc.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ header:
2828
- '**/*.feature.cs'
2929
- 'src/.sonarlint/**'
3030
- 'src/coverlet.runsettings'
31+
- 'src/Monai.Deploy.InformaticsGateway.sln'
32+
- 'src/Database/Migrations/**'
3133
- 'demos/**/.env/**'
3234
- 'docs/templates/**'
3335
- 'tests/Integration.Test/*.dev'

Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ COPY --from=build /app/out .
4545
COPY --from=build /tools /opt/dotnetcore-tools
4646

4747
EXPOSE 104
48+
EXPOSE 2575
4849
EXPOSE 5000
4950

5051
RUN ls -lR /opt/monai/ig

global.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"sdk": {
3-
"version": "6.0.100",
3+
"version": "6.0.400",
44
"rollForward": "latestFeature"
55
}
66
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright 2021-2022 MONAI Consortium
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
using System;
18+
using System.Text.Json.Serialization;
19+
using Ardalis.GuardClauses;
20+
21+
namespace Monai.Deploy.InformaticsGateway.Api.Storage
22+
{
23+
/// <summary>
24+
/// Provides basic information for a FHIR resource and storage hierarchy/path.
25+
/// </summary>
26+
public sealed record Hl7FileStorageMetadata : FileStorageMetadata
27+
{
28+
public const string Hl7SubDirectoryName = "ehr";
29+
public const string FileExtension = ".txt";
30+
31+
/// <inheritdoc/>
32+
[JsonIgnore]
33+
public override string DataTypeDirectoryName => Hl7SubDirectoryName;
34+
35+
/// <inheritdoc/>
36+
[JsonPropertyName("file")]
37+
public override StorageObjectMetadata File { get; set; }
38+
39+
/// <summary>
40+
/// DO NOT USE
41+
/// This constructor is intended for JSON serializer.
42+
/// Due to limitation in current version of .NET, the constructor must be public.
43+
/// https://github.com/dotnet/runtime/issues/31511
44+
/// </summary>
45+
[JsonConstructor]
46+
public Hl7FileStorageMetadata() { }
47+
48+
public Hl7FileStorageMetadata(string connectionId)
49+
: base(connectionId, Guid.NewGuid().ToString())
50+
{
51+
Guard.Against.NullOrWhiteSpace(connectionId, nameof(connectionId));
52+
53+
Source = connectionId;
54+
55+
File = new StorageObjectMetadata(FileExtension)
56+
{
57+
TemporaryPath = string.Join(PathSeparator, connectionId, DataTypeDirectoryName, $"{base.Id}{FileExtension}"),
58+
UploadPath = string.Join(PathSeparator, DataTypeDirectoryName, $"{base.Id}{FileExtension}"),
59+
ContentType = System.Net.Mime.MediaTypeNames.Text.Plain,
60+
};
61+
}
62+
}
63+
}

src/Api/Test/Storage/StorageObjectMetadataTest.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,10 @@ public void GivenAStorageObjectMetadata_InitializeWithFileExtensionMissingDot_Ex
3434
[Fact]
3535
public void GivenAStorageObjectMetadata_WhenSetUploadIsCalled_ExpectUplaodValuesToBeSetAndDataStreamDisposed()
3636
{
37-
var metadata = new StorageObjectMetadata(".txt");
38-
metadata.Data = new MemoryStream();
37+
var metadata = new StorageObjectMetadata(".txt")
38+
{
39+
Data = new MemoryStream()
40+
};
3941
metadata.SetUploaded("MYBUCKET");
4042

4143
Assert.Equal("MYBUCKET", metadata.TemporaryBucketName);

src/CLI/Services/ConfigurationOptionAccessor.cs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ public interface IConfigurationOptionAccessor
3030
/// </summary>
3131
int DicomListeningPort { get; set; }
3232

33+
/// <summary>
34+
/// Gets or sets the HL7 listening port from appsettings.json.
35+
/// </summary>
36+
int Hl7ListeningPort { get; set; }
37+
3338
/// <summary>
3439
/// Gets or sets the Docker image prefix from appsettings.json.
3540
/// This is used to query the Informatics Gateway Docker containers that are installed.
@@ -105,13 +110,28 @@ public int DicomListeningPort
105110
}
106111
set
107112
{
108-
Guard.Against.OutOfRangePort(value, nameof(InformaticsGatewayServerEndpoint));
113+
Guard.Against.OutOfRangePort(value, nameof(DicomListeningPort));
109114
var jObject = ReadConfigurationFile();
110115
jObject["InformaticsGateway"]["dicom"]["scp"]["port"] = value;
111116
SaveConfigurationFile(jObject);
112117
}
113118
}
114119

120+
public int Hl7ListeningPort
121+
{
122+
get
123+
{
124+
return GetValueFromJsonPath<int>("InformaticsGateway.hl7.port");
125+
}
126+
set
127+
{
128+
Guard.Against.OutOfRangePort(value, nameof(Hl7ListeningPort));
129+
var jObject = ReadConfigurationFile();
130+
jObject["InformaticsGateway"]["hl7"]["port"] = value;
131+
SaveConfigurationFile(jObject);
132+
}
133+
}
134+
115135
public string DockerImagePrefix
116136
{
117137
get

src/CLI/Services/DockerRunner.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@ public async Task<bool> StartApplication(ImageVersion imageVersion, Cancellation
119119
createContainerParams.ExposedPorts.Add($"{_configurationService.Configurations.DicomListeningPort}/tcp", new EmptyStruct());
120120
createContainerParams.HostConfig.PortBindings.Add($"{_configurationService.Configurations.DicomListeningPort}/tcp", new List<PortBinding> { new PortBinding { HostPort = $"{_configurationService.Configurations.DicomListeningPort}" } });
121121

122+
_logger.DockerPrtBinding(_configurationService.Configurations.Hl7ListeningPort);
123+
createContainerParams.ExposedPorts.Add($"{_configurationService.Configurations.Hl7ListeningPort}/tcp", new EmptyStruct());
124+
createContainerParams.HostConfig.PortBindings.Add($"{_configurationService.Configurations.Hl7ListeningPort}/tcp", new List<PortBinding> { new PortBinding { HostPort = $"{_configurationService.Configurations.Hl7ListeningPort}" } });
125+
122126
_logger.DockerPrtBinding(_configurationService.Configurations.InformaticsGatewayServerPort);
123127
createContainerParams.ExposedPorts.Add($"{_configurationService.Configurations.InformaticsGatewayServerPort}/tcp", new EmptyStruct());
124128
createContainerParams.HostConfig.PortBindings.Add($"{_configurationService.Configurations.InformaticsGatewayServerPort}/tcp", new List<PortBinding> { new PortBinding { HostPort = $"{_configurationService.Configurations.InformaticsGatewayServerPort}" } });

src/Client.Common/Monai.Deploy.InformaticsGateway.Client.Common.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<Project Sdk="Microsoft.NET.Sdk">
1818

1919
<PropertyGroup>
20-
<TargetFramework>netstandard2.1</TargetFramework>
20+
<TargetFramework>net6.0</TargetFramework>
2121
<RootNamespace>Monai.Deploy.InformaticsGateway.Client.Common</RootNamespace>
2222
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
2323
<IsTrimmable>true</IsTrimmable>

src/Common/Monai.Deploy.InformaticsGateway.Common.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
<PropertyGroup>
2121
<RootNamespace>Monai.Deploy.InformaticsGateway.Common</RootNamespace>
22-
<TargetFramework>netstandard2.1</TargetFramework>
22+
<TargetFramework>net6.0</TargetFramework>
2323
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
2424
<IsTrimmable>true</IsTrimmable>
2525
<ProduceReferenceAssembly>True</ProduceReferenceAssembly>

src/Configuration/Hl7Configuration.cs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,31 @@
1-
// SPDX-FileCopyrightText: © 2022 MONAI Consortium
2-
// SPDX-License-Identifier: Apache License 2.0
1+
/*
2+
* Copyright 2022 MONAI Consortium
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
316

417
using Microsoft.Extensions.Configuration;
518

619
namespace Monai.Deploy.InformaticsGateway.Configuration
720
{
821
public class Hl7Configuration
922
{
10-
public static readonly int DefaultClientTimeout = 300000;
23+
public static readonly int DefaultClientTimeout = 60000;
1124
public const int DefaultMaximumNumberOfConnections = 10;
1225

1326
/// <summary>
1427
/// Gets or sets the client connection timeout in milliseconds.
28+
/// Defaults to 60,000ms.
1529
/// </summary>
1630
[ConfigurationKeyName("clientTimeout")]
1731
public int ClientTimeoutMilliseconds { get; set; } = DefaultClientTimeout;
@@ -27,7 +41,7 @@ public class Hl7Configuration
2741
/// Gets or sets the MLLP listening port.
2842
/// Defaults to 2575.
2943
/// </summary>
30-
[ConfigurationKeyName("clientTimeout")]
44+
[ConfigurationKeyName("port")]
3145
public int Port { get; set; } = 2575;
3246

3347
/// <summary>

src/Database/Migrations/20220802200605_R3_0.3.0.Designer.cs

Lines changed: 17 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Database/Migrations/20220802200605_R3_0.3.0.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,20 @@
1-
using Microsoft.EntityFrameworkCore.Migrations;
1+
/*
2+
* Copyright 2022 MONAI Consortium
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
using Microsoft.EntityFrameworkCore.Migrations;
218

319
#nullable disable
420

src/Database/Migrations/InformaticsGatewayContextModelSnapshot.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,20 @@
1-
// <auto-generated />
1+
/*
2+
* Copyright 2022 MONAI Consortium
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
// <auto-generated />
218
using System;
319
using Microsoft.EntityFrameworkCore;
420
using Microsoft.EntityFrameworkCore.Infrastructure;

src/Database/StorageMetadataWrapperEntityConfiguration.cs

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,32 +15,15 @@
1515
* limitations under the License.
1616
*/
1717

18-
using System;
19-
using System.Collections.Generic;
20-
using System.Linq;
21-
using System.Text.Json;
22-
using System.Text.Json.Serialization;
2318
using Microsoft.EntityFrameworkCore;
24-
using Microsoft.EntityFrameworkCore.ChangeTracking;
2519
using Microsoft.EntityFrameworkCore.Metadata.Builders;
26-
using Monai.Deploy.InformaticsGateway.Api.Storage;
2720

2821
namespace Monai.Deploy.InformaticsGateway.Database
2922
{
3023
internal class StorageMetadataWrapperEntityConfiguration : IEntityTypeConfiguration<StorageMetadataWrapper>
3124
{
3225
public void Configure(EntityTypeBuilder<StorageMetadataWrapper> builder)
3326
{
34-
var filesComparer = new ValueComparer<IList<FileStorageMetadata>>(
35-
(c1, c2) => c1.SequenceEqual(c2),
36-
c => c.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode())),
37-
c => c.ToList());
38-
39-
var jsonSerializerSettings = new JsonSerializerOptions
40-
{
41-
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull
42-
};
43-
4427
builder.HasKey(j => new
4528
{
4629
j.CorrelationId,

src/Database/Test/Monai.Deploy.InformaticsGateway.Database.Test.csproj

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
<!--
2+
~ Copyright 2022 MONAI Consortium
3+
~
4+
~ Licensed under the Apache License, Version 2.0 (the "License");
5+
~ you may not use this file except in compliance with the License.
6+
~ You may obtain a copy of the License at
7+
~
8+
~ http://www.apache.org/licenses/LICENSE-2.0
9+
~
10+
~ Unless required by applicable law or agreed to in writing, software
11+
~ distributed under the License is distributed on an "AS IS" BASIS,
12+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
~ See the License for the specific language governing permissions and
14+
~ limitations under the License.
15+
-->
16+
117
<Project Sdk="Microsoft.NET.Sdk">
218

319
<PropertyGroup>

src/Database/Test/Usings.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,17 @@
1+
/*
2+
* Copyright 2022 MONAI Consortium
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
117
global using Xunit;

src/DicomWebClient/API/IDicomWebClient.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,9 @@ public interface IDicomWebClient
7474
/// </summary>
7575
/// <param name="serviceType"><c>ServiceType</c> to be configured</param>
7676
/// <param name="urlPrefix">Url prefix</param>
77+
#pragma warning disable CA1054
7778
void ConfigureServicePrefix(DicomWebServiceType serviceType, string urlPrefix);
78-
79+
#pragma warning restore CA1054
7980
/// <summary>
8081
/// Configures the authentication header for the DICOMweb client.
8182
/// </summary>

src/DicomWebClient/API/IServiceBase.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ namespace Monai.Deploy.InformaticsGateway.DicomWeb.Client.API
1919
{
2020
public interface IServiceBase
2121
{
22+
#pragma warning disable CA1054
2223
bool TryConfigureServiceUriPrefix(string uriPrefix);
24+
#pragma warning restore CA1054
2325
}
2426
}

0 commit comments

Comments
 (0)