From 3f1fa0293a4866ac7ea5ac510e23e3aa7587409c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ale=C5=A1=20Kalina?= Date: Thu, 26 Sep 2019 16:24:11 +0200 Subject: [PATCH] KCL-1222: Improve naming and documentation of options and builder classes --- .../DeliveryOptionsBuilderTests.cs | 42 ++++++------ .../DeliveryOptionsValidatorTests.cs | 30 ++++---- .../DeliveryClientTests.cs | 8 +-- .../ServiceCollectionsExtensionsTests.cs | 2 +- .../FakeHttpClientTests.cs | 2 +- .../DefaultRetryPolicyProviderTests.cs | 4 +- .../RetryPolicy/DefaultRetryPolicyTests.cs | 24 +++---- .../DeliveryClient/DeliveryClientBuilder.cs | 14 ++-- .../DeliveryClientBuilderImplementation.cs | 10 +-- .../DeliveryClient/IDeliveryClientBuilder.cs | 43 ++++++------ .../DeliveryOptions/DeliveryOptionsBuilder.cs | 43 +++++------- .../DeliveryOptionsValidator.cs | 44 ++++++------ .../IDeliveryOptionsBuilder.cs | 68 +++++++++---------- .../DefaultRetryPolicyOptions.cs | 24 +++++++ .../Configuration/DeliveryOptions .cs | 44 ++++++------ .../Configuration/RetryPolicyOptions.cs | 24 ------- Kentico.Kontent.Delivery/DeliveryClient.cs | 16 ++--- .../RetryPolicy/DefaultRetryPolicy.cs | 13 ++-- .../RetryPolicy/DefaultRetryPolicyProvider.cs | 4 +- .../RetryPolicy/IRetryPolicy.cs | 7 +- .../RetryPolicy/IRetryPolicyProvider.cs | 6 +- 21 files changed, 227 insertions(+), 245 deletions(-) create mode 100644 Kentico.Kontent.Delivery/Configuration/DefaultRetryPolicyOptions.cs delete mode 100644 Kentico.Kontent.Delivery/Configuration/RetryPolicyOptions.cs diff --git a/Kentico.Kontent.Delivery.Tests/Builders/DeliveryOptions/DeliveryOptionsBuilderTests.cs b/Kentico.Kontent.Delivery.Tests/Builders/DeliveryOptions/DeliveryOptionsBuilderTests.cs index 86c7ed59..8226593a 100644 --- a/Kentico.Kontent.Delivery.Tests/Builders/DeliveryOptions/DeliveryOptionsBuilderTests.cs +++ b/Kentico.Kontent.Delivery.Tests/Builders/DeliveryOptions/DeliveryOptionsBuilderTests.cs @@ -21,12 +21,12 @@ public void BuildWithProjectIdAndUseProductionApi() var deliveryOptions = DeliveryOptionsBuilder .CreateInstance() .WithProjectId(ProjectId) - .UseProductionApi + .UseProductionApi() .Build(); Assert.Equal(deliveryOptions.ProjectId, ProjectId); Assert.False(deliveryOptions.UsePreviewApi); - Assert.False(deliveryOptions.UseSecuredProductionApi); + Assert.False(deliveryOptions.UseSecureAccess); } [Fact] @@ -49,40 +49,38 @@ public void BuildWithProjectIdAndSecuredProductionApi() var deliveryOptions = DeliveryOptionsBuilder .CreateInstance() .WithProjectId(ProjectId) - .UseSecuredProductionApi(SecuredApiKey) + .UseProductionApi(SecuredApiKey) .Build(); Assert.Equal(ProjectId, deliveryOptions.ProjectId); - Assert.True(deliveryOptions.UseSecuredProductionApi); - Assert.Equal(SecuredApiKey, deliveryOptions.SecuredProductionApiKey); + Assert.True(deliveryOptions.UseSecureAccess); + Assert.Equal(SecuredApiKey, deliveryOptions.SecureAccessApiKey); } [Fact] public void BuildWithRetryPolicyOptions() { - var retryOptions = new RetryPolicyOptions(); + var retryOptions = new DefaultRetryPolicyOptions(); var deliveryOptions = DeliveryOptionsBuilder .CreateInstance() .WithProjectId(ProjectId) - .UseProductionApi - .WithRetryPolicyOptions(retryOptions) + .UseProductionApi() + .WithDefaultRetryPolicyOptions(retryOptions) .Build(); - Assert.Equal(deliveryOptions.RetryPolicyOptions, retryOptions); + Assert.Equal(deliveryOptions.DefaultRetryPolicyOptions, retryOptions); } [Fact] - public void BuildWithNullRetryPolicyOptions_ResilienceLogicIsDisabled() + public void BuildWithNullRetryPolicyOptions_ThrowsException() { - var deliveryOptions = DeliveryOptionsBuilder + Assert.Throws(() => DeliveryOptionsBuilder .CreateInstance() .WithProjectId(ProjectId) - .UseProductionApi - .WithRetryPolicyOptions(null) - .Build(); - - Assert.False(deliveryOptions.EnableRetryPolicy); + .UseProductionApi() + .WithDefaultRetryPolicyOptions(null) + .Build()); } [Fact] @@ -91,8 +89,8 @@ public void BuildWithDisabledRetryLogic() var deliveryOptions = DeliveryOptionsBuilder .CreateInstance() .WithProjectId(Guid.NewGuid()) - .UseProductionApi - .DisableRetryLogic + .UseProductionApi() + .DisableRetryPolicy() .Build(); Assert.False(deliveryOptions.EnableRetryPolicy); @@ -104,8 +102,8 @@ public void BuildWithWaitForLoadingNewContent() var deliveryOptions = DeliveryOptionsBuilder .CreateInstance() .WithProjectId(Guid.NewGuid()) - .UseProductionApi - .WaitForLoadingNewContent + .UseProductionApi() + .WaitForLoadingNewContent() .Build(); Assert.True(deliveryOptions.WaitForLoadingNewContent); @@ -134,7 +132,7 @@ public void BuildWithCustomEndpointForProductionApi() var deliveryOptions = DeliveryOptionsBuilder .CreateInstance() .WithProjectId(ProjectId) - .UseProductionApi + .UseProductionApi() .WithCustomEndpoint(customEndpoint) .Build(); @@ -166,7 +164,7 @@ public void BuildWithCustomEndpointAsUriForProductionApi() var deliveryOptions = DeliveryOptionsBuilder .CreateInstance() .WithProjectId(ProjectId) - .UseProductionApi + .UseProductionApi() .WithCustomEndpoint(uri) .Build(); diff --git a/Kentico.Kontent.Delivery.Tests/Builders/DeliveryOptions/DeliveryOptionsValidatorTests.cs b/Kentico.Kontent.Delivery.Tests/Builders/DeliveryOptions/DeliveryOptionsValidatorTests.cs index e95c3b4c..63f69e66 100644 --- a/Kentico.Kontent.Delivery.Tests/Builders/DeliveryOptions/DeliveryOptionsValidatorTests.cs +++ b/Kentico.Kontent.Delivery.Tests/Builders/DeliveryOptions/DeliveryOptionsValidatorTests.cs @@ -13,7 +13,7 @@ public void ValidateRetryOptions_NegativeDeltaBackoff_Throws() var deliveryOptions = new Delivery.DeliveryOptions { ProjectId = _guid.ToString(), - RetryPolicyOptions = new RetryPolicyOptions + DefaultRetryPolicyOptions = new DefaultRetryPolicyOptions { DeltaBackoff = TimeSpan.FromSeconds(-1) } @@ -28,7 +28,7 @@ public void ValidateRetryOptions_ZeroDeltaBackoff_Throws() var deliveryOptions = new Delivery.DeliveryOptions { ProjectId = _guid.ToString(), - RetryPolicyOptions = new RetryPolicyOptions + DefaultRetryPolicyOptions = new DefaultRetryPolicyOptions { DeltaBackoff = TimeSpan.Zero } @@ -43,7 +43,7 @@ public void ValidateRetryOptions_NegativeMaxCumulativeWaitTime_Throws() var deliveryOptions = new Delivery.DeliveryOptions { ProjectId = _guid.ToString(), - RetryPolicyOptions = new RetryPolicyOptions + DefaultRetryPolicyOptions = new DefaultRetryPolicyOptions { MaxCumulativeWaitTime = TimeSpan.FromSeconds(-1) } @@ -58,7 +58,7 @@ public void ValidateRetryOptions_ZeroMaxCumulativeWaitTime_Throws() var deliveryOptions = new Delivery.DeliveryOptions { ProjectId = _guid.ToString(), - RetryPolicyOptions = new RetryPolicyOptions + DefaultRetryPolicyOptions = new DefaultRetryPolicyOptions { MaxCumulativeWaitTime = TimeSpan.Zero } @@ -68,15 +68,15 @@ public void ValidateRetryOptions_ZeroMaxCumulativeWaitTime_Throws() } [Fact] - public void ValidateNullRetryOptions_DoesNotThrow() + public void ValidateNullRetryOptions_Throws() { var deliveryOptions = new Delivery.DeliveryOptions { ProjectId = _guid.ToString(), - RetryPolicyOptions = null + DefaultRetryPolicyOptions = null }; - deliveryOptions.Validate(); + Assert.Throws(() => deliveryOptions.Validate()); } [Fact] @@ -122,7 +122,7 @@ public void ValidateOptionsWithNullSecuredApiKey() .CreateInstance() .WithProjectId(_guid); - Assert.Throws(() => deliveryOptionsStep.UseSecuredProductionApi(null)); + Assert.Throws(() => deliveryOptionsStep.UseProductionApi(null)); } [Fact] @@ -146,8 +146,8 @@ public void ValidateOptionsUseOfPreviewAndProductionApiSimultaneously() ProjectId = _guid.ToString(), UsePreviewApi = true, PreviewApiKey = previewApiKey, - UseSecuredProductionApi = true, - SecuredProductionApiKey = productionApiKey + UseSecureAccess = true, + SecureAccessApiKey = productionApiKey }; Assert.Throws(() => deliveryOptions.Validate()); @@ -171,7 +171,7 @@ public void ValidateOptionsWithEnabledSecuredApiWithSetKey() var deliveryOptions = new Delivery.DeliveryOptions { ProjectId = _guid.ToString(), - UseSecuredProductionApi = true + UseSecureAccess = true }; Assert.Throws(() => deliveryOptions.Validate()); @@ -186,7 +186,7 @@ public void ValidateOptionsWithInvalidEndpointFormat(string endpoint) var deliveryOptionsSteps = DeliveryOptionsBuilder .CreateInstance() .WithProjectId(_guid) - .UseProductionApi; + .UseProductionApi(); Assert.Throws(() => deliveryOptionsSteps.WithCustomEndpoint(endpoint)); } @@ -197,7 +197,7 @@ public void ValidateOptionsWithNullUriEndpoint() var deliveryOptionsSteps = DeliveryOptionsBuilder .CreateInstance() .WithProjectId(_guid) - .UseProductionApi; + .UseProductionApi(); Assert.Throws(() => deliveryOptionsSteps.WithCustomEndpoint((Uri)null)); } @@ -209,7 +209,7 @@ public void ValidateOptionsWithUriEndpointWrongScheme() var deliveryOptionsSteps = DeliveryOptionsBuilder .CreateInstance() .WithProjectId(_guid) - .UseProductionApi; + .UseProductionApi(); Assert.Throws(() => deliveryOptionsSteps.WithCustomEndpoint(incorrectSchemeUri)); } @@ -221,7 +221,7 @@ public void ValidateOptionsWithRelativeUriEndpoint() var deliveryOptionsSteps = DeliveryOptionsBuilder .CreateInstance() .WithProjectId(_guid) - .UseProductionApi; + .UseProductionApi(); Assert.Throws(() => deliveryOptionsSteps.WithCustomEndpoint(relativeUri)); } diff --git a/Kentico.Kontent.Delivery.Tests/DeliveryClientTests.cs b/Kentico.Kontent.Delivery.Tests/DeliveryClientTests.cs index 30af6ee2..fb32dcb7 100644 --- a/Kentico.Kontent.Delivery.Tests/DeliveryClientTests.cs +++ b/Kentico.Kontent.Delivery.Tests/DeliveryClientTests.cs @@ -851,9 +851,9 @@ public async void PreviewAndSecuredProductionThrowsWhenBothEnabled(bool usePrevi { ProjectId = _guid.ToString(), UsePreviewApi = usePreviewApi, - UseSecuredProductionApi = useSecuredProduction, + UseSecureAccess = useSecuredProduction, PreviewApiKey = "someKey", - SecuredProductionApiKey = "someKey" + SecureAccessApiKey = "someKey" }; var client = DeliveryClientFactory.GetMockedDeliveryClientWithOptions(options, _mockHttp); @@ -885,8 +885,8 @@ public async void SecuredProductionAddCorrectHeader() var options = new DeliveryOptions { ProjectId = _guid.ToString(), - SecuredProductionApiKey = securityKey, - UseSecuredProductionApi = true + SecureAccessApiKey = securityKey, + UseSecureAccess = true }; _mockHttp .Expect($"{_baseUrl}/items") diff --git a/Kentico.Kontent.Delivery.Tests/Extensions/ServiceCollectionsExtensionsTests.cs b/Kentico.Kontent.Delivery.Tests/Extensions/ServiceCollectionsExtensionsTests.cs index 2b0f8bf7..df5bcf96 100644 --- a/Kentico.Kontent.Delivery.Tests/Extensions/ServiceCollectionsExtensionsTests.cs +++ b/Kentico.Kontent.Delivery.Tests/Extensions/ServiceCollectionsExtensionsTests.cs @@ -72,7 +72,7 @@ public void AddDeliveryClientWithDeliveryOptions_AllServicesAreRegistered() public void AddDeliveryClientWithProjectId_AllServicesAreRegistered() { _fakeServiceCollection.AddDeliveryClient(builder => - builder.WithProjectId(ProjectId).UseProductionApi.Build()); + builder.WithProjectId(ProjectId).UseProductionApi().Build()); AssertDefaultServiceCollection(_expectedInterfacesWithImplementationTypes, _expectedResolvableContentTypes); } diff --git a/Kentico.Kontent.Delivery.Tests/FakeHttpClientTests.cs b/Kentico.Kontent.Delivery.Tests/FakeHttpClientTests.cs index af8d1971..6e9257ca 100644 --- a/Kentico.Kontent.Delivery.Tests/FakeHttpClientTests.cs +++ b/Kentico.Kontent.Delivery.Tests/FakeHttpClientTests.cs @@ -43,7 +43,7 @@ private static DeliveryOptions MockDeliveryOptions(string baseUrl) => DeliveryOptionsBuilder .CreateInstance() .WithProjectId(Guid.NewGuid()) - .UseProductionApi + .UseProductionApi() .WithCustomEndpoint($"{baseUrl}/{{0}}") .Build(); diff --git a/Kentico.Kontent.Delivery.Tests/RetryPolicy/DefaultRetryPolicyProviderTests.cs b/Kentico.Kontent.Delivery.Tests/RetryPolicy/DefaultRetryPolicyProviderTests.cs index 6cd2e82c..35340d39 100644 --- a/Kentico.Kontent.Delivery.Tests/RetryPolicy/DefaultRetryPolicyProviderTests.cs +++ b/Kentico.Kontent.Delivery.Tests/RetryPolicy/DefaultRetryPolicyProviderTests.cs @@ -12,7 +12,7 @@ public void Constructor_NullRetryPolicyOptions_ThrowsArgumentNullException() { var deliveryOptions = Options.Create(new DeliveryOptions { - RetryPolicyOptions = null + DefaultRetryPolicyOptions = null }); Assert.Throws(() => new DefaultRetryPolicyProvider(deliveryOptions)); @@ -23,7 +23,7 @@ public void GetRetryPolicy_ReturnsDefaultPolicy() { var deliveryOptions = Options.Create(new DeliveryOptions { - RetryPolicyOptions = new RetryPolicyOptions() + DefaultRetryPolicyOptions = new DefaultRetryPolicyOptions() }); var provider = new DefaultRetryPolicyProvider(deliveryOptions); diff --git a/Kentico.Kontent.Delivery.Tests/RetryPolicy/DefaultRetryPolicyTests.cs b/Kentico.Kontent.Delivery.Tests/RetryPolicy/DefaultRetryPolicyTests.cs index 6121808f..dc8ab8a8 100644 --- a/Kentico.Kontent.Delivery.Tests/RetryPolicy/DefaultRetryPolicyTests.cs +++ b/Kentico.Kontent.Delivery.Tests/RetryPolicy/DefaultRetryPolicyTests.cs @@ -16,7 +16,7 @@ public class DefaultRetryPolicyTests [Fact] public async Task ExecuteAsync_ResponseOk_DoesNotRetry() { - var options = new RetryPolicyOptions + var options = new DefaultRetryPolicyOptions { DeltaBackoff = TimeSpan.FromSeconds(5) }; @@ -32,7 +32,7 @@ public async Task ExecuteAsync_ResponseOk_DoesNotRetry() [Fact] public async Task ExecuteAsync_RecoversAfterNotSuccessStatusCode() { - var options = new RetryPolicyOptions + var options = new DefaultRetryPolicyOptions { DeltaBackoff = TimeSpan.FromMilliseconds(100) }; @@ -51,7 +51,7 @@ public async Task ExecuteAsync_RecoversAfterNotSuccessStatusCode() [Fact] public async Task ExecuteAsync_RecoversAfterException() { - var options = new RetryPolicyOptions + var options = new DefaultRetryPolicyOptions { DeltaBackoff = TimeSpan.FromMilliseconds(100) }; @@ -72,7 +72,7 @@ public async Task ExecuteAsync_RecoversAfterException() [Fact] public async Task ExecuteAsync_UnsuccessfulStatusCode_RetriesUntilCumulativeWaitTimeReached() { - var options = new RetryPolicyOptions + var options = new DefaultRetryPolicyOptions { DeltaBackoff = TimeSpan.FromMilliseconds(100), MaxCumulativeWaitTime = TimeSpan.FromSeconds(2) @@ -93,7 +93,7 @@ public async Task ExecuteAsync_UnsuccessfulStatusCode_RetriesUntilCumulativeWait [Fact] public async Task ExecuteAsync_Exception_RetriesUntilCumulativeWaitTimeReached() { - var options = new RetryPolicyOptions + var options = new DefaultRetryPolicyOptions { DeltaBackoff = TimeSpan.FromMilliseconds(100), MaxCumulativeWaitTime = TimeSpan.FromSeconds(2) @@ -115,7 +115,7 @@ public async Task ExecuteAsync_Exception_RetriesUntilCumulativeWaitTimeReached() [InlineData(HttpStatusCode.ServiceUnavailable)] public async Task ExecuteAsync_ThrottledRequest_NoHeader_GetsNextWaitTime(HttpStatusCode statusCode) { - var options = new RetryPolicyOptions + var options = new DefaultRetryPolicyOptions { DeltaBackoff = TimeSpan.FromSeconds(10), MaxCumulativeWaitTime = TimeSpan.FromSeconds(5) @@ -136,7 +136,7 @@ public async Task ExecuteAsync_ThrottledRequest_NoHeader_GetsNextWaitTime(HttpSt [InlineData(HttpStatusCode.ServiceUnavailable, 0)] public async Task ExecuteAsync_ThrottledRequest_RetryAfterHeaderWithNotPositiveDelta_GetsNextWaitTime(HttpStatusCode statusCode, int waitTimeInSeconds) { - var options = new RetryPolicyOptions + var options = new DefaultRetryPolicyOptions { DeltaBackoff = TimeSpan.FromSeconds(10), MaxCumulativeWaitTime = TimeSpan.FromSeconds(5) @@ -157,7 +157,7 @@ public async Task ExecuteAsync_ThrottledRequest_RetryAfterHeaderWithNotPositiveD [InlineData(HttpStatusCode.ServiceUnavailable)] public async Task ExecuteAsync_ThrottledRequest_RetryAfterHeaderWithPastDate_GetsNextWaitTime(HttpStatusCode statusCode) { - var options = new RetryPolicyOptions + var options = new DefaultRetryPolicyOptions { DeltaBackoff = TimeSpan.FromSeconds(10), MaxCumulativeWaitTime = TimeSpan.FromSeconds(5) @@ -178,7 +178,7 @@ public async Task ExecuteAsync_ThrottledRequest_RetryAfterHeaderWithPastDate_Get [InlineData(HttpStatusCode.ServiceUnavailable)] public async Task ExecuteAsync_ThrottledRequest_RetryAfterHeaderWithDelta_ReadsWaitTimeFromHeader(HttpStatusCode statusCode) { - var options = new RetryPolicyOptions + var options = new DefaultRetryPolicyOptions { DeltaBackoff = TimeSpan.FromMilliseconds(100), MaxCumulativeWaitTime = TimeSpan.FromSeconds(5) @@ -199,7 +199,7 @@ public async Task ExecuteAsync_ThrottledRequest_RetryAfterHeaderWithDelta_ReadsW [InlineData(HttpStatusCode.ServiceUnavailable)] public async Task ExecuteAsync_ThrottledRequest_RetryAfterHeaderWithDate_ReadsWaitTimeFromHeader(HttpStatusCode statusCode) { - var options = new RetryPolicyOptions + var options = new DefaultRetryPolicyOptions { DeltaBackoff = TimeSpan.FromMilliseconds(100), MaxCumulativeWaitTime = TimeSpan.FromSeconds(5) @@ -224,7 +224,7 @@ public async Task ExecuteAsync_ThrottledRequest_RetryAfterHeaderWithDate_ReadsWa [InlineData(HttpStatusCode.GatewayTimeout)] public async Task ExecuteAsync_RetriesForCertainStatusCodes(HttpStatusCode statusCode) { - var options = new RetryPolicyOptions + var options = new DefaultRetryPolicyOptions { DeltaBackoff = TimeSpan.FromMilliseconds(100) }; @@ -244,7 +244,7 @@ public async Task ExecuteAsync_RetriesForCertainStatusCodes(HttpStatusCode statu [MemberData(nameof(RetriedExceptions))] public async Task ExecuteAsync_RetriesForCertainExceptions(Exception exception) { - var options = new RetryPolicyOptions + var options = new DefaultRetryPolicyOptions { DeltaBackoff = TimeSpan.FromMilliseconds(100) }; diff --git a/Kentico.Kontent.Delivery/Builders/DeliveryClient/DeliveryClientBuilder.cs b/Kentico.Kontent.Delivery/Builders/DeliveryClient/DeliveryClientBuilder.cs index f4e0fa9e..fa30fa47 100644 --- a/Kentico.Kontent.Delivery/Builders/DeliveryClient/DeliveryClientBuilder.cs +++ b/Kentico.Kontent.Delivery/Builders/DeliveryClient/DeliveryClientBuilder.cs @@ -5,30 +5,30 @@ namespace Kentico.Kontent.Delivery { /// - /// A builder class for creating an instance of the interface. + /// A builder of instances. /// public sealed class DeliveryClientBuilder { private static IDeliveryClientBuilder Builder => new DeliveryClientBuilderImplementation(); /// - /// Mandatory step of the for specifying Kentico Kontent project id. + /// Use project identifier. /// - /// The identifier of the Kentico Kontent project. + /// The identifier of a Kentico Kontent project. public static IOptionalClientSetup WithProjectId(string projectId) => Builder.BuildWithProjectId(projectId); /// - /// Mandatory step of the for specifying Kentico Kontent project id. + /// Use project identifier. /// - /// The identifier of the Kentico Kontent project. + /// The identifier of a Kentico Kontent project. public static IOptionalClientSetup WithProjectId(Guid projectId) => Builder.BuildWithProjectId(projectId); /// - /// Mandatory step of the for specifying Kentico Kontent project settings. + /// Use additional configuration. /// - /// A function that is provided with an instance of and expected to return a valid instance of . + /// A delegate that creates an instance of the using the specified . public static IOptionalClientSetup WithOptions(Func buildDeliveryOptions) => Builder.BuildWithDeliveryOptions(buildDeliveryOptions); } diff --git a/Kentico.Kontent.Delivery/Builders/DeliveryClient/DeliveryClientBuilderImplementation.cs b/Kentico.Kontent.Delivery/Builders/DeliveryClient/DeliveryClientBuilderImplementation.cs index 1873ca9a..39a7ae6d 100644 --- a/Kentico.Kontent.Delivery/Builders/DeliveryClient/DeliveryClientBuilderImplementation.cs +++ b/Kentico.Kontent.Delivery/Builders/DeliveryClient/DeliveryClientBuilderImplementation.cs @@ -15,7 +15,6 @@ internal sealed class DeliveryClientBuilderImplementation : IDeliveryClientBuild public IOptionalClientSetup BuildWithDeliveryOptions(Func buildDeliveryOptions) { var builder = DeliveryOptionsBuilder.CreateInstance(); - _deliveryOptions = buildDeliveryOptions(builder); return this; @@ -25,14 +24,14 @@ public IOptionalClientSetup BuildWithProjectId(string projectId) => BuildWithDeliveryOptions(builder => builder .WithProjectId(projectId) - .UseProductionApi + .UseProductionApi() .Build()); public IOptionalClientSetup BuildWithProjectId(Guid projectId) => BuildWithDeliveryOptions(builder => builder .WithProjectId(projectId) - .UseProductionApi + .UseProductionApi() .Build()); IOptionalClientSetup IOptionalClientSetup.WithHttpClient(HttpClient httpClient) @@ -62,16 +61,13 @@ IOptionalClientSetup IOptionalClientSetup.WithPropertyMapper(IPropertyMapper pro IDeliveryClient IDeliveryClientBuild.Build() { _serviceCollection.AddDeliveryClient(_deliveryOptions); - var serviceProvider = _serviceCollection.BuildServiceProvider(); - var client = serviceProvider.GetService(); return client; } - private DeliveryClientBuilderImplementation RegisterOrThrow(TType instance, string parameterName) - where TType : class + private DeliveryClientBuilderImplementation RegisterOrThrow(TType instance, string parameterName) where TType : class { if (instance == null) { diff --git a/Kentico.Kontent.Delivery/Builders/DeliveryClient/IDeliveryClientBuilder.cs b/Kentico.Kontent.Delivery/Builders/DeliveryClient/IDeliveryClientBuilder.cs index 0e3d1446..5db44d39 100644 --- a/Kentico.Kontent.Delivery/Builders/DeliveryClient/IDeliveryClientBuilder.cs +++ b/Kentico.Kontent.Delivery/Builders/DeliveryClient/IDeliveryClientBuilder.cs @@ -7,7 +7,7 @@ namespace Kentico.Kontent.Delivery.Builders.DeliveryClient { /// - /// Defines the contracts of the mandatory steps for building a Kentico Kontent instance. + /// A builder abstraction of mandatory setup of instances. /// public interface IDeliveryClientBuilder { @@ -22,68 +22,67 @@ public interface IDeliveryClientBuilder } /// - /// Defines the contracts of the optional steps for building a Kentico Kontent instance. + /// A builder abstraction of optional setup of instances. /// public interface IOptionalClientSetup : IDeliveryClientBuild { /// - /// Sets a custom HTTP client instance to the instance. + /// Use a custom HTTP client. /// - /// A custom HTTP client instance + /// A custom HTTP client. IOptionalClientSetup WithHttpClient(HttpClient httpClient); /// - /// Sets a custom instance of an object that can resolve links in rich text elements to the instance. + /// Use a custom object to provide URL for content links in rich text elements. /// - /// An instance of an object that can resolve links in rich text elements + /// An instance of the . IOptionalClientSetup WithContentLinkUrlResolver(IContentLinkUrlResolver contentLinkUrlResolver); /// - /// Sets a custom instance of an object that can resolve specific content type of an inline content item to the instance. + /// Use an object to transform linked items and components of the specified type in rich text elements to a valid HTML fragment. /// - /// Content type to be resolved - /// An instance of an object that can resolve component and linked items to HTML markup - /// + /// The type of the linked item or component to transform. + /// An instance of the . IOptionalClientSetup WithInlineContentItemsResolver(IInlineContentItemsResolver inlineContentItemsResolver); /// - /// Sets a custom instance of an object that can resolve modular content in rich text elements to the instance. + /// Use a custom object to transform HTML content of rich text elements. /// - /// An instance of an object that can resolve modular content in rich text elements + /// An instance of the . IOptionalClientSetup WithInlineContentItemsProcessor(IInlineContentItemsProcessor inlineContentItemsProcessor); /// - /// Sets a custom instance of an object that can JSON responses into strongly typed CLR objects to the instance. + /// Use a custom provider to convert JSON data into objects. /// - /// An instance of an object that can JSON responses into strongly typed CLR objects + /// An instance of the . IOptionalClientSetup WithModelProvider(IModelProvider modelProvider); /// - /// Sets a custom instance of an object that can map Kentico Kontent content types to CLR types to the instance. + /// Use a custom provider to map content type codenames to content type objects. /// - /// An instance of an object that can map Kentico Kontent content types to CLR types + /// An instance of the . IOptionalClientSetup WithTypeProvider(ITypeProvider typeProvider); /// - /// Sets a custom instance of a provider of a retry policy to the instance. + /// Use a custom provider to create retry polices for HTTP requests. /// - /// A provider of a retry policy + /// An instance of the . IOptionalClientSetup WithRetryPolicyProvider(IRetryPolicyProvider retryPolicyProvider); /// - /// Sets a custom instance of an object that can map Kentico Kontent content item fields to model properties to the instance. + /// Use a custom mapper to determine relationships between elements of a content item and properties of a model that represents this item. /// - /// An instance of an object that can map Kentico Kontent content item fields to model properties + /// An instance of the . IOptionalClientSetup WithPropertyMapper(IPropertyMapper propertyMapper); } /// - /// Defines the contract of the last build step that initializes a new instance of the interface. + /// A builder abstraction of the last step in the setup of instances. /// public interface IDeliveryClientBuild { /// - /// Initializes a new instance of the interface for retrieving content of the specified project. + /// Returns a new instance of the . /// IDeliveryClient Build(); } diff --git a/Kentico.Kontent.Delivery/Builders/DeliveryOptions/DeliveryOptionsBuilder.cs b/Kentico.Kontent.Delivery/Builders/DeliveryOptions/DeliveryOptionsBuilder.cs index 58ea8175..36794240 100644 --- a/Kentico.Kontent.Delivery/Builders/DeliveryOptions/DeliveryOptionsBuilder.cs +++ b/Kentico.Kontent.Delivery/Builders/DeliveryOptions/DeliveryOptionsBuilder.cs @@ -1,17 +1,17 @@ -using System; -using Kentico.Kontent.Delivery.Builders.DeliveryOptions; +using Kentico.Kontent.Delivery.Builders.DeliveryOptions; +using System; namespace Kentico.Kontent.Delivery { /// - /// A builder class that can be used for creating a instance. + /// A builder of instances. /// public class DeliveryOptionsBuilder : IDeliveryApiConfiguration, IDeliveryOptionsBuilder, IOptionalDeliveryConfiguration { private readonly DeliveryOptions _deliveryOptions = new DeliveryOptions(); /// - /// Creates a new instance of the class for building . + /// Creates a new instance of the class. /// public static IDeliveryOptionsBuilder CreateInstance() => new DeliveryOptionsBuilder(); @@ -34,31 +34,24 @@ IDeliveryApiConfiguration IDeliveryOptionsBuilder.WithProjectId(Guid projectId) return this; } - IOptionalDeliveryConfiguration IOptionalDeliveryConfiguration.WaitForLoadingNewContent + IOptionalDeliveryConfiguration IOptionalDeliveryConfiguration.WaitForLoadingNewContent() { - get - { - _deliveryOptions.WaitForLoadingNewContent = true; + _deliveryOptions.WaitForLoadingNewContent = true; - return this; - } + return this; } - IOptionalDeliveryConfiguration IOptionalDeliveryConfiguration.DisableRetryLogic + IOptionalDeliveryConfiguration IOptionalDeliveryConfiguration.DisableRetryPolicy() { - get - { - _deliveryOptions.EnableRetryPolicy = false; + _deliveryOptions.EnableRetryPolicy = false; - return this; - } + return this; } - IOptionalDeliveryConfiguration IOptionalDeliveryConfiguration.WithRetryPolicyOptions(RetryPolicyOptions options) + IOptionalDeliveryConfiguration IOptionalDeliveryConfiguration.WithDefaultRetryPolicyOptions(DefaultRetryPolicyOptions retryPolicyOptions) { - options?.ValidateRetryPolicyOptions(); - _deliveryOptions.RetryPolicyOptions = options; - _deliveryOptions.EnableRetryPolicy = options != null; + retryPolicyOptions.ValidateRetryPolicyOptions(); + _deliveryOptions.DefaultRetryPolicyOptions = retryPolicyOptions; return this; } @@ -71,14 +64,14 @@ IOptionalDeliveryConfiguration IDeliveryApiConfiguration.UsePreviewApi(string pr return this; } - IOptionalDeliveryConfiguration IDeliveryApiConfiguration.UseProductionApi + IOptionalDeliveryConfiguration IDeliveryApiConfiguration.UseProductionApi() => this; - IOptionalDeliveryConfiguration IDeliveryApiConfiguration.UseSecuredProductionApi(string securedProductionApiKey) + IOptionalDeliveryConfiguration IDeliveryApiConfiguration.UseProductionApi(string secureAccessApiKey) { - securedProductionApiKey.ValidateApiKey(nameof(securedProductionApiKey)); - _deliveryOptions.SecuredProductionApiKey = securedProductionApiKey; - _deliveryOptions.UseSecuredProductionApi = true; + secureAccessApiKey.ValidateApiKey(nameof(secureAccessApiKey)); + _deliveryOptions.SecureAccessApiKey = secureAccessApiKey; + _deliveryOptions.UseSecureAccess = true; return this; } diff --git a/Kentico.Kontent.Delivery/Builders/DeliveryOptions/DeliveryOptionsValidator.cs b/Kentico.Kontent.Delivery/Builders/DeliveryOptions/DeliveryOptionsValidator.cs index 65dc19f6..6ec79f73 100644 --- a/Kentico.Kontent.Delivery/Builders/DeliveryOptions/DeliveryOptionsValidator.cs +++ b/Kentico.Kontent.Delivery/Builders/DeliveryOptions/DeliveryOptionsValidator.cs @@ -4,23 +4,23 @@ namespace Kentico.Kontent.Delivery { /// - /// A class that can be used to validate configuration of the instance. + /// Validates instances of the class. /// public static class DeliveryOptionsValidator { internal static Lazy ApiKeyRegex = new Lazy(() => new Regex(@"[A-Za-z0-9+/]+\.[A-Za-z0-9+/]+\.[A-Za-z0-9+/]+", RegexOptions.Compiled)); /// - /// Validates the instance for correct configuration, i.e, project id format, non-negative number of retry attempts, - /// use of either Preview or Production API and whether an API key is set if the API is used. + /// Validates an instance of the class if it is compatible with . + /// If the configuration is not valid, an exception is thrown. /// - /// A instance. + /// An instance of the class. public static void Validate(this DeliveryOptions deliveryOptions) { ValidateProjectId(deliveryOptions.ProjectId); ValidateUseOfPreviewAndProductionApi(deliveryOptions); ValidateKeyForEnabledApi(deliveryOptions); - deliveryOptions.RetryPolicyOptions?.ValidateRetryPolicyOptions(); + ValidateRetryPolicyOptions(deliveryOptions.DefaultRetryPolicyOptions); } internal static void ValidateProjectId(this string projectId) @@ -37,9 +37,7 @@ internal static void ValidateProjectId(this string projectId) if (!Guid.TryParse(projectId, out var projectIdGuid)) { - throw new ArgumentException( - "Provided string is not a valid project identifier ({ProjectId}). Haven't you accidentally passed the Preview API key instead of the project identifier?", - nameof(projectId)); + throw new ArgumentException("Kentico Kontent project identifier '{ProjectId}' is not valid. Perhaps you have passed an API key instead?", nameof(projectId)); } ValidateProjectId(projectIdGuid); @@ -49,9 +47,7 @@ internal static void ValidateProjectId(this Guid projectId) { if (projectId == Guid.Empty) { - throw new ArgumentException( - "Kentico Kontent project identifier cannot be empty UUID.", - nameof(projectId)); + throw new ArgumentException("Kentico Kontent project identifier is an empty GUID.", nameof(projectId)); } } @@ -61,16 +57,22 @@ internal static void ValidateApiKey(this string apiKey, string parameterName) if (!ApiKeyRegex.Value.IsMatch(apiKey)) { - throw new ArgumentException($"Parameter {parameterName} has invalid format.", parameterName); + throw new ArgumentException($"Parameter {parameterName} is not an API key.", parameterName); } } - internal static void ValidateRetryPolicyOptions(this RetryPolicyOptions retryPolicyOptions) + internal static void ValidateRetryPolicyOptions(this DefaultRetryPolicyOptions retryPolicyOptions) { + if (retryPolicyOptions == null) + { + throw new ArgumentNullException(nameof(retryPolicyOptions), $"Parameter {nameof(retryPolicyOptions)} is not specified."); + } + if (retryPolicyOptions.DeltaBackoff <= TimeSpan.Zero) { throw new ArgumentException($"Parameter {nameof(retryPolicyOptions.DeltaBackoff)} must be a positive timespan."); } + if (retryPolicyOptions.MaxCumulativeWaitTime <= TimeSpan.Zero) { throw new ArgumentException($"Parameter {nameof(retryPolicyOptions.MaxCumulativeWaitTime)} must be a positive timespan."); @@ -85,7 +87,7 @@ internal static void ValidateCustomEndpoint(this string customEndpoint) if (!canCreateUri) { - throw new ArgumentException($"Parameter {nameof(customEndpoint)} has invalid format.", nameof(customEndpoint)); + throw new ArgumentException($"Parameter {nameof(customEndpoint)} is not a valid URL.", nameof(customEndpoint)); } ValidateCustomEndpoint(uriResult); @@ -100,14 +102,14 @@ internal static void ValidateCustomEndpoint(this Uri customEndpoint) if (!customEndpoint.IsAbsoluteUri) { - throw new ArgumentException($"Parameter {nameof(customEndpoint)} has to be an absolute URI.", nameof(customEndpoint)); + throw new ArgumentException($"Parameter {nameof(customEndpoint)} is not an absolute URL.", nameof(customEndpoint)); } var hasCorrectUriScheme = customEndpoint.Scheme == Uri.UriSchemeHttp || customEndpoint.Scheme == Uri.UriSchemeHttps; if (!hasCorrectUriScheme) { - throw new ArgumentException($"Parameter {nameof(customEndpoint)} has unsupported scheme. Please use either http or https.", nameof(customEndpoint)); + throw new ArgumentException($"Parameter {nameof(customEndpoint)} has scheme that is not supported. Please use either HTTP or HTTPS.", nameof(customEndpoint)); } } @@ -128,20 +130,20 @@ private static void ValidateKeyForEnabledApi(this DeliveryOptions deliveryOption { if (deliveryOptions.UsePreviewApi && string.IsNullOrWhiteSpace(deliveryOptions.PreviewApiKey)) { - throw new InvalidOperationException("The Preview API key must be set while using the Preview API."); + throw new InvalidOperationException("The Preview API key must be set to be able to retrieve content with the Preview API."); } - if (deliveryOptions.UseSecuredProductionApi && string.IsNullOrWhiteSpace(deliveryOptions.SecuredProductionApiKey)) + if (deliveryOptions.UseSecureAccess && string.IsNullOrWhiteSpace(deliveryOptions.SecureAccessApiKey)) { - throw new InvalidOperationException("The Secured Production API key must be set while using the Secured Production API."); + throw new InvalidOperationException("The secure access API key must be set to be able to retrieve content with Production API when secure access is enabled."); } } private static void ValidateUseOfPreviewAndProductionApi(this DeliveryOptions deliveryOptions) { - if (deliveryOptions.UsePreviewApi && deliveryOptions.UseSecuredProductionApi) + if (deliveryOptions.UsePreviewApi && deliveryOptions.UseSecureAccess) { - throw new InvalidOperationException("Preview API and Secured Production API can't be used at the same time."); + throw new InvalidOperationException("Preview API and Production API with secured access enabled can't be used at the same time."); } } } diff --git a/Kentico.Kontent.Delivery/Builders/DeliveryOptions/IDeliveryOptionsBuilder.cs b/Kentico.Kontent.Delivery/Builders/DeliveryOptions/IDeliveryOptionsBuilder.cs index 12456233..05aff150 100644 --- a/Kentico.Kontent.Delivery/Builders/DeliveryOptions/IDeliveryOptionsBuilder.cs +++ b/Kentico.Kontent.Delivery/Builders/DeliveryOptions/IDeliveryOptionsBuilder.cs @@ -1,87 +1,84 @@ using System; -using Kentico.Kontent.Delivery.RetryPolicy; namespace Kentico.Kontent.Delivery.Builders.DeliveryOptions { /// - /// Defines the contracts of the mandatory steps for building a instance. + /// A builder abstraction of mandatory setup of instances. /// public interface IDeliveryOptionsBuilder { /// - /// A mandatory step of the for specifying Kentico Kontent project id. + /// Use project identifier. /// - /// The identifier of the Kentico Kontent project. + /// The identifier of a Kentico Kontent project. IDeliveryApiConfiguration WithProjectId(string projectId); /// - /// A mandatory step of the for specifying Kentico Kontent project id. + /// Use project identifier. /// - /// The identifier of the Kentico Kontent project. + /// The identifier of a Kentico Kontent project. IDeliveryApiConfiguration WithProjectId(Guid projectId); } /// - /// Defines the contracts of different APIs that might be used. + /// A builder abstraction of API setup of instances. /// public interface IDeliveryApiConfiguration { /// - /// Sets the Delivery Client to make requests to a Production API. + /// Use Production API with secure access disabled to retrieve content. /// - IOptionalDeliveryConfiguration UseProductionApi { get; } + IOptionalDeliveryConfiguration UseProductionApi(); /// - /// Sets the Delivery Client to make requests to a Preview API. + /// Use Production API with secure access enabled to retrieve content. /// - /// A Preview API key - IOptionalDeliveryConfiguration UsePreviewApi(string previewApiKey); + /// An API key for secure access. + IOptionalDeliveryConfiguration UseProductionApi(string secureAccessApiKey); /// - /// Sets the Delivery Client to make requests to a Secured Production API. + /// Use Preview API to retrieve content. /// - /// An API key for secure access. - IOptionalDeliveryConfiguration UseSecuredProductionApi(string securedProductionApiKey); + /// A Preview API key. + IOptionalDeliveryConfiguration UsePreviewApi(string previewApiKey); } /// - /// Defines the contracts of the optional steps for building a instance. + /// A builder abstraction of optional setup of instances. /// public interface IOptionalDeliveryConfiguration : IDeliveryOptionsBuild { /// - /// An optional step that disables retry policy for HTTP requests. + /// Disable retry policy for HTTP requests. /// - IOptionalDeliveryConfiguration DisableRetryLogic { get; } + IOptionalDeliveryConfiguration DisableRetryPolicy(); /// - /// An optional step that sets the client to wait for updated content. - /// It should be used when you are acting upon a webhook call. + /// Provide content that is always up-to-date. + /// We recommend to wait for new content when you have received a webhook notification. + /// However, the request might take longer than usual to complete. /// - IOptionalDeliveryConfiguration WaitForLoadingNewContent { get; } + IOptionalDeliveryConfiguration WaitForLoadingNewContent(); /// - /// An optional step that sets the custom options for retry policy. + /// Change configuration of the default retry policy. /// - /// - /// The retry policy options in are used only in the default implementation of the interface. - /// Setting the value to null will result in disabled retry policy. - /// If this method does not specify otherwise, the default options will be used. - /// - /// Custom retry policy options. - IOptionalDeliveryConfiguration WithRetryPolicyOptions(RetryPolicyOptions retryPolicyOptions); + /// Configuration of the default retry policy. + IOptionalDeliveryConfiguration WithDefaultRetryPolicyOptions(DefaultRetryPolicyOptions retryPolicyOptions); /// - /// An optional step that sets a custom endpoint for a chosen API. If "{0}" is provided in the URL, it gets replaced by the projectId. + /// Use a custom format for the Production or Preview API endpoint address. + /// The project identifier will be inserted at the position of the first format item "{0}". /// /// /// While both HTTP and HTTPS protocols are supported, we recommend always using HTTPS. /// - /// A custom endpoint URL address. + /// A custom format for the Production API endpoint address. IOptionalDeliveryConfiguration WithCustomEndpoint(string customEndpoint); /// - /// An optional step that sets a custom endpoint for a chosen API. + /// Use a custom format for the Production or Preview API endpoint address. + /// The project identifier will be inserted at the position of the first format item "{0}". /// /// /// While both HTTP and HTTPS protocols are supported, we recommend always using HTTPS. @@ -89,16 +86,15 @@ public interface IOptionalDeliveryConfiguration : IDeliveryOptionsBuild /// A custom endpoint URI. IOptionalDeliveryConfiguration WithCustomEndpoint(Uri customEndpoint); } - + /// - /// Defines the contract of the last build step that creates a new instance of the of the class. + /// A builder abstraction of the last step in setup of instances. /// public interface IDeliveryOptionsBuild { /// - /// Creates a new instance of the class that configures the Kentico Delivery Client. + /// Returns a new instance of the class. /// - /// A new instance Delivery.DeliveryOptions Build(); } } diff --git a/Kentico.Kontent.Delivery/Configuration/DefaultRetryPolicyOptions.cs b/Kentico.Kontent.Delivery/Configuration/DefaultRetryPolicyOptions.cs new file mode 100644 index 00000000..6e74611d --- /dev/null +++ b/Kentico.Kontent.Delivery/Configuration/DefaultRetryPolicyOptions.cs @@ -0,0 +1,24 @@ +using System; +using Kentico.Kontent.Delivery.RetryPolicy; + +namespace Kentico.Kontent.Delivery +{ + /// + /// Represents configuration of the that performs retries using a randomized exponential back off scheme to determine the interval between retries. + /// + public class DefaultRetryPolicyOptions + { + /// + /// Gets or sets the back-off interval between retries. + /// The default value is 1 second. + /// + public TimeSpan DeltaBackoff { get; set; } = TimeSpan.FromSeconds(1); + + /// + /// Gets or sets the maximum cumulative wait time. + /// If the cumulative wait time exceeds this value, the client will stop retrying and return the error to the application. + /// The default value is 30 seconds. + /// + public TimeSpan MaxCumulativeWaitTime { get; set; } = TimeSpan.FromSeconds(30); + } +} \ No newline at end of file diff --git a/Kentico.Kontent.Delivery/Configuration/DeliveryOptions .cs b/Kentico.Kontent.Delivery/Configuration/DeliveryOptions .cs index 082092d9..14c7cf3d 100644 --- a/Kentico.Kontent.Delivery/Configuration/DeliveryOptions .cs +++ b/Kentico.Kontent.Delivery/Configuration/DeliveryOptions .cs @@ -1,67 +1,65 @@ namespace Kentico.Kontent.Delivery { /// - /// Keeps settings which are provided by customer or have default values, used in . + /// Represents configuration of the . /// public class DeliveryOptions { /// - /// Gets or sets the Production endpoint address. + /// Gets or sets the format of the Production API endpoint address. + /// The project identifier will be inserted at the position of the first format item "{0}". /// public string ProductionEndpoint { get; set; } = "https://deliver.kontent.ai/{0}"; /// - /// Gets or sets the Preview endpoint address. + /// Gets or sets the format of the Preview API endpoint address. + /// The project identifier will be inserted at the position of the first format item "{0}". /// public string PreviewEndpoint { get; set; } = "https://preview-deliver.kontent.ai/{0}"; /// - /// Gets or sets the Project identifier. + /// Gets or sets the project identifier. /// public string ProjectId { get; set; } /// - /// Gets or sets the Preview API key. + /// Gets or sets the API key that is used to retrieve content with the Preview API. /// public string PreviewApiKey { get; set; } /// - /// Gets or sets whether the Preview API should be used. If TRUE, needs to be set as well. + /// Gets or sets a value that determines if the Preview API is used to retrieve content. + /// If the Preview API is used the must be set. /// - /// - /// This property enables quick toggling between production and preview configuration even with set. - /// It can be used for debugging and verification of unpublished content in time-critical scenarios, however, we recommend - /// working with only either the production or preview Delivery API, not both, within a single project. - /// public bool UsePreviewApi { get; set; } /// - /// Set to true if you want to wait for updated content. It should be used when you are acting upon a webhook call. + /// Gets or sets a value that determines if the client provides content that is always up-to-date. + /// We recommend to wait for new content when you have received a webhook notification. + /// However, the request might take longer than usual to complete. /// public bool WaitForLoadingNewContent { get; set; } /// - /// Gets or sets whether the production Delivery API will be accessed using an API key. + /// Gets or sets a value that determines if the client sends the secure access API key to retrieve content with the Production API. + /// This key is required to retrieve content when secure access is enabled. + /// To retrieve content when secure access is enabled the must be set. /// - /// - /// This property enables quick toggling between production and secured production configuration even with set. - /// - public bool UseSecuredProductionApi { get; set; } + public bool UseSecureAccess { get; set; } /// - /// Gets or sets the production Delivery API key. + /// Gets or sets the API key that is used to retrieve content with the Production API when secure access is enabled. /// - public string SecuredProductionApiKey { get; set; } + public string SecureAccessApiKey { get; set; } /// - /// Gets or sets whether a retry policy (fallback) will be used for HTTP requests. + /// Gets or sets a value that determines whether a retry policy is used to make HTTP requests. /// public bool EnableRetryPolicy { get; set; } = true; - /// - /// Gets or sets the options for retry policy used in . + /// Gets or sets configuration of the default retry policy. /// - public RetryPolicyOptions RetryPolicyOptions { get; set; } = new RetryPolicyOptions(); + public DefaultRetryPolicyOptions DefaultRetryPolicyOptions { get; set; } = new DefaultRetryPolicyOptions(); } } diff --git a/Kentico.Kontent.Delivery/Configuration/RetryPolicyOptions.cs b/Kentico.Kontent.Delivery/Configuration/RetryPolicyOptions.cs deleted file mode 100644 index 39e6a94a..00000000 --- a/Kentico.Kontent.Delivery/Configuration/RetryPolicyOptions.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using Kentico.Kontent.Delivery.RetryPolicy; - -namespace Kentico.Kontent.Delivery -{ - /// - /// The retry policy options that are used in the default implementation of the interface. - /// - public class RetryPolicyOptions - { - /// - /// Gets or sets the backoff interval associated with the retry. - /// The default is 1 second. - /// - public TimeSpan DeltaBackoff { get; set; } = TimeSpan.FromSeconds(1); - - /// - /// Gets or sets the cumulative wait time associated with the retry. - /// When cumulative wait time is reached the policy will return last response message or rethrow last handled exception. - /// The default is 30 seconds. - /// - public TimeSpan MaxCumulativeWaitTime { get; set; } = TimeSpan.FromSeconds(30); - } -} \ No newline at end of file diff --git a/Kentico.Kontent.Delivery/DeliveryClient.cs b/Kentico.Kontent.Delivery/DeliveryClient.cs index acb15097..110f0dd1 100644 --- a/Kentico.Kontent.Delivery/DeliveryClient.cs +++ b/Kentico.Kontent.Delivery/DeliveryClient.cs @@ -469,9 +469,9 @@ public async Task GetTaxonomiesAsync(IEnumerabl private async Task GetDeliverResponseAsync(string endpointUrl, string continuationToken = null) { - if (DeliveryOptions.UsePreviewApi && DeliveryOptions.UseSecuredProductionApi) + if (DeliveryOptions.UsePreviewApi && DeliveryOptions.UseSecureAccess) { - throw new InvalidOperationException("Preview API and secured Delivery API must not be configured at the same time."); + throw new InvalidOperationException("Preview API and Production API with secured access enabled can't be used at the same time."); } if (DeliveryOptions.EnableRetryPolicy) @@ -499,9 +499,9 @@ private Task SendHttpMessage(string endpointUrl, string con message.Headers.AddWaitForLoadingNewContentHeader(); } - if (UseSecuredProductionApi()) + if (UseSecureAccess()) { - message.Headers.AddAuthorizationHeader("Bearer", DeliveryOptions.SecuredProductionApiKey); + message.Headers.AddAuthorizationHeader("Bearer", DeliveryOptions.SecureAccessApiKey); } if (UsePreviewApi()) @@ -517,9 +517,9 @@ private Task SendHttpMessage(string endpointUrl, string con return HttpClient.SendAsync(message); } - private bool UseSecuredProductionApi() + private bool UseSecureAccess() { - return DeliveryOptions.UseSecuredProductionApi && !string.IsNullOrEmpty(DeliveryOptions.SecuredProductionApiKey); + return DeliveryOptions.UseSecureAccess && !string.IsNullOrEmpty(DeliveryOptions.SecureAccessApiKey); } private bool UsePreviewApi() @@ -540,13 +540,13 @@ private async Task GetResponseContent(HttpResponseMessage httpRespo string faultContent = null; - // The null-coallescing operator causes tests to fail for NREs, hence the "if" statement. + // The null-coalescing operator causes tests to fail for NREs, hence the "if" statement. if (httpResponseMessage?.Content != null) { faultContent = await httpResponseMessage.Content.ReadAsStringAsync(); } - throw new DeliveryException(httpResponseMessage, "Either the retry policy was disabled or all retry attempts were depleted.\nFault content:\n" + faultContent); + throw new DeliveryException(httpResponseMessage, $"There was an error while fetching content:\nStatus:{httpResponseMessage.StatusCode}\nReason:{httpResponseMessage.ReasonPhrase}\n\n{faultContent}"); } private bool HasStaleContent(HttpResponseMessage httpResponseMessage) diff --git a/Kentico.Kontent.Delivery/RetryPolicy/DefaultRetryPolicy.cs b/Kentico.Kontent.Delivery/RetryPolicy/DefaultRetryPolicy.cs index a124e300..98fa9771 100644 --- a/Kentico.Kontent.Delivery/RetryPolicy/DefaultRetryPolicy.cs +++ b/Kentico.Kontent.Delivery/RetryPolicy/DefaultRetryPolicy.cs @@ -23,7 +23,7 @@ internal class DefaultRetryPolicy : IRetryPolicy private static readonly HttpStatusCode[] StatusCodesToRetry = { HttpStatusCode.RequestTimeout, - (HttpStatusCode)429, //TooManyRequest + (HttpStatusCode)429, // Too Many Requests HttpStatusCode.InternalServerError, HttpStatusCode.BadGateway, HttpStatusCode.ServiceUnavailable, @@ -31,13 +31,13 @@ internal class DefaultRetryPolicy : IRetryPolicy }; private static readonly HttpStatusCode[] StatusCodesWithPossibleRetryHeader = { - (HttpStatusCode)429, //TooManyRequest + (HttpStatusCode)429, // Too Many Requests HttpStatusCode.ServiceUnavailable, }; - private readonly RetryPolicyOptions _options; + private readonly DefaultRetryPolicyOptions _options; - public DefaultRetryPolicy(RetryPolicyOptions options) + public DefaultRetryPolicy(DefaultRetryPolicyOptions options) { _options = options; } @@ -61,8 +61,8 @@ public async Task ExecuteAsync(Func TimeSpan.Zero - ? retryHeader + waitTime = StatusCodesWithPossibleRetryHeader.Contains(response.StatusCode) && response.Headers.TryGetRetryHeader(out var retryAfter) && retryAfter > TimeSpan.Zero + ? retryAfter : GetNextWaitTime(retryAttempts); } @@ -74,6 +74,7 @@ public async Task ExecuteAsync(Func options) { - _retryPolicyOptions = options.Value.RetryPolicyOptions ?? throw new ArgumentNullException(nameof(options)); + _retryPolicyOptions = options.Value.DefaultRetryPolicyOptions ?? throw new ArgumentNullException(nameof(options)); } public IRetryPolicy GetRetryPolicy() => new DefaultRetryPolicy(_retryPolicyOptions); diff --git a/Kentico.Kontent.Delivery/RetryPolicy/IRetryPolicy.cs b/Kentico.Kontent.Delivery/RetryPolicy/IRetryPolicy.cs index 65b20d91..9fdaac10 100644 --- a/Kentico.Kontent.Delivery/RetryPolicy/IRetryPolicy.cs +++ b/Kentico.Kontent.Delivery/RetryPolicy/IRetryPolicy.cs @@ -1,19 +1,18 @@ using System; using System.Net.Http; -using System.Threading; using System.Threading.Tasks; namespace Kentico.Kontent.Delivery.RetryPolicy { /// - /// Requests handling retry policy + /// Represents a retry policy for HTTP requests. /// public interface IRetryPolicy { /// - /// Executes the specified asynchronous request within policy and returns result + /// Invokes the specified request delegate within policy. /// - /// The action to perform + /// The request delegate to invoke. /// A response message returned by . Task ExecuteAsync(Func> sendRequest); } diff --git a/Kentico.Kontent.Delivery/RetryPolicy/IRetryPolicyProvider.cs b/Kentico.Kontent.Delivery/RetryPolicy/IRetryPolicyProvider.cs index 2fb7a752..1d1e3b65 100644 --- a/Kentico.Kontent.Delivery/RetryPolicy/IRetryPolicyProvider.cs +++ b/Kentico.Kontent.Delivery/RetryPolicy/IRetryPolicyProvider.cs @@ -1,14 +1,14 @@ namespace Kentico.Kontent.Delivery.RetryPolicy { /// - /// Provides a retry policy instance if enabled + /// Provides a retry policy for . /// public interface IRetryPolicyProvider { /// - /// Gets the retry policy instance. + /// Returns a new instance of a retry policy. /// - /// + /// A new instance of a retry policy. IRetryPolicy GetRetryPolicy(); } } \ No newline at end of file