From c75afeec7f9827f6ae4c715d357894c4311939fe Mon Sep 17 00:00:00 2001 From: Shaun Donnelly Date: Thu, 27 Apr 2023 11:32:22 -0700 Subject: [PATCH 1/3] default template provider refactor --- .../ContainerRegistryTemplateProvider.cs | 29 ++--- .../ConvertData/ConvertDataEngine.cs | 21 +++- .../ConvertData/DefaultTemplateProvider.cs | 100 ++++++++++++++++++ ...uilderConvertDataRegistrationExtensions.cs | 8 +- .../ConvertData/ITemplateProviderFactory.cs | 14 +++ .../ConvertData/TemplateProviderFactory.cs | 31 ++++++ .../ContainerRegistryTemplateProviderTests.cs | 19 ++-- .../ConvertData/ConvertDataEngineTests.cs | 51 +++++++-- .../ConvertDataRequestHandlerTests.cs | 9 +- 9 files changed, 231 insertions(+), 51 deletions(-) create mode 100644 src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/DefaultTemplateProvider.cs create mode 100644 src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/ITemplateProviderFactory.cs create mode 100644 src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/TemplateProviderFactory.cs diff --git a/src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/ContainerRegistryTemplateProvider.cs b/src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/ContainerRegistryTemplateProvider.cs index 79dd962518..2bfa1f3e10 100644 --- a/src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/ContainerRegistryTemplateProvider.cs +++ b/src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/ContainerRegistryTemplateProvider.cs @@ -52,35 +52,25 @@ public ContainerRegistryTemplateProvider( } /// - /// Fetch template collection from container registry or built-in archive. + /// Fetch template collection from container registry following a custom template convert request. /// /// The convert data request which contains template reference. /// Cancellation token to cancel the fetch operation. /// Template collection. public async Task>> GetTemplateCollectionAsync(ConvertDataRequest request, CancellationToken cancellationToken) { - // We have embedded a default template collection in the templatemanagement package. - // If the template collection is the default reference, we don't need to retrieve token. - var accessToken = string.Empty; - if (!request.IsDefaultTemplateReference) - { - _logger.LogInformation("Using a custom template collection for data conversion."); - - async Task TokenEntryFactory(ICacheEntry entry) - { - var token = await _containerRegistryTokenProvider.GetTokenAsync(request.RegistryServer, cancellationToken); - entry.Size = token.Length; - entry.AbsoluteExpiration = GetTokenAbsoluteExpiration(token); - return token; - } + _logger.LogInformation("Using a custom template collection for data conversion."); - accessToken = await _cache.GetOrCreateAsync(GetCacheKey(request.RegistryServer), TokenEntryFactory); - } - else + async Task TokenEntryFactory(ICacheEntry entry) { - _logger.LogInformation("Using the default template collection for data conversion."); + var token = await _containerRegistryTokenProvider.GetTokenAsync(request.RegistryServer, cancellationToken); + entry.Size = token.Length; + entry.AbsoluteExpiration = GetTokenAbsoluteExpiration(token); + return token; } + var accessToken = await _cache.GetOrCreateAsync(GetCacheKey(request.RegistryServer), TokenEntryFactory); + try { var provider = _templateCollectionProviderFactory.CreateTemplateCollectionProvider(request.TemplateCollectionReference, accessToken); @@ -119,6 +109,7 @@ async Task TokenEntryFactory(ICacheEntry entry) private static DateTimeOffset GetTokenAbsoluteExpiration(string accessToken) { var defaultExpiration = DateTimeOffset.Now.AddMinutes(30); + if (accessToken.StartsWith("bearer ", StringComparison.OrdinalIgnoreCase)) { var jwtTokenText = accessToken.Substring(7); diff --git a/src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/ConvertDataEngine.cs b/src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/ConvertDataEngine.cs index d15a482986..71755a5496 100644 --- a/src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/ConvertDataEngine.cs +++ b/src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/ConvertDataEngine.cs @@ -23,22 +23,22 @@ namespace Microsoft.Health.Fhir.Core.Features.Operations.ConvertData { public class ConvertDataEngine : IConvertDataEngine { - private readonly IConvertDataTemplateProvider _convertDataTemplateProvider; + private readonly ITemplateProviderFactory _templateProviderFactory; private readonly ConvertDataConfiguration _convertDataConfiguration; private readonly ILogger _logger; private readonly Dictionary _converterMap = new Dictionary(); public ConvertDataEngine( - IConvertDataTemplateProvider convertDataTemplateProvider, + ITemplateProviderFactory templateProviderFactory, IOptions convertDataConfiguration, ILogger logger) { - EnsureArg.IsNotNull(convertDataTemplateProvider, nameof(convertDataTemplateProvider)); + EnsureArg.IsNotNull(templateProviderFactory, nameof(templateProviderFactory)); EnsureArg.IsNotNull(convertDataConfiguration, nameof(convertDataConfiguration)); EnsureArg.IsNotNull(logger, nameof(logger)); - _convertDataTemplateProvider = convertDataTemplateProvider; + _templateProviderFactory = templateProviderFactory; _convertDataConfiguration = convertDataConfiguration.Value; _logger = logger; @@ -47,7 +47,18 @@ public ConvertDataEngine( public async Task Process(ConvertDataRequest convertRequest, CancellationToken cancellationToken) { - var templateCollection = await _convertDataTemplateProvider.GetTemplateCollectionAsync(convertRequest, cancellationToken); + IConvertDataTemplateProvider convertDataTemplateProvider; + + if (convertRequest.IsDefaultTemplateReference) + { + convertDataTemplateProvider = _templateProviderFactory.GetDefaultTemplateProvider(); + } + else + { + convertDataTemplateProvider = _templateProviderFactory.GetContainerRegistryTemplateProvider(); + } + + List> templateCollection = await convertDataTemplateProvider.GetTemplateCollectionAsync(convertRequest, cancellationToken); ITemplateProvider templateProvider = new TemplateProvider(templateCollection); if (templateProvider == null) diff --git a/src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/DefaultTemplateProvider.cs b/src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/DefaultTemplateProvider.cs new file mode 100644 index 0000000000..05b4a8e55f --- /dev/null +++ b/src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/DefaultTemplateProvider.cs @@ -0,0 +1,100 @@ +// ------------------------------------------------------------------------------------------------- +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using DotLiquid; +using EnsureThat; +using Microsoft.Extensions.Caching.Memory; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Microsoft.Health.Fhir.Core.Configs; +using Microsoft.Health.Fhir.Core.Features.Operations.ConvertData.Models; +using Microsoft.Health.Fhir.Core.Messages.ConvertData; +using Microsoft.Health.Fhir.TemplateManagement; +using Microsoft.Health.Fhir.TemplateManagement.Exceptions; + +namespace Microsoft.Health.Fhir.Core.Features.Operations.ConvertData +{ + public class DefaultTemplateProvider : IConvertDataTemplateProvider, IDisposable + { + private bool _disposed = false; + private readonly ILogger _logger; + private readonly MemoryCache _cache; + private readonly ITemplateCollectionProviderFactory _templateCollectionProviderFactory; + private readonly ConvertDataConfiguration _convertDataConfig; + + public DefaultTemplateProvider( + IOptions convertDataConfig, + ILogger logger) + { + EnsureArg.IsNotNull(convertDataConfig, nameof(convertDataConfig)); + EnsureArg.IsNotNull(logger, nameof(logger)); + + _convertDataConfig = convertDataConfig.Value; + + _logger = logger; + + // Initialize cache and template collection provider factory + _cache = new MemoryCache(new MemoryCacheOptions + { + SizeLimit = _convertDataConfig.CacheSizeLimit, + }); + _templateCollectionProviderFactory = new TemplateCollectionProviderFactory(_cache, Options.Create(_convertDataConfig.TemplateCollectionOptions)); + } + + /// + /// Fetch template collection from built-in archive following a default template convert request. + /// + /// The convert data request which contains template reference. + /// Cancellation token to cancel the fetch operation. + /// Template collection. + public async Task>> GetTemplateCollectionAsync(ConvertDataRequest request, CancellationToken cancellationToken) + { + var accessToken = string.Empty; + + _logger.LogInformation("Using the default template collection for data conversion."); + + try + { + var provider = _templateCollectionProviderFactory.CreateTemplateCollectionProvider(request.TemplateCollectionReference, accessToken); + return await provider.GetTemplateCollectionAsync(cancellationToken); + } + catch (TemplateManagementException templateEx) + { + _logger.LogWarning(templateEx, "Template collection is invalid."); + throw new TemplateCollectionErrorException(string.Format(Core.Resources.FetchTemplateCollectionFailed, templateEx.Message), templateEx); + } + catch (Exception unhandledEx) + { + _logger.LogError(unhandledEx, "Unhandled exception: failed to get template collection."); + throw new FetchTemplateCollectionFailedException(string.Format(Core.Resources.FetchTemplateCollectionFailed, unhandledEx.Message), unhandledEx); + } + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + if (disposing) + { + _cache?.Dispose(); + } + + _disposed = true; + } + } +} diff --git a/src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/FhirServerBuilderConvertDataRegistrationExtensions.cs b/src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/FhirServerBuilderConvertDataRegistrationExtensions.cs index 327eb362f9..ea16e812b0 100644 --- a/src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/FhirServerBuilderConvertDataRegistrationExtensions.cs +++ b/src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/FhirServerBuilderConvertDataRegistrationExtensions.cs @@ -16,7 +16,7 @@ public static IFhirServerBuilder AddConvertData(this IFhirServerBuilder fhirServ { EnsureArg.IsNotNull(fhirServerBuilder, nameof(fhirServerBuilder)); - fhirServerBuilder.AddConvertDataTemplateProvider() + fhirServerBuilder.AddConvertDataTemplateProviders() .AddConvertDataEngine(); return fhirServerBuilder; @@ -29,9 +29,11 @@ private static IFhirServerBuilder AddConvertDataEngine(this IFhirServerBuilder f return fhirServerBuilder; } - private static IFhirServerBuilder AddConvertDataTemplateProvider(this IFhirServerBuilder fhirServerBuilder) + private static IFhirServerBuilder AddConvertDataTemplateProviders(this IFhirServerBuilder fhirServerBuilder) { - fhirServerBuilder.Services.AddSingleton(); + fhirServerBuilder.Services.AddSingleton(); + fhirServerBuilder.Services.AddSingleton(); + fhirServerBuilder.Services.AddSingleton(); return fhirServerBuilder; } diff --git a/src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/ITemplateProviderFactory.cs b/src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/ITemplateProviderFactory.cs new file mode 100644 index 0000000000..6a9e88582d --- /dev/null +++ b/src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/ITemplateProviderFactory.cs @@ -0,0 +1,14 @@ +// ------------------------------------------------------------------------------------------------- +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------------------------------------------- + +namespace Microsoft.Health.Fhir.Core.Features.Operations.ConvertData +{ + public interface ITemplateProviderFactory + { + public IConvertDataTemplateProvider GetContainerRegistryTemplateProvider(); + + public IConvertDataTemplateProvider GetDefaultTemplateProvider(); + } +} diff --git a/src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/TemplateProviderFactory.cs b/src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/TemplateProviderFactory.cs new file mode 100644 index 0000000000..e4dcbb5e12 --- /dev/null +++ b/src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/TemplateProviderFactory.cs @@ -0,0 +1,31 @@ +// ------------------------------------------------------------------------------------------------- +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information. +// ------------------------------------------------------------------------------------------------- + +using System; +using EnsureThat; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.Health.Fhir.Core.Features.Operations.ConvertData +{ + public class TemplateProviderFactory : ITemplateProviderFactory + { + private IServiceProvider _sp; + + public TemplateProviderFactory(IServiceProvider sp) + { + _sp = EnsureArg.IsNotNull(sp, nameof(sp)); + } + + public IConvertDataTemplateProvider GetContainerRegistryTemplateProvider() + { + return _sp.GetRequiredService(); + } + + public IConvertDataTemplateProvider GetDefaultTemplateProvider() + { + return _sp.GetRequiredService(); + } + } +} diff --git a/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Operations/ConvertData/ContainerRegistryTemplateProviderTests.cs b/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Operations/ConvertData/ContainerRegistryTemplateProviderTests.cs index 84f2989b3f..66359f1163 100644 --- a/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Operations/ConvertData/ContainerRegistryTemplateProviderTests.cs +++ b/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Operations/ConvertData/ContainerRegistryTemplateProviderTests.cs @@ -38,19 +38,23 @@ public async Task GivenDefaultTemplateReference_WhenFetchingTemplates_DefaultTem } } - [Fact] - public async Task GivenAnInvalidToken_WhenFetchingCustomTemplates_ExceptionShouldBeThrown() + private IConvertDataTemplateProvider GetDefaultTemplateProvider() { - var containerRegistryTemplateProvider = GetDefaultTemplateProvider(); - var templateReference = "test.azurecr.io/templates:latest"; + var convertDataConfig = new ConvertDataConfiguration + { + Enabled = true, + OperationTimeout = TimeSpan.FromSeconds(1), + }; + convertDataConfig.ContainerRegistryServers.Add("test.azurecr.io"); - await Assert.ThrowsAsync(() => containerRegistryTemplateProvider.GetTemplateCollectionAsync(GetRequestWithTemplateReference(templateReference), CancellationToken.None)); + var config = Options.Create(convertDataConfig); + return new DefaultTemplateProvider(config, new NullLogger()); } - private IConvertDataTemplateProvider GetDefaultTemplateProvider() + private IConvertDataTemplateProvider GetCustomTemplateProvider() { IContainerRegistryTokenProvider tokenProvider = Substitute.For(); - tokenProvider.GetTokenAsync(default, default).ReturnsForAnyArgs("Bearer faketoken"); + tokenProvider.GetTokenAsync(default, default).ReturnsForAnyArgs("Faketoken"); var convertDataConfig = new ConvertDataConfiguration { @@ -68,4 +72,3 @@ private ConvertDataRequest GetRequestWithTemplateReference(string templateRefere return new ConvertDataRequest(Samples.SampleHl7v2Message, DataType.Hl7v2, templateReference.Split('/')[0], true, templateReference, "ADT_A01"); } } -} diff --git a/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Operations/ConvertData/ConvertDataEngineTests.cs b/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Operations/ConvertData/ConvertDataEngineTests.cs index 000bcc1a6c..4423264597 100644 --- a/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Operations/ConvertData/ConvertDataEngineTests.cs +++ b/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Operations/ConvertData/ConvertDataEngineTests.cs @@ -132,7 +132,7 @@ public async Task GivenFhirConvertDataRequest_WithADefaultTemplates_CorrectResul [InlineData("¶Š™œãý£¾.com/template:default")] public async Task GivenConvertDataRequest_WithUnconfiguredRegistry_ContainerRegistryNotConfiguredExceptionShouldBeThrown(string templateReference) { - var convertDataEngine = GetDefaultEngine(); + var convertDataEngine = GetCustomEngine(); var hl7v2Request = GetHl7V2RequestWithTemplateReference(templateReference); await Assert.ThrowsAsync(() => convertDataEngine.Process(hl7v2Request, CancellationToken.None)); @@ -256,7 +256,7 @@ public async Task GivenHl7V2TemplateNotInJsonFormat_WhenConvert_ExceptionShouldB { "ADT_A01", Template.Parse(@"""a"":""b""") }, }, }; - var convertDataEngine = GetCustomEngineWithTemplates(wrongTemplateCollection); + var convertDataEngine = GetDefaultEngineWithTemplates(wrongTemplateCollection); var request = GetHl7V2RequestWithDefaultTemplates(); var exception = await Assert.ThrowsAsync(() => convertDataEngine.Process(request, CancellationToken.None)); Assert.True(exception.InnerException is PostprocessException); @@ -272,7 +272,7 @@ public async Task GivenCcdaTemplateNotInJsonFormat_WhenConvert_ExceptionShouldBe { "CCD", Template.Parse(@"""a"":""b""") }, }, }; - var convertDataEngine = GetCustomEngineWithTemplates(wrongTemplateCollection); + var convertDataEngine = GetDefaultEngineWithTemplates(wrongTemplateCollection); var request = GetCcdaRequestWithDefaultTemplates(); var exception = await Assert.ThrowsAsync(() => convertDataEngine.Process(request, CancellationToken.None)); Assert.True(exception.InnerException is PostprocessException); @@ -288,7 +288,7 @@ public async Task GivenJsonTemplateNotInJsonFormat_WhenConvert_ExceptionShouldBe { "ExamplePatient", Template.Parse(@"""a"":""b""") }, }, }; - var convertDataEngine = GetCustomEngineWithTemplates(wrongTemplateCollection); + var convertDataEngine = GetDefaultEngineWithTemplates(wrongTemplateCollection); var request = GetJsonRequestWithDefaultTemplates(); var exception = await Assert.ThrowsAsync(() => convertDataEngine.Process(request, CancellationToken.None)); Assert.True(exception.InnerException is PostprocessException); @@ -304,7 +304,7 @@ public async Task GivenFhirTemplateNotInJsonFormat_WhenConvert_ExceptionShouldBe { "Patient", Template.Parse(@"""a"":""b""") }, }, }; - var convertDataEngine = GetCustomEngineWithTemplates(wrongTemplateCollection); + var convertDataEngine = GetDefaultEngineWithTemplates(wrongTemplateCollection); var request = GetFhirRequestWithDefaultTemplates(); var exception = await Assert.ThrowsAsync(() => convertDataEngine.Process(request, CancellationToken.None)); Assert.True(exception.InnerException is PostprocessException); @@ -393,22 +393,51 @@ private static ConvertDataRequest GetFhirRequestWithRootTemplate(string rootTemp private IConvertDataEngine GetDefaultEngine() { IOptions convertDataConfiguration = Options.Create(_config); - IContainerRegistryTokenProvider tokenProvider = Substitute.For(); - tokenProvider.GetTokenAsync(Arg.Any(), default).ReturnsForAnyArgs(x => GetToken(x[0].ToString(), _config)); - ContainerRegistryTemplateProvider templateProvider = new ContainerRegistryTemplateProvider(tokenProvider, convertDataConfiguration, new NullLogger()); + DefaultTemplateProvider templateProvider = new DefaultTemplateProvider(convertDataConfiguration, new NullLogger()); + ITemplateProviderFactory templateProviderFactory = Substitute.For(); + templateProviderFactory.GetDefaultTemplateProvider().ReturnsForAnyArgs(templateProvider); + + return new ConvertDataEngine( + templateProviderFactory, + convertDataConfiguration, + new NullLogger()); + } + + private IConvertDataEngine GetDefaultEngineWithTemplates(List> templateCollection) + { + var templateProviderFactory = Substitute.For(); + + IConvertDataTemplateProvider templateProvider = Substitute.For(); + + templateProvider.GetTemplateCollectionAsync(default, default).ReturnsForAnyArgs(templateCollection); + templateProviderFactory.GetDefaultTemplateProvider().ReturnsForAnyArgs(templateProvider); + return new ConvertDataEngine(templateProviderFactory, Options.Create(_config), new NullLogger()); + } + + private IConvertDataEngine GetCustomEngine() + { + IOptions convertDataConfiguration = Options.Create(_config); + IContainerRegistryTokenProvider containerRegistryTokenProvider = Substitute.For(); + containerRegistryTokenProvider.GetTokenAsync(Arg.Any(), default).ReturnsForAnyArgs(x => GetToken(x[0].ToString(), _config)); + + ContainerRegistryTemplateProvider templateProvider = new ContainerRegistryTemplateProvider(containerRegistryTokenProvider, convertDataConfiguration, new NullLogger()); + ITemplateProviderFactory templateProviderFactory = Substitute.For(); + templateProviderFactory.GetContainerRegistryTemplateProvider().ReturnsForAnyArgs(templateProvider); return new ConvertDataEngine( - templateProvider, + templateProviderFactory, convertDataConfiguration, new NullLogger()); } private IConvertDataEngine GetCustomEngineWithTemplates(List> templateCollection) { - var templateProvider = Substitute.For(); + var templateProviderFactory = Substitute.For(); + var templateProvider = Substitute.For(); templateProvider.GetTemplateCollectionAsync(default, default).ReturnsForAnyArgs(templateCollection); - return new ConvertDataEngine(templateProvider, Options.Create(_config), new NullLogger()); + templateProviderFactory.GetContainerRegistryTemplateProvider().ReturnsForAnyArgs(templateProvider); + return new ConvertDataEngine(templateProviderFactory, Options.Create(_config), new NullLogger()); } // For unit tests, we only use the built-in templates and here returns an empty token. diff --git a/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Operations/ConvertData/ConvertDataRequestHandlerTests.cs b/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Operations/ConvertData/ConvertDataRequestHandlerTests.cs index 9494c86f4a..e36120f774 100644 --- a/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Operations/ConvertData/ConvertDataRequestHandlerTests.cs +++ b/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Operations/ConvertData/ConvertDataRequestHandlerTests.cs @@ -116,13 +116,12 @@ private ConvertDataRequestHandler GetRequestHandler() IOptions convertDataConfiguration = Options.Create(convertDataConfig); - IContainerRegistryTokenProvider tokenProvider = Substitute.For(); - tokenProvider.GetTokenAsync(Arg.Any(), default).ReturnsForAnyArgs(string.Empty); - - ContainerRegistryTemplateProvider templateProvider = new ContainerRegistryTemplateProvider(tokenProvider, convertDataConfiguration, new NullLogger()); + DefaultTemplateProvider templateProvider = new DefaultTemplateProvider(convertDataConfiguration, new NullLogger()); + ITemplateProviderFactory templateProviderFactory = Substitute.For(); + templateProviderFactory.GetDefaultTemplateProvider().Returns(templateProvider); var convertDataEngine = new ConvertDataEngine( - templateProvider, + templateProviderFactory, convertDataConfiguration, new NullLogger()); From efec9dd3a3b359cf3c09956e69b940d841e08f80 Mon Sep 17 00:00:00 2001 From: Shaun Donnelly Date: Thu, 27 Apr 2023 11:45:59 -0700 Subject: [PATCH 2/3] added missing bracket --- .../ConvertData/ContainerRegistryTemplateProviderTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Operations/ConvertData/ContainerRegistryTemplateProviderTests.cs b/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Operations/ConvertData/ContainerRegistryTemplateProviderTests.cs index 66359f1163..ed786e019c 100644 --- a/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Operations/ConvertData/ContainerRegistryTemplateProviderTests.cs +++ b/src/Microsoft.Health.Fhir.Shared.Core.UnitTests/Features/Operations/ConvertData/ContainerRegistryTemplateProviderTests.cs @@ -72,3 +72,4 @@ private ConvertDataRequest GetRequestWithTemplateReference(string templateRefere return new ConvertDataRequest(Samples.SampleHl7v2Message, DataType.Hl7v2, templateReference.Split('/')[0], true, templateReference, "ADT_A01"); } } +} From 7c60ade549527701deafd88dff65288b05953903 Mon Sep 17 00:00:00 2001 From: Shaun Donnelly Date: Thu, 27 Apr 2023 13:27:54 -0700 Subject: [PATCH 3/3] make sp readonly --- .../Features/Operations/ConvertData/TemplateProviderFactory.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/TemplateProviderFactory.cs b/src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/TemplateProviderFactory.cs index e4dcbb5e12..6cb887f9bf 100644 --- a/src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/TemplateProviderFactory.cs +++ b/src/Microsoft.Health.Fhir.Core/Features/Operations/ConvertData/TemplateProviderFactory.cs @@ -11,7 +11,7 @@ namespace Microsoft.Health.Fhir.Core.Features.Operations.ConvertData { public class TemplateProviderFactory : ITemplateProviderFactory { - private IServiceProvider _sp; + private readonly IServiceProvider _sp; public TemplateProviderFactory(IServiceProvider sp) {