Skip to content

Commit

Permalink
Use update study only for v2 (#3299)
Browse files Browse the repository at this point in the history
* Use update study only for v2

* dont use collection literal
  • Loading branch information
bcarthic authored Jan 12, 2024
1 parent 0f218fe commit 2c8d1ca
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 4 deletions.
6 changes: 3 additions & 3 deletions docs/concepts/bulk-update.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ Example requests can be sent in the [Postman collection](../resources/Conformanc
Bulk update endpoint starts a long running operation that updates all the instances in the study with the specified attributes.

```http
POST ...v1/studies/$bulkUpdate
POST ...v1/partitions/{PartitionName}/studies/$bulkUpdate
POST ...v2/studies/$bulkUpdate
POST ...v2/partitions/{PartitionName}/studies/$bulkUpdate
```

#### Request Header
Expand Down Expand Up @@ -98,7 +98,7 @@ HTTP/1.1 202 Accepted
Content-Type: application/json
{
"id": "1323c079a1b64efcb8943ef7707b5438",
"href": "../v1/operations/1323c079a1b64efcb8943ef7707b5438"
"href": "../v2/operations/1323c079a1b64efcb8943ef7707b5438"
}
```

Expand Down
13 changes: 12 additions & 1 deletion src/Microsoft.Health.Dicom.Api/Controllers/StoreController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
using Microsoft.Health.Dicom.Core.Exceptions;
using Microsoft.Health.Dicom.Core.Extensions;
using Microsoft.Health.Dicom.Core.Features.Audit;
using Microsoft.Health.Dicom.Core.Features.Context;
using Microsoft.Health.Dicom.Core.Messages.Store;
using Microsoft.Health.Dicom.Core.Messages.Update;
using Microsoft.Health.Dicom.Core.Models;
Expand All @@ -36,19 +37,22 @@ namespace Microsoft.Health.Dicom.Api.Controllers;
[ServiceFilter(typeof(PopulateDataPartitionFilterAttribute))]
public class StoreController : ControllerBase
{
private readonly IDicomRequestContextAccessor _dicomRequestContextAccessor;
private readonly IMediator _mediator;
private readonly ILogger<StoreController> _logger;
private readonly bool _asyncOperationDisabled;

public StoreController(IMediator mediator, ILogger<StoreController> logger, IOptions<FeatureConfiguration> featureConfiguration)
public StoreController(IMediator mediator, ILogger<StoreController> logger, IOptions<FeatureConfiguration> featureConfiguration, IDicomRequestContextAccessor dicomRequestContextAccessor)
{
EnsureArg.IsNotNull(mediator, nameof(mediator));
EnsureArg.IsNotNull(logger, nameof(logger));
EnsureArg.IsNotNull(featureConfiguration, nameof(featureConfiguration));
EnsureArg.IsNotNull(dicomRequestContextAccessor, nameof(dicomRequestContextAccessor));

_mediator = mediator;
_logger = logger;
_asyncOperationDisabled = featureConfiguration.Value.DisableOperations;
_dicomRequestContextAccessor = dicomRequestContextAccessor;
}

[AcceptContentFilter(new[] { KnownContentTypes.ApplicationDicomJson })]
Expand Down Expand Up @@ -94,6 +98,7 @@ public async Task<IActionResult> PostInstanceInStudyAsync(string studyInstanceUi
[Consumes(KnownContentTypes.ApplicationJson)]
[ProducesResponseType(typeof(OperationReference), (int)HttpStatusCode.Accepted)]
[ProducesResponseType(typeof(DicomDataset), (int)HttpStatusCode.BadRequest)]
[ProducesResponseType(typeof(string), (int)HttpStatusCode.NotFound)]
[VersionedPartitionRoute(KnownRoutes.UpdateInstanceRoute, Name = KnownRouteNames.PartitionedUpdateInstance)]
[VersionedRoute(KnownRoutes.UpdateInstanceRoute, Name = KnownRouteNames.UpdateInstance)]
[AuditEventType(AuditEventSubType.UpdateStudy)]
Expand All @@ -104,6 +109,12 @@ public async Task<IActionResult> UpdateAsync([FromBody][Required] UpdateSpecific
throw new DicomAsyncOperationDisabledException();
}

// DICOM update only supported in API version 2 and above
if (_dicomRequestContextAccessor.RequestContext.Version < ApiVersionsConvention.MinimumSupportedVersionForDicomUpdate)
{
return StatusCode((int)HttpStatusCode.NotFound);
}

UpdateInstanceResponse response = await _mediator.UpdateInstanceAsync(updateSpecification);
if (response.FailedDataset != null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ internal class ApiVersionsConvention : IControllerConvention
internal static IReadOnlyList<ApiVersion> UpcomingVersion = new List<ApiVersion>() { };

internal const int CurrentVersion = 2;
internal const int MinimumSupportedVersionForDicomUpdate = 2;

private readonly bool _isLatestApiVersionEnabled;

public ApiVersionsConvention(IOptions<FeatureConfiguration> featureConfiguration)
Expand Down
12 changes: 12 additions & 0 deletions swagger/v1-prerelease/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2376,6 +2376,12 @@ paths:
type: array
items:
$ref: '#/components/schemas/DicomItem'
'404':
description: Not Found
content:
application/json:
schema:
type: string
/v1-prerelease/studies/$bulkUpdate:
post:
tags:
Expand Down Expand Up @@ -2408,6 +2414,12 @@ paths:
type: array
items:
$ref: '#/components/schemas/DicomItem'
'404':
description: Not Found
content:
application/json:
schema:
type: string
'/v1-prerelease/partitions/{partitionName}/workitems':
post:
tags:
Expand Down
12 changes: 12 additions & 0 deletions swagger/v1/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2420,6 +2420,12 @@ paths:
type: array
items:
$ref: '#/components/schemas/DicomItem'
'404':
description: Not Found
content:
application/json:
schema:
type: string
/v1/studies/$bulkUpdate:
post:
tags:
Expand Down Expand Up @@ -2452,6 +2458,12 @@ paths:
type: array
items:
$ref: '#/components/schemas/DicomItem'
'404':
description: Not Found
content:
application/json:
schema:
type: string
'/v1/partitions/{partitionName}/workitems':
post:
tags:
Expand Down
12 changes: 12 additions & 0 deletions swagger/v2/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2438,6 +2438,12 @@ paths:
type: array
items:
$ref: '#/components/schemas/DicomItem'
'404':
description: Not Found
content:
application/json:
schema:
type: string
/v2/studies/$bulkUpdate:
post:
tags:
Expand Down Expand Up @@ -2470,6 +2476,12 @@ paths:
type: array
items:
$ref: '#/components/schemas/DicomItem'
'404':
description: Not Found
content:
application/json:
schema:
type: string
'/v2/partitions/{partitionName}/workitems':
post:
tags:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,28 @@ namespace Microsoft.Health.Dicom.Web.Tests.E2E.Rest;
public class UpdateInstanceTests : IClassFixture<WebJobsIntegrationTestFixture<WebStartup, FunctionsStartup>>, IAsyncLifetime
{
private readonly IDicomWebClient _client;
private readonly IDicomWebClient _v1Client;
private readonly DicomTagsManager _tagManager;
private readonly DicomInstancesManager _instancesManager;

public UpdateInstanceTests(WebJobsIntegrationTestFixture<WebStartup, FunctionsStartup> fixture)
{
EnsureArg.IsNotNull(fixture, nameof(fixture));
_client = fixture.GetDicomWebClient();
_v1Client = fixture.GetDicomWebClient(DicomApiVersions.V1);
_tagManager = new DicomTagsManager(_client);
_instancesManager = new DicomInstancesManager(_client);
}

[Fact]
public async Task GivenV1DicomClient_WhenUpdateStudy_TheItShouldReturnNotFound()
{
string studyInstanceUid1 = TestUidGenerator.Generate();
DicomWebException exception = await Assert.ThrowsAsync<DicomWebException>(() => _v1Client.UpdateStudyAsync(new[] { studyInstanceUid1 }, new DicomDataset()));

Assert.Equal(HttpStatusCode.NotFound, exception.StatusCode);
}

[Fact]
public async Task WhenUpdatingDicomMetadataForASingleStudy_ThenItShouldUpdateCorrectly()
{
Expand Down

0 comments on commit 2c8d1ca

Please sign in to comment.