Skip to content

Patch/0.3.18 #391

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 37 commits into from
May 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
97d1b53
Bump actions/upload-artifact from 3.1.1 to 3.1.2 (#314)
dependabot[bot] Jan 11, 2023
c0e35e9
Bump actions/cache from 3.0.11 to 3.2.3 (#313)
dependabot[bot] Jan 11, 2023
2831d3c
Bump Microsoft.NET.Test.Sdk from 17.4.0 to 17.4.1 (#309)
dependabot[bot] Jan 11, 2023
7ad457a
Clears payload at startup (#326)
mocsharp Feb 5, 2023
e3a463b
Fix payload assembler not respecting user configured timeout window (…
mocsharp Feb 9, 2023
1067bb0
Bump Microsoft.EntityFrameworkCore.InMemory from 6.0.13 to 6.0.14 (#337)
dependabot[bot] Feb 21, 2023
55f78e3
Bump Microsoft.EntityFrameworkCore from 6.0.13 to 6.0.14 (#336)
dependabot[bot] Feb 21, 2023
efaab5c
Bump Microsoft.EntityFrameworkCore.Design from 6.0.13 to 6.0.14 (#335)
dependabot[bot] Feb 21, 2023
49227ef
Bump anchore/scan-action from 3.3.2 to 3.3.4 (#334)
dependabot[bot] Feb 21, 2023
65c549e
Bump actions/cache from 3.2.3 to 3.2.5 (#333)
dependabot[bot] Feb 21, 2023
539ae4d
Bump docker/build-push-action from 3.2.0 to 4.0.0 (#328)
dependabot[bot] Feb 21, 2023
2267f21
Bump docker/metadata-action from 4.1.1 to 4.3.0 (#319)
dependabot[bot] Feb 21, 2023
3b1b3c7
Bump actions/cache from 3.2.5 to 3.2.6 (#342)
dependabot[bot] Mar 8, 2023
a176f43
Bump Microsoft.EntityFrameworkCore.Sqlite from 6.0.13 to 6.0.14 (#338)
dependabot[bot] Mar 8, 2023
86cb04c
Update messaging lib to 0.1.20 (#343)
mocsharp Mar 8, 2023
7c97f1e
Log payload move exception (#323)
mocsharp Mar 8, 2023
4906d18
Update message lib to 0.1.21 (#345)
mocsharp Mar 10, 2023
1a2af0c
gh-347 Remove incomplete payloads on timeout (#348)
mocsharp Mar 11, 2023
76b145d
Bump Microsoft.NET.Test.Sdk from 17.4.1 to 17.5.0 (#354)
dependabot[bot] Mar 15, 2023
4359c79
Bump gittools/actions from 0.9.15 to 0.10.2 (#352)
dependabot[bot] Mar 15, 2023
4142479
Bump actions/cache from 3.2.6 to 3.3.1 (#350)
dependabot[bot] Mar 15, 2023
88f1f3e
upping licenses
neildsouth Mar 16, 2023
8a4d6f3
upped dependancies
neildsouth Mar 16, 2023
9a11492
Merge pull request #356 from Project-MONAI/ac1619-nds
neildsouth Mar 16, 2023
222c747
Update Storage & Messaging libraries (#355)
mocsharp Mar 17, 2023
a8caee3
Add PUT /config/ae (#371)
mocsharp Mar 28, 2023
fcbd588
gh-347 Update log statement for debugging (#366)
mocsharp Mar 28, 2023
ac7d557
Set time limit when calling Storage List/Verify APIs (#378)
mocsharp Apr 6, 2023
1e63847
Bump anchore/scan-action from 3.3.4 to 3.3.5 (#373)
dependabot[bot] Apr 18, 2023
a83ef62
Resets ActionBlock if faulted or cancelled. (#385)
mocsharp Apr 20, 2023
630dceb
Update index.md
dbericat May 11, 2023
22cdee9
adding endpoint to get AETitles by AeTitle
neildsouth May 11, 2023
5fba84d
adding new tests
neildsouth May 11, 2023
de8d857
improving test coverage
neildsouth May 11, 2023
dffc3ee
updating APi docs
neildsouth May 11, 2023
6a87247
change to path of new endpoint
neildsouth May 11, 2023
6edaa54
Merged from main
woodheadio May 12, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/.gitversion.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ branches:
ignore:
sha: []
merge-message-formats: {}
next-version: 0.3.16
next-version: 0.3.17
39 changes: 39 additions & 0 deletions docs/api/rest/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,45 @@ curl --location --request GET 'http://localhost:5000/config/source/USEAST'

---

## GET /config/source/aetitle/{aeTitle}

Returns configurations for the specified calling (source) AET.

### Parameters

| Name | Type | Description |
| ---- | ------ | ------------------------------------------ |
| name | string | The aeTitle of an AE Title to be retrieved. |

### Responses

Response Content Type: JSON - [SourceApplicationEntity[]](xref:Monai.Deploy.InformaticsGateway.Api.SourceApplicationEntity).

| Code | Description |
| ---- | --------------------------------------------------------------------------------------------------------------------------------------- |
| 200 | AE Titles retrieved successfully. |
| 404 | Named source not found. |
| 500 | Server error. The response will be a [Problem details](https://datatracker.ietf.org/doc/html/rfc7807) object with server error details. |

### Example Request

```bash
curl --location --request GET 'http://localhost:5000/config/source/aetitle/USEAST'
```

### Example Response

```json
[{
"name": "USEAST",
"aeTitle": "PACSUSEAST",
"hostIp": "10.20.3.4"
},
{...}]
```

---

## POST /config/source

Adds a new calling (source) AE Title to the Informatics Gateway to allow DICOM instances from the specified IP address and AE Title.
Expand Down
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
~ limitations under the License.
-->

# MONAI Deploy Informatics Gateway <small>v0.0.0</small>
# MONAI Deploy Informatics Gateway

![NVIDIA](./images/MONAI-logo_color.svg)

Expand Down
6 changes: 0 additions & 6 deletions src/Common/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,6 @@
"resolved": "17.2.3",
"contentHash": "VcozGeE4SxIo0cnXrDHhbrh/Gb8KQnZ3BvMelvh+iw0PrIKtuuA46U2Xm4e4pgnaWFgT4RdZfTpWl/WPRdw0WQ=="
},
"System.IO.Abstractions": {
"type": "Direct",
"requested": "[17.2.3, )",
"resolved": "17.2.3",
"contentHash": "VcozGeE4SxIo0cnXrDHhbrh/Gb8KQnZ3BvMelvh+iw0PrIKtuuA46U2Xm4e4pgnaWFgT4RdZfTpWl/WPRdw0WQ=="
},
"System.Threading.Tasks.Dataflow": {
"type": "Direct",
"requested": "[6.0.0, )",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ public interface ISourceApplicationEntityRepository

Task<SourceApplicationEntity?> FindByNameAsync(string name, CancellationToken cancellationToken = default);

Task<SourceApplicationEntity[]?> FindByAETAsync(string name, CancellationToken cancellationToken = default);

Task<SourceApplicationEntity> AddAsync(SourceApplicationEntity item, CancellationToken cancellationToken = default);

Task<SourceApplicationEntity> UpdateAsync(SourceApplicationEntity entity, CancellationToken cancellationToken = default);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,16 @@ public async Task<bool> ContainsAsync(Expression<Func<SourceApplicationEntity, b
}).ConfigureAwait(false);
}

public async Task<SourceApplicationEntity[]?> FindByAETAsync(string aeTitle, CancellationToken cancellationToken = default)
{
Guard.Against.NullOrWhiteSpace(aeTitle);

return await _retryPolicy.ExecuteAsync(async () =>
{
return await _dataset.Where(p => p.AeTitle.Equals(aeTitle)).ToArrayAsync(cancellationToken).ConfigureAwait(false);
}).ConfigureAwait(false);
}

public async Task<SourceApplicationEntity> RemoveAsync(SourceApplicationEntity entity, CancellationToken cancellationToken = default)
{
Guard.Against.Null(entity);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,20 @@ public async Task GivenAAETitleName_WhenFindByNameAsyncIsCalled_ExpectItToReturn
Assert.Null(actual);
}

[Fact]
public async Task GivenAAETitleName_WhenFindByAETAsyncIsCalled_ExpectItToReturnMatchingEntity()
{
var store = new SourceApplicationEntityRepository(_serviceScopeFactory.Object, _logger.Object, _options);

var actual = await store.FindByAETAsync("AET1").ConfigureAwait(false);
Assert.NotNull(actual);
Assert.Equal("AET1", actual.FirstOrDefault()!.AeTitle);
Assert.Equal("AET1", actual.FirstOrDefault()!.Name);

actual = await store.FindByAETAsync("AET6").ConfigureAwait(false);
Assert.Empty(actual);
}

[Fact]
public async Task GivenASourceApplicationEntity_WhenRemoveIsCalled_ExpectItToDeleted()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,20 @@ public async Task GivenAAETitleName_WhenFindByNameAsyncIsCalled_ExpectItToReturn
Assert.Null(actual);
}

[Fact]
public async Task GivenAETitle_WhenFindByAETitleAsyncIsCalled_ExpectItToReturnMatchingEntity()
{
var store = new SourceApplicationEntityRepository(_serviceScopeFactory.Object, _logger.Object, _options, _databaseFixture.Options);

var actual = await store.FindByAETAsync("AET1").ConfigureAwait(false);
Assert.NotNull(actual);
Assert.Equal("AET1", actual.FirstOrDefault()!.AeTitle);
Assert.Equal("AET1", actual.FirstOrDefault()!.Name);

actual = await store.FindByAETAsync("AET6").ConfigureAwait(false);
Assert.Empty(actual);
}

[Fact]
public async Task GivenASourceApplicationEntity_WhenRemoveIsCalled_ExpectItToDeleted()
{
Expand Down Expand Up @@ -158,5 +172,7 @@ public async Task GivenASourceApplicationEntity_WhenUpdatedIsCalled_ExpectItToSa
Assert.NotNull(dbResult);
Assert.Equal(expected.AeTitle, dbResult!.AeTitle);
}


}
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,16 @@ public async Task<List<SourceApplicationEntity>> ToListAsync(CancellationToken c
}).ConfigureAwait(false);
}

public async Task<SourceApplicationEntity[]?> FindByAETAsync(string aeTitle, CancellationToken cancellationToken = default)
{
return await _retryPolicy.ExecuteAsync(async () =>
{
return (await _collection
.Find(x => x.AeTitle == aeTitle)
.ToListAsync(cancellationToken).ConfigureAwait(false)).ToArray();
}).ConfigureAwait(false);
}

public async Task<SourceApplicationEntity> AddAsync(SourceApplicationEntity item, CancellationToken cancellationToken = default)
{
Guard.Against.Null(item);
Expand Down
4 changes: 2 additions & 2 deletions src/DicomWebClient/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -1248,8 +1248,8 @@
"monai.deploy.informaticsgateway.client.common": {
"type": "Project",
"dependencies": {
"Ardalis.GuardClauses": "4.0.1",
"System.Text.Json": "6.0.7"
"Ardalis.GuardClauses": "[4.0.1, )",
"System.Text.Json": "[6.0.7, )"
}
}
}
Expand Down
26 changes: 26 additions & 0 deletions src/InformaticsGateway/Services/Http/SourceAeTitleController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,32 @@ public async Task<ActionResult<SourceApplicationEntity>> GetAeTitle(string name)
}
}

[HttpGet("/aetitle/{aeTitle}")]
[Produces("application/json")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
[ActionName(nameof(GetAeTitleByAET))]
public async Task<ActionResult<SourceApplicationEntity>> GetAeTitleByAET(string aeTitle)
{
try
{
var sourceApplicationEntity = await _repository.FindByAETAsync(aeTitle, HttpContext.RequestAborted).ConfigureAwait(false);

if (sourceApplicationEntity is null)
{
return NotFound();
}

return Ok(sourceApplicationEntity);
}
catch (Exception ex)
{
_logger.ErrorListingSourceApplicationEntities(ex);
return Problem(title: "Error querying DICOM sources.", statusCode: (int)System.Net.HttpStatusCode.InternalServerError, detail: ex.Message);
}
}

[HttpPost]
[Consumes(MediaTypeNames.Application.Json)]
[ProducesResponseType(StatusCodes.Status201Created)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,27 @@ public async Task GetAeTitle_ReturnsAMatch()
_repository.Verify(p => p.FindByNameAsync(value, It.IsAny<CancellationToken>()), Times.Once());
}

[RetryFact(5, 250, DisplayName = "GetAeTitle - Shall return matching object")]
public async Task GetAeTitle_ViaAETitleReturnsAMatch()
{
var value = "AET";
_repository.Setup(p => p.FindByAETAsync(It.IsAny<string>(), It.IsAny<CancellationToken>())).Returns(
Task.FromResult(
new SourceApplicationEntity[]{
new SourceApplicationEntity
{
AeTitle = value,
HostIp = "host",
Name = $"{value}name",
}}));

var result = await _controller.GetAeTitleByAET(value);
var okObjectResult = result.Result as OkObjectResult;
var response = okObjectResult.Value as SourceApplicationEntity[];
Assert.Equal(value, response.FirstOrDefault().AeTitle);
_repository.Verify(p => p.FindByAETAsync(value, It.IsAny<CancellationToken>()), Times.Once());
}

[RetryFact(5, 250, DisplayName = "GetAeTitle - Shall return 404 if not found")]
public async Task GetAeTitle_Returns404IfNotFound()
{
Expand Down Expand Up @@ -175,6 +196,24 @@ public async Task GetAeTitle_ShallReturnProblemOnFailure()
_repository.Verify(p => p.FindByNameAsync(value, It.IsAny<CancellationToken>()), Times.Once());
}

[RetryFact(5, 250, DisplayName = "GetAeTitle from AETitle - Shall return problem on failure")]
public async Task GetAeTitleViaAETitle_ShallReturnProblemOnFailure()
{
var value = "AET";
_repository.Setup(p => p.FindByAETAsync(It.IsAny<string>(), It.IsAny<CancellationToken>())).Throws(new Exception("error"));

var result = await _controller.GetAeTitleByAET(value);

var objectResult = result.Result as ObjectResult;
Assert.NotNull(objectResult);
var problem = objectResult.Value as ProblemDetails;
Assert.NotNull(problem);
Assert.Equal("Error querying DICOM sources.", problem.Title);
Assert.Equal("error", problem.Detail);
Assert.Equal((int)HttpStatusCode.InternalServerError, problem.Status);
_repository.Verify(p => p.FindByAETAsync(value, It.IsAny<CancellationToken>()), Times.Once());
}

#endregion GetAeTitle

#region Create
Expand Down
8 changes: 4 additions & 4 deletions src/InformaticsGateway/appsettings.Development.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@
"messaging": {
"publisherSettings": {
"endpoint": "localhost",
"username": "rabbitmq",
"password": "rabbitmq",
"username": "admin",
"password": "admin",
"virtualHost": "monaideploy",
"exchange": "monaideploy"
},
"subscriberSettings": {
"endpoint": "localhost",
"username": "rabbitmq",
"password": "rabbitmq",
"username": "admin",
"password": "admin",
"virtualHost": "monaideploy",
"exchange": "monaideploy",
"exportRequestQueue": "export_tasks"
Expand Down