diff --git a/Directory.Packages.props b/Directory.Packages.props index e66667d6e0..4fe4448d51 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,7 +1,7 @@ - 7.1.13 + 7.1.53 4.3.0 @@ -32,7 +32,7 @@ - + @@ -123,4 +123,4 @@ - \ No newline at end of file + diff --git a/src/Microsoft.Health.Fhir.Api/Features/ActionResults/ResourceActionResult.cs b/src/Microsoft.Health.Fhir.Api/Features/ActionResults/ResourceActionResult.cs index bb193b7550..ae187d7557 100644 --- a/src/Microsoft.Health.Fhir.Api/Features/ActionResults/ResourceActionResult.cs +++ b/src/Microsoft.Health.Fhir.Api/Features/ActionResults/ResourceActionResult.cs @@ -12,6 +12,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Primitives; +using Microsoft.Health.Abstractions.Exceptions; using Microsoft.Health.Core.Features.Context; using Microsoft.Health.Fhir.Core.Features.Context; using Microsoft.Health.Fhir.Core.Features.Persistence; @@ -56,7 +57,16 @@ public override async Task ExecuteResultAsync(ActionContext context) { EnsureArg.IsNotNull(context, nameof(context)); - var fhirContext = context.HttpContext.RequestServices.GetService>(); + RequestContextAccessor fhirContext = null; + + try + { + fhirContext = context.HttpContext.RequestServices.GetService>(); + } + catch (ObjectDisposedException ode) + { + throw new ServiceUnavailableException(Resources.NotAbleToCreateTheFinalResultsOfAnOperation, ode); + } HttpResponse response = context.HttpContext.Response; diff --git a/src/Microsoft.Health.Fhir.Api/Resources.Designer.cs b/src/Microsoft.Health.Fhir.Api/Resources.Designer.cs index 669a490d3d..e075cd83f5 100644 --- a/src/Microsoft.Health.Fhir.Api/Resources.Designer.cs +++ b/src/Microsoft.Health.Fhir.Api/Resources.Designer.cs @@ -537,6 +537,15 @@ public static string NoSoftPurge { } } + /// + /// Looks up a localized string similar to Not able to create final result. Retry the operation.. + /// + public static string NotAbleToCreateTheFinalResultsOfAnOperation { + get { + return ResourceManager.GetString("NotAbleToCreateTheFinalResultsOfAnOperation", resourceCulture); + } + } + /// /// Looks up a localized string similar to The requested route was not found.. /// diff --git a/src/Microsoft.Health.Fhir.Api/Resources.resx b/src/Microsoft.Health.Fhir.Api/Resources.resx index 16838bf404..47e69b7478 100644 --- a/src/Microsoft.Health.Fhir.Api/Resources.resx +++ b/src/Microsoft.Health.Fhir.Api/Resources.resx @@ -420,4 +420,7 @@ The export parameter "includeAssociatedData" contains an invalid value. Supported values are: {0}. - + + Not able to create final result. Retry the operation. + + \ No newline at end of file diff --git a/src/Microsoft.Health.Fhir.Core/Features/Conformance/SystemConformanceProvider.cs b/src/Microsoft.Health.Fhir.Core/Features/Conformance/SystemConformanceProvider.cs index bde00ec30e..f231fb7542 100644 --- a/src/Microsoft.Health.Fhir.Core/Features/Conformance/SystemConformanceProvider.cs +++ b/src/Microsoft.Health.Fhir.Core/Features/Conformance/SystemConformanceProvider.cs @@ -209,11 +209,12 @@ public async Task BackgroudLoop() Stopwatch sw = Stopwatch.StartNew(); for (int i = 0; i < _rebuildDelay; i++) { - await Task.Delay(TimeSpan.FromMinutes(1)); + await Task.Delay(TimeSpan.FromMinutes(1), _cancellationTokenSource.Token); if (_disposed) { _logger.LogError("SystemConformanceProvider is already disposed. SystemConformanceProvider's BackgroudLoop is completed."); + return; } if (_cancellationTokenSource.IsCancellationRequested) @@ -238,7 +239,7 @@ public async Task BackgroudLoop() _builder.SyncProfiles(); } - await (_metadataSemaphore?.WaitAsync(CancellationToken.None) ?? Task.CompletedTask); + await (_metadataSemaphore?.WaitAsync(_cancellationTokenSource.Token) ?? Task.CompletedTask); try { _metadata = null; @@ -266,6 +267,12 @@ public async ValueTask DisposeAsync() { _logger.LogInformation("SystemConformanceProvider: DisposeAsync invoked."); + if (_disposed) + { + _logger.LogInformation("SystemConformanceProvider: Instance is already disposed."); + return; + } + if (!_cancellationTokenSource.IsCancellationRequested) { await _cancellationTokenSource.CancelAsync(); diff --git a/src/Microsoft.Health.Fhir.Core/Models/OperationOutcomeConstants.cs b/src/Microsoft.Health.Fhir.Core/Models/OperationOutcomeConstants.cs index 2c83cc80b0..2dafee8800 100644 --- a/src/Microsoft.Health.Fhir.Core/Models/OperationOutcomeConstants.cs +++ b/src/Microsoft.Health.Fhir.Core/Models/OperationOutcomeConstants.cs @@ -33,6 +33,7 @@ public static class IssueType public const string Throttled = nameof(Throttled); public const string Timeout = nameof(Timeout); public const string TooCostly = nameof(TooCostly); + public const string Transient = nameof(Transient); } } } diff --git a/src/Microsoft.Health.Fhir.CosmosDb/Features/Storage/Queues/CosmosQueueClient.cs b/src/Microsoft.Health.Fhir.CosmosDb/Features/Storage/Queues/CosmosQueueClient.cs index ee361c8490..c30d29041d 100644 --- a/src/Microsoft.Health.Fhir.CosmosDb/Features/Storage/Queues/CosmosQueueClient.cs +++ b/src/Microsoft.Health.Fhir.CosmosDb/Features/Storage/Queues/CosmosQueueClient.cs @@ -7,7 +7,6 @@ using System.Collections.Generic; using System.Linq; using System.Net; -using System.Runtime; using System.Security.Cryptography; using System.Threading; using System.Threading.Tasks; @@ -520,29 +519,41 @@ private static void CancelJobDefinition(JobDefinitionWrapper item) private async Task> ExecuteQueryAsync(QueryDefinition sqlQuerySpec, int? itemCount, byte queueType, CancellationToken cancellationToken) { - using IScoped container = _containerFactory.Invoke(); - - ICosmosQuery query = _queryFactory.Create( - container.Value, - new CosmosQueryContext( - sqlQuerySpec, - new QueryRequestOptions { PartitionKey = new PartitionKey(JobGroupWrapper.GetJobInfoPartitionKey(queueType)), MaxItemCount = itemCount })); + IScoped container = null; - var items = new List(); - FeedResponse response; + try + { + container = _containerFactory.Invoke(); + } + catch (ObjectDisposedException ode) + { + throw new ServiceUnavailableException(Resources.NotAbleToExecuteQuery, ode); + } - while (itemCount == null || items.Count < itemCount.Value) + using (container) { - response = await _retryPolicy.ExecuteAsync(async () => await query.ExecuteNextAsync(cancellationToken)); - items.AddRange(response); + ICosmosQuery query = _queryFactory.Create( + container.Value, + new CosmosQueryContext( + sqlQuerySpec, + new QueryRequestOptions { PartitionKey = new PartitionKey(JobGroupWrapper.GetJobInfoPartitionKey(queueType)), MaxItemCount = itemCount })); - if (string.IsNullOrEmpty(response.ContinuationToken)) + var items = new List(); + FeedResponse response; + + while (itemCount == null || items.Count < itemCount.Value) { - break; + response = await _retryPolicy.ExecuteAsync(async () => await query.ExecuteNextAsync(cancellationToken)); + items.AddRange(response); + + if (string.IsNullOrEmpty(response.ContinuationToken)) + { + break; + } } - } - return items; + return items; + } } private async Task SaveJobGroupAsync(JobGroupWrapper definition, CancellationToken cancellationToken, bool ignoreEtag = false) diff --git a/src/Microsoft.Health.Fhir.CosmosDb/Resources.Designer.cs b/src/Microsoft.Health.Fhir.CosmosDb/Resources.Designer.cs index f9e286a0df..2d2efdea74 100644 --- a/src/Microsoft.Health.Fhir.CosmosDb/Resources.Designer.cs +++ b/src/Microsoft.Health.Fhir.CosmosDb/Resources.Designer.cs @@ -204,6 +204,15 @@ internal static string KeyVaultWrapUnwrapFailure { } } + /// + /// Looks up a localized string similar to Not able to execute a query. Retry the operation.. + /// + internal static string NotAbleToExecuteQuery { + get { + return ResourceManager.GetString("NotAbleToExecuteQuery", resourceCulture); + } + } + /// /// Looks up a localized string similar to Unhandled {0} '{1}'.. /// diff --git a/src/Microsoft.Health.Fhir.CosmosDb/Resources.resx b/src/Microsoft.Health.Fhir.CosmosDb/Resources.resx index b57e12b377..c3a0475cf5 100644 --- a/src/Microsoft.Health.Fhir.CosmosDb/Resources.resx +++ b/src/Microsoft.Health.Fhir.CosmosDb/Resources.resx @@ -1,17 +1,17 @@  - @@ -171,4 +171,7 @@ Provided feed range is invalid and could not be parsed. - + + Not able to execute a query. Retry the operation. + + \ No newline at end of file