-
Notifications
You must be signed in to change notification settings - Fork 523
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
Add support for include to delete requests #4811
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,8 +13,10 @@ | |
using MediatR; | ||
using Microsoft.Build.Framework; | ||
using Microsoft.Extensions.Logging; | ||
using Microsoft.Extensions.Options; | ||
using Microsoft.Health.Core.Features.Context; | ||
using Microsoft.Health.Core.Features.Security.Authorization; | ||
using Microsoft.Health.Fhir.Core.Configs; | ||
using Microsoft.Health.Fhir.Core.Exceptions; | ||
using Microsoft.Health.Fhir.Core.Extensions; | ||
using Microsoft.Health.Fhir.Core.Features.Conformance; | ||
|
@@ -31,6 +33,7 @@ public class ConditionalDeleteResourceHandler : BaseResourceHandler, IRequestHan | |
private readonly ISearchService _searchService; | ||
private readonly IDeletionService _deleter; | ||
private readonly RequestContextAccessor<IFhirRequestContext> _fhirContext; | ||
private readonly CoreFeatureConfiguration _configuration; | ||
private readonly ILogger<ConditionalDeleteResourceHandler> _logger; | ||
|
||
public ConditionalDeleteResourceHandler( | ||
|
@@ -43,17 +46,20 @@ public ConditionalDeleteResourceHandler( | |
IAuthorizationService<DataActions> authorizationService, | ||
IDeletionService deleter, | ||
RequestContextAccessor<IFhirRequestContext> fhirContext, | ||
IOptions<CoreFeatureConfiguration> configuration, | ||
ILogger<ConditionalDeleteResourceHandler> logger) | ||
: base(fhirDataStore, conformanceProvider, resourceWrapperFactory, resourceIdProvider, authorizationService) | ||
{ | ||
EnsureArg.IsNotNull(mediator, nameof(mediator)); | ||
EnsureArg.IsNotNull(searchService, nameof(searchService)); | ||
EnsureArg.IsNotNull(deleter, nameof(deleter)); | ||
EnsureArg.IsNotNull(configuration.Value, nameof(configuration)); | ||
EnsureArg.IsNotNull(logger, nameof(logger)); | ||
|
||
_searchService = searchService; | ||
_deleter = deleter; | ||
_fhirContext = fhirContext; | ||
_configuration = configuration.Value; | ||
_logger = logger; | ||
} | ||
|
||
|
@@ -86,33 +92,47 @@ public async Task<DeleteResourceResponse> Handle(ConditionalDeleteResourceReques | |
|
||
private async Task<DeleteResourceResponse> DeleteSingleAsync(ConditionalDeleteResourceRequest request, CancellationToken cancellationToken) | ||
{ | ||
var matchedResults = await _searchService.ConditionalSearchAsync( | ||
var results = await _searchService.ConditionalSearchAsync( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did we a limit on the number of included items coming back from ConditionalSearch? i.e. if we delete the primary resource and some of the included items, do some then become orphaned? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The limit is still there. On line 108 there is a check to see if we got the "include results truncated" issue. If we did it returns 408 and says there are too many included results. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I still need to add similar behavior to bulk delete. I'm debating how best to do that so it still deletes as many results as possible. Once we have pagination for include I'll just have it page through the results. |
||
request.ResourceType, | ||
request.ConditionalParameters, | ||
cancellationToken, | ||
logger: _logger); | ||
|
||
int count = matchedResults.Results.Count; | ||
int count = results.Results.Where(result => result.SearchEntryMode == ValueSets.SearchEntryMode.Match).Count(); | ||
bool tooManyIncludeResults = _fhirContext.RequestContext.BundleIssues.Any(x => string.Equals(x.Diagnostics, Core.Resources.TruncatedIncludeMessage, StringComparison.OrdinalIgnoreCase)); | ||
|
||
if (count == 0) | ||
{ | ||
return new DeleteResourceResponse(0); | ||
} | ||
else if (count == 1) | ||
else if (count == 1 && !tooManyIncludeResults) | ||
{ | ||
var result = await _deleter.DeleteAsync( | ||
new DeleteResourceRequest( | ||
request.ResourceType, | ||
matchedResults.Results.First().Resource.ResourceId, | ||
request.DeleteOperation, | ||
bundleResourceContext: request.BundleResourceContext), | ||
cancellationToken); | ||
if (results.Results.Count == 1) | ||
{ | ||
var result = await _deleter.DeleteAsync( | ||
new DeleteResourceRequest( | ||
request.ResourceType, | ||
results.Results.First().Resource.ResourceId, | ||
request.DeleteOperation, | ||
bundleResourceContext: request.BundleResourceContext), | ||
cancellationToken); | ||
|
||
if (string.IsNullOrWhiteSpace(result.VersionId)) | ||
if (string.IsNullOrWhiteSpace(result.VersionId)) | ||
{ | ||
return new DeleteResourceResponse(result); | ||
} | ||
|
||
return new DeleteResourceResponse(result, weakETag: WeakETag.FromVersionId(result.VersionId)); | ||
} | ||
else | ||
{ | ||
return new DeleteResourceResponse(result); | ||
// Include results were present, use delete multiple to handle them. | ||
return await DeleteMultipleAsync(request, cancellationToken); | ||
} | ||
|
||
return new DeleteResourceResponse(result, weakETag: WeakETag.FromVersionId(result.VersionId)); | ||
} | ||
else if (count == 1 && tooManyIncludeResults) | ||
{ | ||
throw new BadRequestException(string.Format(CultureInfo.InvariantCulture, Core.Resources.TooManyIncludeResults, _configuration.DefaultIncludeCountPerSearch)); | ||
} | ||
else | ||
{ | ||
|
@@ -124,7 +144,7 @@ private async Task<DeleteResourceResponse> DeleteSingleAsync(ConditionalDeleteRe | |
|
||
private async Task<DeleteResourceResponse> DeleteMultipleAsync(ConditionalDeleteResourceRequest request, CancellationToken cancellationToken) | ||
{ | ||
long numDeleted = await _deleter.DeleteMultipleAsync(request, cancellationToken); | ||
long numDeleted = (await _deleter.DeleteMultipleAsync(request, cancellationToken)).Sum(result => result.Value); | ||
return new DeleteResourceResponse((int)numDeleted); | ||
} | ||
} | ||
|
Check warning
Code scanning / CodeQL
Useless assignment to local variable Warning