Skip to content

Commit

Permalink
Merge branch 'develop' into vchang/gh-347
Browse files Browse the repository at this point in the history
  • Loading branch information
mocsharp authored Mar 28, 2023
2 parents a3120c7 + a8caee3 commit a124376
Show file tree
Hide file tree
Showing 28 changed files with 1,114 additions and 115 deletions.
6 changes: 3 additions & 3 deletions doc/dependency_decisions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2401,21 +2401,21 @@
- :who: mocsharp
:why: Apache-2.0 (https://github.com/mongodb/mongo-csharp-driver/raw/master/License.txt)
:versions:
- 2.19.0
- 2.19.1
:when: 2022-11-16 23:38:53.891380809 Z
- - :approve
- MongoDB.Driver
- :who: mocsharp
:why: Apache-2.0 (https://github.com/mongodb/mongo-csharp-driver/raw/master/License.txt)
:versions:
- 2.19.0
- 2.19.1
:when: 2022-11-16 23:38:54.213853364 Z
- - :approve
- MongoDB.Driver.Core
- :who: mocsharp
:why: Apache-2.0 (https://github.com/mongodb/mongo-csharp-driver/raw/master/License.txt)
:versions:
- 2.19.0
- 2.19.1
:when: 2022-11-16 23:38:54.553730219 Z
- - :approve
- MongoDB.Libmongocrypt
Expand Down
59 changes: 59 additions & 0 deletions docs/api/rest/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,65 @@ curl --location --request POST 'http://localhost:5000/config/ae/' \

---

## PUT /config/ae

Updates an existing MONAI SCP Application Entity.

> [!Note]
> The MONAI SCP AE Title cannot be changed.
> [!Note]
> The DICOM tag used for `grouping` can be either a Study Instance UID (0020,000D) or Series Instance UID (0020,000E).
> The default is set to a Study Instance UID (0020,000D) if not specified.
> [!Note]
> `timeout` is the number of seconds the AE Title will wait between each instance before assembling a payload and publishing
> a workflow request. We recommend calculating this value based on the network speed and the maximum size of each
> DICOM instance.
### Parameters

See the [MonaiApplicationEntity](xref:Monai.Deploy.InformaticsGateway.Api.MonaiApplicationEntity)
class definition for details.

### Responses

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

| Code | Description |
| ---- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| 200 | AE Title updated successfully. |
| 400 | Validation error. The response will be a [Problem details](https://datatracker.ietf.org/doc/html/rfc7807) object with server error details. |
| 404 | Named MONAI AE 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 PUT 'http://localhost:5000/config/ae/' \
--header 'Content-Type: application/json' \
--data-raw '{
"name": "breast-tumor",
"timeout": 3,
"workflows": [
"3f6a08a1-0dea-44e9-ab82-1ff1adf43a8e"
]
}
}'
```

### Example Response

```json
{
"name": "breast-tumor",
"aeTitle": "BREASTV1",
"workflows": ["3f6a08a1-0dea-44e9-ab82-1ff1adf43a8e"],
"timeout": 3
}
```

---
## DELETE /config/ae/{name}

Deletes the specified MONAI SCP Application Entity.
Expand Down
39 changes: 38 additions & 1 deletion docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!--
~ Copyright 2021-2022 MONAI Consortium
~ Copyright 2021-2023 MONAI Consortium
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
Expand All @@ -17,6 +17,43 @@

# Changelog

## 0.3.15

[GitHub Milestone 0.3.15](https://github.com/Project-MONAI/monai-deploy-informatics-gateway/milestone/20)

- New APIs for managing SCP AE Titles
- `PUT /config/ae`: [Update SCP AE TItle](./api/rest/config.md#put-configae)

## 0.3.14

[GitHub Milestone 0.3.14](https://github.com/Project-MONAI/monai-deploy-informatics-gateway/milestone/19)

- Fixes RabbitMQ startup issues.

## 0.3.13

[GitHub Milestone 0.3.13](https://github.com/Project-MONAI/monai-deploy-informatics-gateway/milestone/18)

- Fixes an issue where failure uploads caused payload to stuck in the queue and stops processing any incoming data.

## 0.3.12

[GitHub Milestone 0.3.12](https://github.com/Project-MONAI/monai-deploy-informatics-gateway/milestone/17)

- Fixes exception handling for unavailable previously created dead-letter queues

## 0.3.11

[GitHub Milestone 0.3.11](https://github.com/Project-MONAI/monai-deploy-informatics-gateway/milestone/16)

- Adds exception handling for unavailable previously created dead-letter queues

## 0.3.10

[GitHub Milestone 0.3.10](https://github.com/Project-MONAI/monai-deploy-informatics-gateway/milestone/15)

- Fixes payload assembler not respecting user configured timeout window

## 0.3.8

[GitHub Milestone 0.3.8](https://github.com/Project-MONAI/monai-deploy-informatics-gateway/milestone/14)
Expand Down
18 changes: 9 additions & 9 deletions docs/compliance/third-party-licenses.md
Original file line number Diff line number Diff line change
Expand Up @@ -8672,14 +8672,14 @@ By downloading this software, you agree to the license terms & all licenses list


<details>
<summary>MongoDB.Bson 2.19.0</summary>
<summary>MongoDB.Bson 2.19.1</summary>

## MongoDB.Bson

- Version: 2.19.0
- Version: 2.19.1
- Authors: MongoDB Inc.
- Project URL: https://www.mongodb.com/docs/drivers/csharp/
- Source: [NuGet](https://www.nuget.org/packages/MongoDB.Bson/2.19.0)
- Source: [NuGet](https://www.nuget.org/packages/MongoDB.Bson/2.19.1)
- License: [Apache-2.0](https://github.com/mongodb/mongo-csharp-driver/raw/master/License.txt)


Expand All @@ -8704,14 +8704,14 @@ By downloading this software, you agree to the license terms & all licenses list


<details>
<summary>MongoDB.Driver 2.19.0</summary>
<summary>MongoDB.Driver 2.19.1</summary>

## MongoDB.Driver

- Version: 2.19.0
- Version: 2.19.1
- Authors: MongoDB Inc.
- Project URL: https://www.mongodb.com/docs/drivers/csharp/
- Source: [NuGet](https://www.nuget.org/packages/MongoDB.Driver/2.19.0)
- Source: [NuGet](https://www.nuget.org/packages/MongoDB.Driver/2.19.1)
- License: [Apache-2.0](https://github.com/mongodb/mongo-csharp-driver/raw/master/License.txt)


Expand All @@ -8736,14 +8736,14 @@ By downloading this software, you agree to the license terms & all licenses list


<details>
<summary>MongoDB.Driver.Core 2.19.0</summary>
<summary>MongoDB.Driver.Core 2.19.1</summary>

## MongoDB.Driver.Core

- Version: 2.19.0
- Version: 2.19.1
- Authors: MongoDB Inc.
- Project URL: https://www.mongodb.com/docs/drivers/csharp/
- Source: [NuGet](https://www.nuget.org/packages/MongoDB.Driver.Core/2.19.0)
- Source: [NuGet](https://www.nuget.org/packages/MongoDB.Driver.Core/2.19.1)
- License: [Apache-2.0](https://github.com/mongodb/mongo-csharp-driver/raw/master/License.txt)


Expand Down
27 changes: 25 additions & 2 deletions src/Api/MonaiApplicationEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* limitations under the License.
*/

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
Expand Down Expand Up @@ -95,6 +96,16 @@ public class MonaiApplicationEntity : MongoDBEntityBase
/// </summary>
public string? CreatedBy { get; set; }

/// <summary>
/// Gets or set the most recent user who updated the DICOM entity.
/// </summary>
public string? UpdatedBy { get; set; }

/// <summary>
/// Gets or set the most recent date time the DICOM entity was updated.
/// </summary>
public DateTime? DateTimeUpdated { get; set; }

public MonaiApplicationEntity()
{
SetDefaultValues();
Expand Down Expand Up @@ -124,9 +135,21 @@ public override string ToString()
return $"Name: {Name}/AET: {AeTitle}";
}

public void SetAuthor(ClaimsPrincipal user)
public void SetAuthor(ClaimsPrincipal user, EditMode editMode)
{
CreatedBy = user.Identity?.Name;
if (editMode == EditMode.Update)
{
DateTimeUpdated = DateTime.UtcNow;
}

if (editMode == EditMode.Create)
{
CreatedBy = user.Identity?.Name;
}
else if (editMode == EditMode.Update)
{
UpdatedBy = user.Identity?.Name;
}
}
}
}
89 changes: 88 additions & 1 deletion src/CLI/Commands/AetCommand.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2021-2022 MONAI Consortium
* Copyright 2021-2023 MONAI Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -40,6 +40,7 @@ public AetCommand() : base("aet", "Configure SCP Application Entities")
AddAlias("aetitle");

SetupAddAetCommand();
SetupEditAetCommand();
SetupRemoveAetCommand();
SetupListAetCommand();
}
Expand Down Expand Up @@ -100,6 +101,39 @@ private void SetupAddAetCommand()
addCommand.Handler = CommandHandler.Create<MonaiApplicationEntity, IHost, bool, CancellationToken>(AddAeTitlehandlerAsync);
}

private void SetupEditAetCommand()
{
var addCommand = new Command("update", "Update a SCP Application Entities");
AddCommand(addCommand);

var nameOption = new Option<string>(new string[] { "-n", "--name" }, "Name of the SCP Application Entity") { IsRequired = false };
addCommand.AddOption(nameOption);
var groupingOption = new Option<string>(new string[] { "-g", "--grouping" }, getDefaultValue: () => "0020,000D", "DICOM tag used to group instances") { IsRequired = false };
addCommand.AddOption(groupingOption);
var timeoutOption = new Option<uint>(new string[] { "-t", "--timeout" }, getDefaultValue: () => 5, "Timeout, in seconds, to wait for instances") { IsRequired = false };
addCommand.AddOption(timeoutOption);
var workflowsOption = new Option<List<string>>(new string[] { "-w", "--workflows" }, description: "A space separated list of workflow names or IDs to be associated with the SCP AE Title")
{
AllowMultipleArgumentsPerToken = true,
IsRequired = false,
};
addCommand.AddOption(workflowsOption);
var ignoredSopsOption = new Option<List<string>>(new string[] { "-i", "--ignored-sop-classes" }, description: "A space separated list of SOP Class UIDs to be ignored")
{
AllowMultipleArgumentsPerToken = true,
IsRequired = false,
};
addCommand.AddOption(ignoredSopsOption);
var allowedSopsOption = new Option<List<string>>(new string[] { "-s", "--allowed-sop-classes" }, description: "A space separated list of SOP Class UIDs to be accepted")
{
AllowMultipleArgumentsPerToken = true,
IsRequired = false,
};
addCommand.AddOption(allowedSopsOption);

addCommand.Handler = CommandHandler.Create<MonaiApplicationEntity, IHost, bool, CancellationToken>(EditAeTitleHandlerAsync);
}

private async Task<int> ListAeTitlehandlerAsync(IHost host, bool verbose, CancellationToken cancellationToken)
{
Guard.Against.Null(host);
Expand Down Expand Up @@ -256,5 +290,58 @@ private async Task<int> AddAeTitlehandlerAsync(MonaiApplicationEntity entity, IH
}
return ExitCodes.Success;
}

private async Task<int> EditAeTitleHandlerAsync(MonaiApplicationEntity entity, IHost host, bool verbose, CancellationToken cancellationToken)
{
Guard.Against.Null(entity);
Guard.Against.Null(host);

LogVerbose(verbose, host, "Configuring services...");
var configService = host.Services.GetRequiredService<IConfigurationService>();
var client = host.Services.GetRequiredService<IInformaticsGatewayClient>();
var logger = CreateLogger<DestinationCommand>(host);

Guard.Against.Null(logger, nameof(logger), "Logger is unavailable.");
Guard.Against.Null(configService, nameof(configService), "Configuration service is unavailable.");
Guard.Against.Null(client, nameof(client), $"{Strings.ApplicationName} client is unavailable.");

try
{
CheckConfiguration(configService);
client.ConfigureServiceUris(configService.Configurations.InformaticsGatewayServerUri);

LogVerbose(verbose, host, $"Connecting to {Strings.ApplicationName} at {configService.Configurations.InformaticsGatewayServerEndpoint}...");
LogVerbose(verbose, host, $"Updating SCP AE Title {entity.AeTitle}...");
var result = await client.MonaiScpAeTitle.Update(entity, cancellationToken).ConfigureAwait(false);

logger.MonaiAeTitleUpdated(result.Name, result.AeTitle, result.Grouping, result.Timeout);
if (result.Workflows.Any())
{
logger.MonaiAeWorkflows(string.Join(',', result.Workflows));
logger.WorkflowWarning();
}
if (result.IgnoredSopClasses.Any())
{
logger.MonaiAeIgnoredSops(string.Join(',', result.IgnoredSopClasses));
logger.IgnoredSopClassesWarning();
}
if (result.AllowedSopClasses.Any())
{
logger.MonaiAeAllowedSops(string.Join(',', result.AllowedSopClasses));
logger.AcceptedSopClassesWarning();
}
}
catch (ConfigurationException ex)
{
logger.ConfigurationException(ex.Message);
return ExitCodes.Config_NotConfigured;
}
catch (Exception ex)
{
logger.ErrorUpdatingMonaiApplicationEntity(entity.AeTitle, ex.Message);
return ExitCodes.MonaiScp_ErrorUpdate;
}
return ExitCodes.Success;
}
}
}
1 change: 1 addition & 0 deletions src/CLI/ExitCodes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public static class ExitCodes
public const int MonaiScp_ErrorList = 200;
public const int MonaiScp_ErrorDelete = 201;
public const int MonaiScp_ErrorCreate = 202;
public const int MonaiScp_ErrorUpdate = 203;

public const int DestinationAe_ErrorList = 300;
public const int DestinationAe_ErrorDelete = 301;
Expand Down
8 changes: 7 additions & 1 deletion src/CLI/Logging/Log.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 MONAI Consortium
* Copyright 2023 MONAI Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -181,6 +181,12 @@ public static partial class Log
[LoggerMessage(EventId = 30059, Level = LogLevel.Critical, Message = "Error updating DICOM source {aeTitle}: {message}")]
public static partial void ErrorUpdatingDicomSource(this ILogger logger, string aeTitle, string message);

[LoggerMessage(EventId = 30060, Level = LogLevel.Information, Message = "MONAI Deploy SCP Application Entity updated:\r\n\tName: {name}\r\n\tAE Title: {aeTitle}\r\n\tGrouping: {grouping}\r\n\tTimeout: {timeout}")]
public static partial void MonaiAeTitleUpdated(this ILogger logger, string name, string aeTitle, string grouping, uint timeout);

[LoggerMessage(EventId = 30061, Level = LogLevel.Critical, Message = "Error updating SCP Application Entity {aeTitle}: {message}")]
public static partial void ErrorUpdatingMonaiApplicationEntity(this ILogger logger, string aeTitle, string message);

// Docker Runner
[LoggerMessage(EventId = 31000, Level = LogLevel.Debug, Message = "Checking for existing {applicationName} ({version}) containers...")]
public static partial void CheckingExistingAppContainer(this ILogger logger, string applicationName, string version);
Expand Down
Loading

0 comments on commit a124376

Please sign in to comment.