From 477a1e7c2a0233b55fbb0f8b7032d0bad993d9c2 Mon Sep 17 00:00:00 2001 From: Anthony Timmers Date: Fri, 26 Sep 2025 17:47:29 +0200 Subject: [PATCH 1/6] Make run skipped tests again --- src/Signhost.APIClient.Tests/SignhostApiRetryClientTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Signhost.APIClient.Tests/SignhostApiRetryClientTests.cs b/src/Signhost.APIClient.Tests/SignhostApiRetryClientTests.cs index 28881d2..f99936e 100644 --- a/src/Signhost.APIClient.Tests/SignhostApiRetryClientTests.cs +++ b/src/Signhost.APIClient.Tests/SignhostApiRetryClientTests.cs @@ -346,7 +346,7 @@ public void When_All_Calls_Fail_DeleteTransactionAsync_Should_Throw_Exception() /// Tests if the api call fails as expected the fourth time around. /// So the retry policy is used and a exception is thrown. /// - [Fact(Skip = "Current method of the base library hasn't implemented SignhostRestApiClientException yet.")] + [Fact] public void When_All_Calls_Fails_GetDocumentAsync_Should_Throw_Exception() { Func apiCall = () => @@ -360,7 +360,7 @@ public void When_All_Calls_Fails_GetDocumentAsync_Should_Throw_Exception() /// Tests if the api call fails as expected the fourth time around. /// So the retry policy is used and a exception is thrown. /// - [Fact(Skip = "Current method of the base library hasn't implemented SignhostRestApiClientException yet.")] + [Fact] public void When_All_Calls_Fail_GetReceiptAsync_Should_Throw_Exception() { Func apiCall = () => From 3ecb2516b4c349fa84964e703689997f3b7dfcae Mon Sep 17 00:00:00 2001 From: Anthony Timmers Date: Fri, 21 Nov 2025 19:29:00 +0100 Subject: [PATCH 2/6] Remove NCrunch entries --- .gitignore | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.gitignore b/.gitignore index 41faeb1..a283660 100644 --- a/.gitignore +++ b/.gitignore @@ -103,11 +103,6 @@ _TeamCity* # DotCover is a Code Coverage Tool *.dotCover -# NCrunch -_NCrunch_* -.*crunch*.local.xml -*.v3.ncrunchsolution.user - # MightyMoose *.mm.* AutoTest.Net/ From fb2f1d87efd766cb0077765549593b84909a983b Mon Sep 17 00:00:00 2001 From: Anthony Timmers Date: Fri, 21 Nov 2025 19:32:34 +0100 Subject: [PATCH 3/6] Update additional target frameworks up to .NET 10 --- .github/workflows/publish_nuget_package.yml | 2 +- src/Signhost.APIClient.Tests/Signhost.APIClient.Tests.csproj | 2 +- src/Signhost.APIClient/Signhost.APIClient.csproj | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish_nuget_package.yml b/.github/workflows/publish_nuget_package.yml index f2a9d49..e13ae23 100644 --- a/.github/workflows/publish_nuget_package.yml +++ b/.github/workflows/publish_nuget_package.yml @@ -42,7 +42,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v5 with: - dotnet-version: '8.x' + dotnet-version: '10.x' - name: Clear NuGet Cache run: dotnet nuget locals all --clear diff --git a/src/Signhost.APIClient.Tests/Signhost.APIClient.Tests.csproj b/src/Signhost.APIClient.Tests/Signhost.APIClient.Tests.csproj index 9d82d4b..ab0067c 100644 --- a/src/Signhost.APIClient.Tests/Signhost.APIClient.Tests.csproj +++ b/src/Signhost.APIClient.Tests/Signhost.APIClient.Tests.csproj @@ -1,6 +1,6 @@ - net8.0 + net10.0 false diff --git a/src/Signhost.APIClient/Signhost.APIClient.csproj b/src/Signhost.APIClient/Signhost.APIClient.csproj index 0f9b5c3..bcf9f4e 100644 --- a/src/Signhost.APIClient/Signhost.APIClient.csproj +++ b/src/Signhost.APIClient/Signhost.APIClient.csproj @@ -1,6 +1,7 @@  - netstandard2.0 + net10.0;net9.0;net8.0;netstandard2.0;net462 + 10 Signhost.APIClient From b621e84f59ed519c88379e072f966c2541937e8b Mon Sep 17 00:00:00 2001 From: Anthony Timmers Date: Fri, 21 Nov 2025 19:35:44 +0100 Subject: [PATCH 4/6] Fix casing inconsistencies for Signhost --- README.md | 5 ++-- .../SignhostApiRetryClientTests.cs | 18 +++++------ .../Rest/Polly/SignHostAPIRetryClient.cs | 30 +++++++++---------- 3 files changed, 26 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 9d20050..3c2d85a 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,7 @@ For full API documentation, please visit [evidos.github.io](https://evidos.githu For detailed examples, visit: [https://github.com/Evidos/SignhostClientLibrary/blob/master/README.md](https://github.com/Evidos/SignhostClientLibrary/blob/master/README.md) ```c# -var settings = new SignHostApiClientSettings("YourAppKey", "apikey or usertoken"); - -var retryClient = new SignHostApiRetryClient(settings); +var settings = new SignhostApiClientSettings("YourAppKey", "apikey or usertoken"); +var retryClient = new SignhostApiRetryClient(settings); ``` diff --git a/src/Signhost.APIClient.Tests/SignhostApiRetryClientTests.cs b/src/Signhost.APIClient.Tests/SignhostApiRetryClientTests.cs index f99936e..410e82e 100644 --- a/src/Signhost.APIClient.Tests/SignhostApiRetryClientTests.cs +++ b/src/Signhost.APIClient.Tests/SignhostApiRetryClientTests.cs @@ -17,16 +17,16 @@ namespace SignhostAPIRetryClient.Tests { /// - /// Tests the SignHostApiRetryClient. + /// Tests the SignhostApiRetryClient. /// public class SignhostApiRetryClientTests : IDisposable { - private readonly SignHostApiClientSettings settings; + private readonly SignhostApiClientSettings settings; - private readonly SignHostApiRetryClient firstCallSucceedsClient; - private readonly SignHostApiRetryClient thirdCallSucceedsClient; - private readonly SignHostApiRetryClient allCallsFailClient; + private readonly SignhostApiRetryClient firstCallSucceedsClient; + private readonly SignhostApiRetryClient thirdCallSucceedsClient; + private readonly SignhostApiRetryClient allCallsFailClient; private readonly MemoryStream documentFile; @@ -36,12 +36,12 @@ public class SignhostApiRetryClientTests /// public SignhostApiRetryClientTests() { - settings = new SignHostApiClientSettings( + settings = new SignhostApiClientSettings( "AppKey") { Endpoint = "http://localhost/api/", }; - firstCallSucceedsClient = new SignHostApiRetryClient( + firstCallSucceedsClient = new SignhostApiRetryClient( settings, new HttpClient( SetupMockedHandler( @@ -50,7 +50,7 @@ public SignhostApiRetryClientTests() HttpStatusCode.InternalServerError, HttpStatusCode.InternalServerError))); - thirdCallSucceedsClient = new SignHostApiRetryClient( + thirdCallSucceedsClient = new SignhostApiRetryClient( settings, new HttpClient( SetupMockedHandler( @@ -59,7 +59,7 @@ public SignhostApiRetryClientTests() HttpStatusCode.OK, HttpStatusCode.InternalServerError))); - allCallsFailClient = new SignHostApiRetryClient( + allCallsFailClient = new SignhostApiRetryClient( settings, new HttpClient( SetupMockedHandler( diff --git a/src/Signhost.APIClient/Rest/Polly/SignHostAPIRetryClient.cs b/src/Signhost.APIClient/Rest/Polly/SignHostAPIRetryClient.cs index e08da3a..fa1a28b 100644 --- a/src/Signhost.APIClient/Rest/Polly/SignHostAPIRetryClient.cs +++ b/src/Signhost.APIClient/Rest/Polly/SignHostAPIRetryClient.cs @@ -11,44 +11,44 @@ namespace Signhost.APIClient.Rest.Polly { /// - /// Implements the interface which provides + /// Implements the interface which provides /// a signhost api client implementation. /// - public class SignHostApiRetryClient - : ISignHostApiClient + public class SignhostApiRetryClient + : ISignhostApiClient , IDisposable { - private readonly SignHostApiClient client; + private readonly SignhostApiClient client; private readonly AsyncPolicy retryPolicy; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// This client has a built-in retry mechanism. - /// Set your usertoken and APPKey by creating a . + /// Set your usertoken and APPKey by creating a . /// - /// . + /// . /// An to use instead of the default. - public SignHostApiRetryClient( - ISignHostApiClientSettings settings, + public SignhostApiRetryClient( + ISignhostApiClientSettings settings, AsyncPolicy? policy = null) : this(settings, new HttpClient(), policy) { } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// This client has a built-in retry mechanism. - /// Set your usertoken and APPKey by creating a . + /// Set your usertoken and APPKey by creating a . /// - /// . + /// . /// to use for all http calls. /// An to use instead of the default. - public SignHostApiRetryClient( - ISignHostApiClientSettings settings, + public SignhostApiRetryClient( + ISignhostApiClientSettings settings, HttpClient httpClient, AsyncPolicy? policy = null) { - client = new SignHostApiClient(settings, httpClient); + client = new SignhostApiClient(settings, httpClient); if (policy is null) { retryPolicy = GetDefaultPolicy(); From c840bf7a3fdc25336ab3e555a25b10396d08234e Mon Sep 17 00:00:00 2001 From: Anthony Timmers Date: Fri, 21 Nov 2025 19:38:16 +0100 Subject: [PATCH 5/6] Reformat to file-scoped namespace --- .../SignhostApiRetryClientTests.cs | 831 +++++++++--------- .../Rest/Polly/SignHostAPIRetryClient.cs | 569 ++++++------ 2 files changed, 699 insertions(+), 701 deletions(-) diff --git a/src/Signhost.APIClient.Tests/SignhostApiRetryClientTests.cs b/src/Signhost.APIClient.Tests/SignhostApiRetryClientTests.cs index 410e82e..7f2bcea 100644 --- a/src/Signhost.APIClient.Tests/SignhostApiRetryClientTests.cs +++ b/src/Signhost.APIClient.Tests/SignhostApiRetryClientTests.cs @@ -14,425 +14,424 @@ using Signhost.APIClient.Rest.Polly; using Xunit; -namespace SignhostAPIRetryClient.Tests +namespace SignhostAPIRetryClient.Tests; + +/// +/// Tests the SignhostApiRetryClient. +/// +public class SignhostApiRetryClientTests + : IDisposable { + private readonly SignhostApiClientSettings settings; + + private readonly SignhostApiRetryClient firstCallSucceedsClient; + private readonly SignhostApiRetryClient thirdCallSucceedsClient; + private readonly SignhostApiRetryClient allCallsFailClient; + + private readonly MemoryStream documentFile; + + /// + /// Initializes a new instance of the class. + /// Sets up the mocked handlers for the HttpClient. + /// + public SignhostApiRetryClientTests() + { + settings = new SignhostApiClientSettings( + "AppKey") { + Endpoint = "http://localhost/api/", + }; + + firstCallSucceedsClient = new SignhostApiRetryClient( + settings, + new HttpClient( + SetupMockedHandler( + HttpStatusCode.OK, + HttpStatusCode.InternalServerError, + HttpStatusCode.InternalServerError, + HttpStatusCode.InternalServerError))); + + thirdCallSucceedsClient = new SignhostApiRetryClient( + settings, + new HttpClient( + SetupMockedHandler( + HttpStatusCode.InternalServerError, + HttpStatusCode.InternalServerError, + HttpStatusCode.OK, + HttpStatusCode.InternalServerError))); + + allCallsFailClient = new SignhostApiRetryClient( + settings, + new HttpClient( + SetupMockedHandler( + HttpStatusCode.InternalServerError, + HttpStatusCode.InternalServerError, + HttpStatusCode.InternalServerError, + HttpStatusCode.InternalServerError))); + + documentFile = new MemoryStream(); + } + + /// + /// Tests if the api call works as expected the first time around. + /// So the retry policy isn't used and no exception is thrown. + /// + [Fact] + public void When_First_Call_Succeeds_AddOrReplaceFileMetaToTransactionAsync_Should_Not_Throw_Exception() + { + Func apiCall = () => + firstCallSucceedsClient.AddOrReplaceFileMetaToTransactionAsync( + new FileMeta(), + "Transaction Id", + "File Id"); + apiCall.Should().NotThrowAsync(); + } + + /// + /// Tests if the api call works as expected the first time around. + /// So the retry policy isn't used and no exception is thrown. + /// + [Fact] + public void When_First_Call_Succeeds_AddOrReplaceFileToTransactionAsync_Should_Not_Throw_Exception() + { + Func apiCall = () => + firstCallSucceedsClient.AddOrReplaceFileToTransactionAsync( + documentFile, + "Transaction Id", + "File Id", + new FileUploadOptions()); + apiCall.Should().NotThrowAsync(); + } + + /// + /// Tests if the api call works as expected the first time around. + /// So the retry policy isn't used and no exception is thrown. + /// + [Fact] + public void When_First_Call_Succeeds_CreateTransactionAsync_Should_Not_Throw_Exception() + { + Func apiCall = () => + firstCallSucceedsClient.CreateTransactionAsync(new Transaction()); + apiCall.Should().NotThrowAsync(); + } + + /// + /// Tests if the api call works as expected the first time around. + /// So the retry policy isn't used and no exception is thrown. + /// + [Fact] + public void When_First_Call_Succeeds_DeleteTransactionAsync_Should_Not_Throw_Exception() + { + Func apiCall = () => + firstCallSucceedsClient.DeleteTransactionAsync( + "Transaction Id", + new DeleteTransactionOptions()); + apiCall.Should().NotThrowAsync(); + } + + /// + /// Tests if the api call works as expected the first time around. + /// So the retry policy isn't used and no exception is thrown. + /// + [Fact] + public void When_First_Call_Succeeds_GetDocumentAsync_Should_Not_Throw_Exception() + { + Func apiCall = () => + firstCallSucceedsClient.GetDocumentAsync( + "Transaction Id", + "File Id"); + apiCall.Should().NotThrowAsync(); + } + + /// + /// Tests if the api call works as expected the first time around. + /// So the retry policy isn't used and no exception is thrown. + /// + [Fact] + public void When_First_Call_Succeeds_GetReceiptAsync_Should_Not_Throw_Exception() + { + Func apiCall = () => + firstCallSucceedsClient.GetReceiptAsync("Transaction Id"); + apiCall.Should().NotThrowAsync(); + } + + /// + /// Tests if the api call works as expected the first time around. + /// So the retry policy isn't used and no exception is thrown. + /// + [Fact] + public void When_First_Call_Succeeds_GetTransactionAsync_Should_Not_Throw_Exception() + { + Func apiCall = () => + firstCallSucceedsClient.GetTransactionAsync("transaction Id"); + apiCall.Should().NotThrowAsync(); + } + + /// + /// Tests if the api call works as expected the first time around. + /// So the retry policy isn't used and no exception is thrown. + /// + [Fact] + public void When_First_Call_Succeeds_GetTransactionResponseAsync_Should_Not_Throw_Exception() + { + Func apiCall = () => + firstCallSucceedsClient.GetTransactionResponseAsync("Transaction Id"); + apiCall.Should().NotThrowAsync(); + } + + /// + /// Tests if the api call works as expected the third time around. + /// So the retry policy is used and no exception is thrown. + /// + [Fact] + public void When_Third_Call_Succeeds_AddOrReplaceFileMetaToTransactionAsync_Should_Not_Throw_Exception() + { + Func apiCall = () + => thirdCallSucceedsClient.AddOrReplaceFileMetaToTransactionAsync( + new FileMeta(), + "Transaction Id", + "File Id"); + apiCall.Should().NotThrowAsync(); + } + + /// + /// Tests if the api call works as expected the third time around. + /// So the retry policy is used and no exception is thrown. + /// + [Fact] + public void When_Third_Call_Succeeds_AddOrReplaceFileToTransactionAsync_Should_Not_Throw_Exception() + { + Func apiCall = () => + thirdCallSucceedsClient.AddOrReplaceFileToTransactionAsync( + documentFile, + "Transaction Id", + "File Id", + new FileUploadOptions()); + apiCall.Should().NotThrowAsync(); + } + + /// + /// Tests if the api call works as expected the third time around. + /// So the retry policy is used and no exception is thrown. + /// + [Fact] + public void When_Third_Call_Succeeds_CreateTransactionAsync_Should_Not_Throw_Exception() + { + Func apiCall = () => + thirdCallSucceedsClient.CreateTransactionAsync(new Transaction()); + apiCall.Should().NotThrowAsync(); + } + + /// + /// Tests if the api call works as expected the third time around. + /// So the retry policy is used and no exception is thrown. + /// + [Fact] + public void When_Third_Call_Succeeds_DeleteTransactionAsync_Should_Not_Throw_Exception() + { + Func apiCall = () => + thirdCallSucceedsClient.DeleteTransactionAsync( + "Transaction Id", + new DeleteTransactionOptions()); + apiCall.Should().NotThrowAsync(); + } + + /// + /// Tests if the api call works as expected the third time around. + /// So the retry policy is used and no exception is thrown. + /// + [Fact] + public void When_Third_Call_Succeeds_GetDocumentAsync_Should_Not_Throw_Exception() + { + Func apiCall = () => + thirdCallSucceedsClient.GetDocumentAsync( + "Transaction Id", + "File Id"); + apiCall.Should().NotThrowAsync(); + } + + /// + /// Tests if the api call works as expected the third time around. + /// So the retry policy is used and no exception is thrown. + /// + [Fact] + public void When_Third_Call_Succeeds_GetReceiptAsync_Should_Not_Throw_Exception() + { + Func apiCall = () => + thirdCallSucceedsClient.GetReceiptAsync("Transaction Id"); + apiCall.Should().NotThrowAsync(); + } + + /// + /// Tests if the api call works as expected the third time around. + /// So the retry policy is used and no exception is thrown. + /// + [Fact] + public void When_Third_Call_Succeeds_GetTransactionAsync_Should_Not_Throw_Exception() + { + Func apiCall = () => + thirdCallSucceedsClient.GetTransactionAsync("transaction Id"); + apiCall.Should().NotThrowAsync(); + } + + /// + /// Tests if the api call works as expected the third time around. + /// So the retry policy is used and no exception is thrown. + /// + [Fact] + public void When_Third_Call_Succeeds_GetTransactionResponseAsync_Should_Not_Throw_Exception() + { + Func apiCall = () => + thirdCallSucceedsClient.GetTransactionResponseAsync("Transaction Id"); + apiCall.Should().NotThrowAsync(); + } + + /// + /// Tests if the api call fails as expected the fourth time around. + /// So the retry policy is used and a exception is thrown. + /// + [Fact] + public void When_All_Calls_Fail_AddOrReplaceFileMetaToTransactionAsync_Should_Throw_Exception() + { + Func apiCall = () => + allCallsFailClient.AddOrReplaceFileMetaToTransactionAsync( + new FileMeta(), + "Transaction Id", + "File Id"); + apiCall.Should().ThrowAsync(); + } + + /// + /// Tests if the api call fails as expected the fourth time around. + /// So the retry policy is used and a exception is thrown. + /// + [Fact] + public void When_All_Calls_Fail_AddOrReplaceFileToTransactionAsync_Should_Throw_Exception() + { + Func apiCall = () => + allCallsFailClient.AddOrReplaceFileToTransactionAsync( + new MemoryStream(), + "Transaction Id", + "File Id", + new FileUploadOptions()); + apiCall.Should().ThrowAsync(); + } + + /// + /// Tests if the api call fails as expected the fourth time around. + /// So the retry policy is used and a exception is thrown. + /// + [Fact] + public void When_All_Calls_Fail_CreateTransactionAsync_Should_Throw_Exception() + { + Func apiCall = () => + allCallsFailClient.CreateTransactionAsync(new Transaction()); + apiCall.Should().ThrowAsync(); + } + + /// + /// Tests if the api call fails as expected the fourth time around. + /// So the retry policy is used and a exception is thrown. + /// + [Fact] + public void When_All_Calls_Fail_DeleteTransactionAsync_Should_Throw_Exception() + { + Func apiCall = () => + allCallsFailClient.DeleteTransactionAsync( + "Transaction Id", + new DeleteTransactionOptions()); + apiCall.Should().ThrowAsync(); + } + + /// + /// Tests if the api call fails as expected the fourth time around. + /// So the retry policy is used and a exception is thrown. + /// + [Fact] + public void When_All_Calls_Fails_GetDocumentAsync_Should_Throw_Exception() + { + Func apiCall = () => + allCallsFailClient.GetDocumentAsync( + "Transaction Id", + "File Id"); + apiCall.Should().ThrowAsync(); + } + + /// + /// Tests if the api call fails as expected the fourth time around. + /// So the retry policy is used and a exception is thrown. + /// + [Fact] + public void When_All_Calls_Fail_GetReceiptAsync_Should_Throw_Exception() + { + Func apiCall = () => + allCallsFailClient.GetReceiptAsync("Transaction Id"); + apiCall.Should().ThrowAsync(); + } + /// - /// Tests the SignhostApiRetryClient. + /// Tests if the api call fails as expected the fourth time around. + /// So the retry policy is used and a exception is thrown. /// - public class SignhostApiRetryClientTests - : IDisposable + [Fact] + public void When_All_Calls_Fail_GetTransactionAsync_Should_Throw_Exception() + { + Func apiCall = () => + allCallsFailClient.GetTransactionAsync("transaction Id"); + apiCall.Should().ThrowAsync(); + } + + /// + /// Tests if the api call fails as expected the fourth time around. + /// So the retry policy is used and a exception is thrown. + /// + [Fact] + public void When_All_Calls_Fail_GetTransactionResponseAsync_Should_Throw_Exception() + { + Func apiCall = () => + allCallsFailClient.GetTransactionResponseAsync("Transaction Id"); + apiCall.Should().ThrowAsync(); + } + + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// Disposes of the objects in the class, + /// that implement IDisposable. + /// + /// If set to true then the object is being disposed from a call to Dispose(); + /// false if it is from a finalizer / destructor. + protected virtual void Dispose(bool disposing) + { + firstCallSucceedsClient.Dispose(); + thirdCallSucceedsClient.Dispose(); + allCallsFailClient.Dispose(); + + documentFile.Dispose(); + } + + private HttpMessageHandler SetupMockedHandler( + HttpStatusCode firstStatus, + HttpStatusCode secondStatus, + HttpStatusCode thirdStatus, + HttpStatusCode fourthStatus) { - private readonly SignhostApiClientSettings settings; - - private readonly SignhostApiRetryClient firstCallSucceedsClient; - private readonly SignhostApiRetryClient thirdCallSucceedsClient; - private readonly SignhostApiRetryClient allCallsFailClient; - - private readonly MemoryStream documentFile; - - /// - /// Initializes a new instance of the class. - /// Sets up the mocked handlers for the HttpClient. - /// - public SignhostApiRetryClientTests() - { - settings = new SignhostApiClientSettings( - "AppKey") { - Endpoint = "http://localhost/api/", - }; - - firstCallSucceedsClient = new SignhostApiRetryClient( - settings, - new HttpClient( - SetupMockedHandler( - HttpStatusCode.OK, - HttpStatusCode.InternalServerError, - HttpStatusCode.InternalServerError, - HttpStatusCode.InternalServerError))); - - thirdCallSucceedsClient = new SignhostApiRetryClient( - settings, - new HttpClient( - SetupMockedHandler( - HttpStatusCode.InternalServerError, - HttpStatusCode.InternalServerError, - HttpStatusCode.OK, - HttpStatusCode.InternalServerError))); - - allCallsFailClient = new SignhostApiRetryClient( - settings, - new HttpClient( - SetupMockedHandler( - HttpStatusCode.InternalServerError, - HttpStatusCode.InternalServerError, - HttpStatusCode.InternalServerError, - HttpStatusCode.InternalServerError))); - - documentFile = new MemoryStream(); - } - - /// - /// Tests if the api call works as expected the first time around. - /// So the retry policy isn't used and no exception is thrown. - /// - [Fact] - public void When_First_Call_Succeeds_AddOrReplaceFileMetaToTransactionAsync_Should_Not_Throw_Exception() - { - Func apiCall = () => - firstCallSucceedsClient.AddOrReplaceFileMetaToTransactionAsync( - new FileMeta(), - "Transaction Id", - "File Id"); - apiCall.Should().NotThrowAsync(); - } - - /// - /// Tests if the api call works as expected the first time around. - /// So the retry policy isn't used and no exception is thrown. - /// - [Fact] - public void When_First_Call_Succeeds_AddOrReplaceFileToTransactionAsync_Should_Not_Throw_Exception() - { - Func apiCall = () => - firstCallSucceedsClient.AddOrReplaceFileToTransactionAsync( - documentFile, - "Transaction Id", - "File Id", - new FileUploadOptions()); - apiCall.Should().NotThrowAsync(); - } - - /// - /// Tests if the api call works as expected the first time around. - /// So the retry policy isn't used and no exception is thrown. - /// - [Fact] - public void When_First_Call_Succeeds_CreateTransactionAsync_Should_Not_Throw_Exception() - { - Func apiCall = () => - firstCallSucceedsClient.CreateTransactionAsync(new Transaction()); - apiCall.Should().NotThrowAsync(); - } - - /// - /// Tests if the api call works as expected the first time around. - /// So the retry policy isn't used and no exception is thrown. - /// - [Fact] - public void When_First_Call_Succeeds_DeleteTransactionAsync_Should_Not_Throw_Exception() - { - Func apiCall = () => - firstCallSucceedsClient.DeleteTransactionAsync( - "Transaction Id", - new DeleteTransactionOptions()); - apiCall.Should().NotThrowAsync(); - } - - /// - /// Tests if the api call works as expected the first time around. - /// So the retry policy isn't used and no exception is thrown. - /// - [Fact] - public void When_First_Call_Succeeds_GetDocumentAsync_Should_Not_Throw_Exception() - { - Func apiCall = () => - firstCallSucceedsClient.GetDocumentAsync( - "Transaction Id", - "File Id"); - apiCall.Should().NotThrowAsync(); - } - - /// - /// Tests if the api call works as expected the first time around. - /// So the retry policy isn't used and no exception is thrown. - /// - [Fact] - public void When_First_Call_Succeeds_GetReceiptAsync_Should_Not_Throw_Exception() - { - Func apiCall = () => - firstCallSucceedsClient.GetReceiptAsync("Transaction Id"); - apiCall.Should().NotThrowAsync(); - } - - /// - /// Tests if the api call works as expected the first time around. - /// So the retry policy isn't used and no exception is thrown. - /// - [Fact] - public void When_First_Call_Succeeds_GetTransactionAsync_Should_Not_Throw_Exception() - { - Func apiCall = () => - firstCallSucceedsClient.GetTransactionAsync("transaction Id"); - apiCall.Should().NotThrowAsync(); - } - - /// - /// Tests if the api call works as expected the first time around. - /// So the retry policy isn't used and no exception is thrown. - /// - [Fact] - public void When_First_Call_Succeeds_GetTransactionResponseAsync_Should_Not_Throw_Exception() - { - Func apiCall = () => - firstCallSucceedsClient.GetTransactionResponseAsync("Transaction Id"); - apiCall.Should().NotThrowAsync(); - } - - /// - /// Tests if the api call works as expected the third time around. - /// So the retry policy is used and no exception is thrown. - /// - [Fact] - public void When_Third_Call_Succeeds_AddOrReplaceFileMetaToTransactionAsync_Should_Not_Throw_Exception() - { - Func apiCall = () - => thirdCallSucceedsClient.AddOrReplaceFileMetaToTransactionAsync( - new FileMeta(), - "Transaction Id", - "File Id"); - apiCall.Should().NotThrowAsync(); - } - - /// - /// Tests if the api call works as expected the third time around. - /// So the retry policy is used and no exception is thrown. - /// - [Fact] - public void When_Third_Call_Succeeds_AddOrReplaceFileToTransactionAsync_Should_Not_Throw_Exception() - { - Func apiCall = () => - thirdCallSucceedsClient.AddOrReplaceFileToTransactionAsync( - documentFile, - "Transaction Id", - "File Id", - new FileUploadOptions()); - apiCall.Should().NotThrowAsync(); - } - - /// - /// Tests if the api call works as expected the third time around. - /// So the retry policy is used and no exception is thrown. - /// - [Fact] - public void When_Third_Call_Succeeds_CreateTransactionAsync_Should_Not_Throw_Exception() - { - Func apiCall = () => - thirdCallSucceedsClient.CreateTransactionAsync(new Transaction()); - apiCall.Should().NotThrowAsync(); - } - - /// - /// Tests if the api call works as expected the third time around. - /// So the retry policy is used and no exception is thrown. - /// - [Fact] - public void When_Third_Call_Succeeds_DeleteTransactionAsync_Should_Not_Throw_Exception() - { - Func apiCall = () => - thirdCallSucceedsClient.DeleteTransactionAsync( - "Transaction Id", - new DeleteTransactionOptions()); - apiCall.Should().NotThrowAsync(); - } - - /// - /// Tests if the api call works as expected the third time around. - /// So the retry policy is used and no exception is thrown. - /// - [Fact] - public void When_Third_Call_Succeeds_GetDocumentAsync_Should_Not_Throw_Exception() - { - Func apiCall = () => - thirdCallSucceedsClient.GetDocumentAsync( - "Transaction Id", - "File Id"); - apiCall.Should().NotThrowAsync(); - } - - /// - /// Tests if the api call works as expected the third time around. - /// So the retry policy is used and no exception is thrown. - /// - [Fact] - public void When_Third_Call_Succeeds_GetReceiptAsync_Should_Not_Throw_Exception() - { - Func apiCall = () => - thirdCallSucceedsClient.GetReceiptAsync("Transaction Id"); - apiCall.Should().NotThrowAsync(); - } - - /// - /// Tests if the api call works as expected the third time around. - /// So the retry policy is used and no exception is thrown. - /// - [Fact] - public void When_Third_Call_Succeeds_GetTransactionAsync_Should_Not_Throw_Exception() - { - Func apiCall = () => - thirdCallSucceedsClient.GetTransactionAsync("transaction Id"); - apiCall.Should().NotThrowAsync(); - } - - /// - /// Tests if the api call works as expected the third time around. - /// So the retry policy is used and no exception is thrown. - /// - [Fact] - public void When_Third_Call_Succeeds_GetTransactionResponseAsync_Should_Not_Throw_Exception() - { - Func apiCall = () => - thirdCallSucceedsClient.GetTransactionResponseAsync("Transaction Id"); - apiCall.Should().NotThrowAsync(); - } - - /// - /// Tests if the api call fails as expected the fourth time around. - /// So the retry policy is used and a exception is thrown. - /// - [Fact] - public void When_All_Calls_Fail_AddOrReplaceFileMetaToTransactionAsync_Should_Throw_Exception() - { - Func apiCall = () => - allCallsFailClient.AddOrReplaceFileMetaToTransactionAsync( - new FileMeta(), - "Transaction Id", - "File Id"); - apiCall.Should().ThrowAsync(); - } - - /// - /// Tests if the api call fails as expected the fourth time around. - /// So the retry policy is used and a exception is thrown. - /// - [Fact] - public void When_All_Calls_Fail_AddOrReplaceFileToTransactionAsync_Should_Throw_Exception() - { - Func apiCall = () => - allCallsFailClient.AddOrReplaceFileToTransactionAsync( - new MemoryStream(), - "Transaction Id", - "File Id", - new FileUploadOptions()); - apiCall.Should().ThrowAsync(); - } - - /// - /// Tests if the api call fails as expected the fourth time around. - /// So the retry policy is used and a exception is thrown. - /// - [Fact] - public void When_All_Calls_Fail_CreateTransactionAsync_Should_Throw_Exception() - { - Func apiCall = () => - allCallsFailClient.CreateTransactionAsync(new Transaction()); - apiCall.Should().ThrowAsync(); - } - - /// - /// Tests if the api call fails as expected the fourth time around. - /// So the retry policy is used and a exception is thrown. - /// - [Fact] - public void When_All_Calls_Fail_DeleteTransactionAsync_Should_Throw_Exception() - { - Func apiCall = () => - allCallsFailClient.DeleteTransactionAsync( - "Transaction Id", - new DeleteTransactionOptions()); - apiCall.Should().ThrowAsync(); - } - - /// - /// Tests if the api call fails as expected the fourth time around. - /// So the retry policy is used and a exception is thrown. - /// - [Fact] - public void When_All_Calls_Fails_GetDocumentAsync_Should_Throw_Exception() - { - Func apiCall = () => - allCallsFailClient.GetDocumentAsync( - "Transaction Id", - "File Id"); - apiCall.Should().ThrowAsync(); - } - - /// - /// Tests if the api call fails as expected the fourth time around. - /// So the retry policy is used and a exception is thrown. - /// - [Fact] - public void When_All_Calls_Fail_GetReceiptAsync_Should_Throw_Exception() - { - Func apiCall = () => - allCallsFailClient.GetReceiptAsync("Transaction Id"); - apiCall.Should().ThrowAsync(); - } - - /// - /// Tests if the api call fails as expected the fourth time around. - /// So the retry policy is used and a exception is thrown. - /// - [Fact] - public void When_All_Calls_Fail_GetTransactionAsync_Should_Throw_Exception() - { - Func apiCall = () => - allCallsFailClient.GetTransactionAsync("transaction Id"); - apiCall.Should().ThrowAsync(); - } - - /// - /// Tests if the api call fails as expected the fourth time around. - /// So the retry policy is used and a exception is thrown. - /// - [Fact] - public void When_All_Calls_Fail_GetTransactionResponseAsync_Should_Throw_Exception() - { - Func apiCall = () => - allCallsFailClient.GetTransactionResponseAsync("Transaction Id"); - apiCall.Should().ThrowAsync(); - } - - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// - /// Disposes of the objects in the class, - /// that implement IDisposable. - /// - /// If set to true then the object is being disposed from a call to Dispose(); - /// false if it is from a finalizer / destructor. - protected virtual void Dispose(bool disposing) - { - firstCallSucceedsClient.Dispose(); - thirdCallSucceedsClient.Dispose(); - allCallsFailClient.Dispose(); - - documentFile.Dispose(); - } - - private HttpMessageHandler SetupMockedHandler( - HttpStatusCode firstStatus, - HttpStatusCode secondStatus, - HttpStatusCode thirdStatus, - HttpStatusCode fourthStatus) - { - var mockHandler = new Mock(); - mockHandler - .Protected() - .SetupSequence>( - "SendAsync", - ItExpr.IsAny(), - ItExpr.IsAny()) - .ReturnsAsync(new HttpResponseMessage(statusCode: firstStatus)) - .ReturnsAsync(new HttpResponseMessage(statusCode: secondStatus)) - .ReturnsAsync(new HttpResponseMessage(statusCode: thirdStatus)) - .ReturnsAsync(new HttpResponseMessage(statusCode: fourthStatus)); - - return mockHandler.Object; - } + var mockHandler = new Mock(); + mockHandler + .Protected() + .SetupSequence>( + "SendAsync", + ItExpr.IsAny(), + ItExpr.IsAny()) + .ReturnsAsync(new HttpResponseMessage(statusCode: firstStatus)) + .ReturnsAsync(new HttpResponseMessage(statusCode: secondStatus)) + .ReturnsAsync(new HttpResponseMessage(statusCode: thirdStatus)) + .ReturnsAsync(new HttpResponseMessage(statusCode: fourthStatus)); + + return mockHandler.Object; } } diff --git a/src/Signhost.APIClient/Rest/Polly/SignHostAPIRetryClient.cs b/src/Signhost.APIClient/Rest/Polly/SignHostAPIRetryClient.cs index fa1a28b..1a3176c 100644 --- a/src/Signhost.APIClient/Rest/Polly/SignHostAPIRetryClient.cs +++ b/src/Signhost.APIClient/Rest/Polly/SignHostAPIRetryClient.cs @@ -8,323 +8,322 @@ using Signhost.APIClient.Rest.DataObjects; using Signhost.APIClient.Rest.ErrorHandling; -namespace Signhost.APIClient.Rest.Polly +namespace Signhost.APIClient.Rest.Polly; + +/// +/// Implements the interface which provides +/// a signhost api client implementation. +/// +public class SignhostApiRetryClient + : ISignhostApiClient + , IDisposable { + private readonly SignhostApiClient client; + private readonly AsyncPolicy retryPolicy; + /// - /// Implements the interface which provides - /// a signhost api client implementation. + /// Initializes a new instance of the class. + /// This client has a built-in retry mechanism. + /// Set your usertoken and APPKey by creating a . /// - public class SignhostApiRetryClient - : ISignhostApiClient - , IDisposable + /// . + /// An to use instead of the default. + public SignhostApiRetryClient( + ISignhostApiClientSettings settings, + AsyncPolicy? policy = null) + : this(settings, new HttpClient(), policy) { - private readonly SignhostApiClient client; - private readonly AsyncPolicy retryPolicy; - - /// - /// Initializes a new instance of the class. - /// This client has a built-in retry mechanism. - /// Set your usertoken and APPKey by creating a . - /// - /// . - /// An to use instead of the default. - public SignhostApiRetryClient( - ISignhostApiClientSettings settings, - AsyncPolicy? policy = null) - : this(settings, new HttpClient(), policy) - { - } + } - /// - /// Initializes a new instance of the class. - /// This client has a built-in retry mechanism. - /// Set your usertoken and APPKey by creating a . - /// - /// . - /// to use for all http calls. - /// An to use instead of the default. - public SignhostApiRetryClient( - ISignhostApiClientSettings settings, - HttpClient httpClient, - AsyncPolicy? policy = null) - { - client = new SignhostApiClient(settings, httpClient); + /// + /// Initializes a new instance of the class. + /// This client has a built-in retry mechanism. + /// Set your usertoken and APPKey by creating a . + /// + /// . + /// to use for all http calls. + /// An to use instead of the default. + public SignhostApiRetryClient( + ISignhostApiClientSettings settings, + HttpClient httpClient, + AsyncPolicy? policy = null) + { + client = new SignhostApiClient(settings, httpClient); - if (policy is null) { - retryPolicy = GetDefaultPolicy(); - } - else { - retryPolicy = policy; - } + if (policy is null) { + retryPolicy = GetDefaultPolicy(); } - - /// - public async Task AddOrReplaceFileMetaToTransactionAsync( - FileMeta fileMeta, - string transactionId, - string fileId) - => await AddOrReplaceFileMetaToTransactionAsync( - fileMeta, - transactionId, - fileId, - default); - - /// - public async Task AddOrReplaceFileMetaToTransactionAsync( - FileMeta fileMeta, - string transactionId, - string fileId, - CancellationToken cancellationToken = default) - { - await retryPolicy - .ExecuteAsync( - ct => client.AddOrReplaceFileMetaToTransactionAsync( - fileMeta, - transactionId, - fileId, - ct), - cancellationToken); + else { + retryPolicy = policy; } + } - /// - public async Task AddOrReplaceFileToTransactionAsync( - Stream fileStream, - string transactionId, - string fileId, - FileUploadOptions uploadOptions) - => await AddOrReplaceFileToTransactionAsync( - fileStream, - transactionId, - fileId, - uploadOptions, - default); + /// + public async Task AddOrReplaceFileMetaToTransactionAsync( + FileMeta fileMeta, + string transactionId, + string fileId) + => await AddOrReplaceFileMetaToTransactionAsync( + fileMeta, + transactionId, + fileId, + default); - /// - public async Task AddOrReplaceFileToTransactionAsync( - Stream fileStream, - string transactionId, - string fileId, - FileUploadOptions uploadOptions, - CancellationToken cancellationToken = default) - { - await retryPolicy - .ExecuteAsync( - ct => client.AddOrReplaceFileToTransactionAsync( - fileStream, - transactionId, - fileId, - uploadOptions, - ct), - cancellationToken); - } + /// + public async Task AddOrReplaceFileMetaToTransactionAsync( + FileMeta fileMeta, + string transactionId, + string fileId, + CancellationToken cancellationToken = default) + { + await retryPolicy + .ExecuteAsync( + ct => client.AddOrReplaceFileMetaToTransactionAsync( + fileMeta, + transactionId, + fileId, + ct), + cancellationToken); + } - /// - public async Task AddOrReplaceFileToTransactionAsync( - string filePath, - string transactionId, - string fileId, - FileUploadOptions uploadOptions) - => await AddOrReplaceFileToTransactionAsync( - filePath, - transactionId, - fileId, - uploadOptions, - default); + /// + public async Task AddOrReplaceFileToTransactionAsync( + Stream fileStream, + string transactionId, + string fileId, + FileUploadOptions uploadOptions) + => await AddOrReplaceFileToTransactionAsync( + fileStream, + transactionId, + fileId, + uploadOptions, + default); - /// - public async Task AddOrReplaceFileToTransactionAsync( - string filePath, - string transactionId, - string fileId, - FileUploadOptions uploadOptions, - CancellationToken cancellationToken = default) - { - await retryPolicy - .ExecuteAsync( - ct => client.AddOrReplaceFileToTransactionAsync( - filePath, - transactionId, - fileId, - uploadOptions, - ct), - cancellationToken); - } + /// + public async Task AddOrReplaceFileToTransactionAsync( + Stream fileStream, + string transactionId, + string fileId, + FileUploadOptions uploadOptions, + CancellationToken cancellationToken = default) + { + await retryPolicy + .ExecuteAsync( + ct => client.AddOrReplaceFileToTransactionAsync( + fileStream, + transactionId, + fileId, + uploadOptions, + ct), + cancellationToken); + } - /// - public async Task CreateTransactionAsync( - Transaction transaction) - => await CreateTransactionAsync(transaction, default); + /// + public async Task AddOrReplaceFileToTransactionAsync( + string filePath, + string transactionId, + string fileId, + FileUploadOptions uploadOptions) + => await AddOrReplaceFileToTransactionAsync( + filePath, + transactionId, + fileId, + uploadOptions, + default); - /// - public async Task CreateTransactionAsync( - Transaction transaction, - CancellationToken cancellationToken = default) - { - return await retryPolicy - .ExecuteAsync( - ct => client.CreateTransactionAsync( - transaction, - ct), - cancellationToken); - } + /// + public async Task AddOrReplaceFileToTransactionAsync( + string filePath, + string transactionId, + string fileId, + FileUploadOptions uploadOptions, + CancellationToken cancellationToken = default) + { + await retryPolicy + .ExecuteAsync( + ct => client.AddOrReplaceFileToTransactionAsync( + filePath, + transactionId, + fileId, + uploadOptions, + ct), + cancellationToken); + } - /// - public async Task DeleteTransactionAsync( - string transactionId, - CancellationToken cancellationToken = default) - => await DeleteTransactionAsync( - transactionId, - default, + /// + public async Task CreateTransactionAsync( + Transaction transaction) + => await CreateTransactionAsync(transaction, default); + + /// + public async Task CreateTransactionAsync( + Transaction transaction, + CancellationToken cancellationToken = default) + { + return await retryPolicy + .ExecuteAsync( + ct => client.CreateTransactionAsync( + transaction, + ct), cancellationToken); + } - /// - public async Task DeleteTransactionAsync( - string transactionId, - DeleteTransactionOptions options) - => await DeleteTransactionAsync( - transactionId, - options, - default); + /// + public async Task DeleteTransactionAsync( + string transactionId, + CancellationToken cancellationToken = default) + => await DeleteTransactionAsync( + transactionId, + default, + cancellationToken); - /// - public async Task DeleteTransactionAsync( - string transactionId, - DeleteTransactionOptions? options = null, - CancellationToken cancellationToken = default) - { - await retryPolicy - .ExecuteAsync( - ct => client.DeleteTransactionAsync( - transactionId, - options, - ct), - cancellationToken); - } + /// + public async Task DeleteTransactionAsync( + string transactionId, + DeleteTransactionOptions options) + => await DeleteTransactionAsync( + transactionId, + options, + default); + + /// + public async Task DeleteTransactionAsync( + string transactionId, + DeleteTransactionOptions? options = null, + CancellationToken cancellationToken = default) + { + await retryPolicy + .ExecuteAsync( + ct => client.DeleteTransactionAsync( + transactionId, + options, + ct), + cancellationToken); + } - /// - public async Task GetDocumentAsync( - string transactionId, - string fileId) - => await GetDocumentAsync(transactionId, fileId, default); + /// + public async Task GetDocumentAsync( + string transactionId, + string fileId) + => await GetDocumentAsync(transactionId, fileId, default); - /// - public async Task GetDocumentAsync( - string transactionId, - string fileId, - CancellationToken cancellationToken = default) - { - return await retryPolicy - .ExecuteAsync( - ct => client.GetDocumentAsync( - transactionId, - fileId, - ct), - cancellationToken); - } + /// + public async Task GetDocumentAsync( + string transactionId, + string fileId, + CancellationToken cancellationToken = default) + { + return await retryPolicy + .ExecuteAsync( + ct => client.GetDocumentAsync( + transactionId, + fileId, + ct), + cancellationToken); + } - /// - public async Task GetReceiptAsync(string transactionId) - => await GetReceiptAsync(transactionId, default); + /// + public async Task GetReceiptAsync(string transactionId) + => await GetReceiptAsync(transactionId, default); - /// - public async Task GetReceiptAsync( - string transactionId, - CancellationToken cancellationToken = default) - { - return await retryPolicy - .ExecuteAsync( - ct => client.GetReceiptAsync( - transactionId, - ct), - cancellationToken); - } + /// + public async Task GetReceiptAsync( + string transactionId, + CancellationToken cancellationToken = default) + { + return await retryPolicy + .ExecuteAsync( + ct => client.GetReceiptAsync( + transactionId, + ct), + cancellationToken); + } - /// - public async Task GetTransactionAsync(string transactionId) - => await GetTransactionAsync(transactionId, default); + /// + public async Task GetTransactionAsync(string transactionId) + => await GetTransactionAsync(transactionId, default); - /// - public async Task GetTransactionAsync( - string transactionId, - CancellationToken cancellationToken = default) - { - return await retryPolicy - .ExecuteAsync( - ct => client.GetTransactionAsync( - transactionId, - ct), - cancellationToken); - } + /// + public async Task GetTransactionAsync( + string transactionId, + CancellationToken cancellationToken = default) + { + return await retryPolicy + .ExecuteAsync( + ct => client.GetTransactionAsync( + transactionId, + ct), + cancellationToken); + } - /// - public async Task> GetTransactionResponseAsync( - string transactionId) - => await GetTransactionResponseAsync(transactionId, default); + /// + public async Task> GetTransactionResponseAsync( + string transactionId) + => await GetTransactionResponseAsync(transactionId, default); - /// - public async Task> GetTransactionResponseAsync( - string transactionId, - CancellationToken cancellationToken = default) - { - return await retryPolicy - .ExecuteAsync( - ct => client.GetTransactionResponseAsync( - transactionId, - ct), - cancellationToken); - } + /// + public async Task> GetTransactionResponseAsync( + string transactionId, + CancellationToken cancellationToken = default) + { + return await retryPolicy + .ExecuteAsync( + ct => client.GetTransactionResponseAsync( + transactionId, + ct), + cancellationToken); + } - /// - public async Task StartTransactionAsync( - string transactionId) - => await StartTransactionAsync(transactionId, default); + /// + public async Task StartTransactionAsync( + string transactionId) + => await StartTransactionAsync(transactionId, default); - /// - public async Task StartTransactionAsync( - string transactionId, - CancellationToken cancellationToken = default) - { - await retryPolicy - .ExecuteAsync( - ct => client.StartTransactionAsync( - transactionId, - ct), - cancellationToken); - } + /// + public async Task StartTransactionAsync( + string transactionId, + CancellationToken cancellationToken = default) + { + await retryPolicy + .ExecuteAsync( + ct => client.StartTransactionAsync( + transactionId, + ct), + cancellationToken); + } - /// - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } - /// - /// Disposes the instance. - /// - /// Is callled. - protected virtual void Dispose(bool disposing) - { - if (disposing) { - client?.Dispose(); - } + /// + /// Disposes the instance. + /// + /// Is callled. + protected virtual void Dispose(bool disposing) + { + if (disposing) { + client?.Dispose(); } + } - private static AsyncPolicy GetDefaultPolicy() - { - return Policy - .Handle(ex => - !(ex is BadAuthorizationException) && - !(ex is BadRequestException) && - !(ex is NotFoundException)) + private static AsyncPolicy GetDefaultPolicy() + { + return Policy + .Handle(ex => + !(ex is BadAuthorizationException) && + !(ex is BadRequestException) && + !(ex is NotFoundException)) - // When an HttpClient times out it doesn't throw a TimeoutException like you'd expect. - // Instead it throws a TaskCanceledException, that's why we check the cancellation token. - .Or(ex => !ex.CancellationToken.IsCancellationRequested) - .WaitAndRetryAsync( - 3, - retryAttempt => - TimeSpan.FromMilliseconds(Math.Pow(10, retryAttempt))); - } + // When an HttpClient times out it doesn't throw a TimeoutException like you'd expect. + // Instead it throws a TaskCanceledException, that's why we check the cancellation token. + .Or(ex => !ex.CancellationToken.IsCancellationRequested) + .WaitAndRetryAsync( + 3, + retryAttempt => + TimeSpan.FromMilliseconds(Math.Pow(10, retryAttempt))); } } From 0dd5b54d44e4864aade6431503e1ff8651ab14b2 Mon Sep 17 00:00:00 2001 From: Anthony Timmers Date: Fri, 21 Nov 2025 19:41:44 +0100 Subject: [PATCH 6/6] Bump version to v5 --- .../Signhost.APIClient.Tests.csproj | 1 + .../SignhostApiRetryClientTests.cs | 13 +- .../Rest/Polly/SignHostAPIRetryClient.cs | 221 +++++------------- .../Signhost.APIClient.csproj | 3 +- 4 files changed, 64 insertions(+), 174 deletions(-) diff --git a/src/Signhost.APIClient.Tests/Signhost.APIClient.Tests.csproj b/src/Signhost.APIClient.Tests/Signhost.APIClient.Tests.csproj index ab0067c..41c1975 100644 --- a/src/Signhost.APIClient.Tests/Signhost.APIClient.Tests.csproj +++ b/src/Signhost.APIClient.Tests/Signhost.APIClient.Tests.csproj @@ -2,6 +2,7 @@ net10.0 false + enable diff --git a/src/Signhost.APIClient.Tests/SignhostApiRetryClientTests.cs b/src/Signhost.APIClient.Tests/SignhostApiRetryClientTests.cs index 7f2bcea..68f222a 100644 --- a/src/Signhost.APIClient.Tests/SignhostApiRetryClientTests.cs +++ b/src/Signhost.APIClient.Tests/SignhostApiRetryClientTests.cs @@ -1,4 +1,3 @@ -#nullable enable using System; using System.IO; using System.Net; @@ -109,8 +108,8 @@ public void When_First_Call_Succeeds_AddOrReplaceFileToTransactionAsync_Should_N [Fact] public void When_First_Call_Succeeds_CreateTransactionAsync_Should_Not_Throw_Exception() { - Func apiCall = () => - firstCallSucceedsClient.CreateTransactionAsync(new Transaction()); + Func apiCall = () => firstCallSucceedsClient + .CreateTransactionAsync(new CreateTransactionRequest()); apiCall.Should().NotThrowAsync(); } @@ -216,8 +215,8 @@ public void When_Third_Call_Succeeds_AddOrReplaceFileToTransactionAsync_Should_N [Fact] public void When_Third_Call_Succeeds_CreateTransactionAsync_Should_Not_Throw_Exception() { - Func apiCall = () => - thirdCallSucceedsClient.CreateTransactionAsync(new Transaction()); + Func apiCall = () => thirdCallSucceedsClient + .CreateTransactionAsync(new CreateTransactionRequest()); apiCall.Should().NotThrowAsync(); } @@ -323,8 +322,8 @@ public void When_All_Calls_Fail_AddOrReplaceFileToTransactionAsync_Should_Throw_ [Fact] public void When_All_Calls_Fail_CreateTransactionAsync_Should_Throw_Exception() { - Func apiCall = () => - allCallsFailClient.CreateTransactionAsync(new Transaction()); + Func apiCall = () => allCallsFailClient + .CreateTransactionAsync(new CreateTransactionRequest()); apiCall.Should().ThrowAsync(); } diff --git a/src/Signhost.APIClient/Rest/Polly/SignHostAPIRetryClient.cs b/src/Signhost.APIClient/Rest/Polly/SignHostAPIRetryClient.cs index 1a3176c..3af4cac 100644 --- a/src/Signhost.APIClient/Rest/Polly/SignHostAPIRetryClient.cs +++ b/src/Signhost.APIClient/Rest/Polly/SignHostAPIRetryClient.cs @@ -1,5 +1,4 @@ -#nullable enable -using System; +using System; using System.IO; using System.Net.Http; using System.Threading; @@ -59,15 +58,14 @@ public SignhostApiRetryClient( } /// - public async Task AddOrReplaceFileMetaToTransactionAsync( - FileMeta fileMeta, - string transactionId, - string fileId) - => await AddOrReplaceFileMetaToTransactionAsync( - fileMeta, - transactionId, - fileId, - default); + public async Task CreateTransactionAsync( + CreateTransactionRequest request, + CancellationToken cancellationToken = default) + { + return await retryPolicy.ExecuteAsync( + ct => client.CreateTransactionAsync(request, ct), + cancellationToken); + } /// public async Task AddOrReplaceFileMetaToTransactionAsync( @@ -76,14 +74,13 @@ public async Task AddOrReplaceFileMetaToTransactionAsync( string fileId, CancellationToken cancellationToken = default) { - await retryPolicy - .ExecuteAsync( - ct => client.AddOrReplaceFileMetaToTransactionAsync( - fileMeta, - transactionId, - fileId, - ct), - cancellationToken); + await retryPolicy.ExecuteAsync( + ct => client.AddOrReplaceFileMetaToTransactionAsync( + fileMeta, + transactionId, + fileId, + ct), + cancellationToken); } /// @@ -91,31 +88,17 @@ public async Task AddOrReplaceFileToTransactionAsync( Stream fileStream, string transactionId, string fileId, - FileUploadOptions uploadOptions) - => await AddOrReplaceFileToTransactionAsync( - fileStream, - transactionId, - fileId, - uploadOptions, - default); - - /// - public async Task AddOrReplaceFileToTransactionAsync( - Stream fileStream, - string transactionId, - string fileId, - FileUploadOptions uploadOptions, + FileUploadOptions? uploadOptions, CancellationToken cancellationToken = default) { - await retryPolicy - .ExecuteAsync( - ct => client.AddOrReplaceFileToTransactionAsync( - fileStream, - transactionId, - fileId, - uploadOptions, - ct), - cancellationToken); + await retryPolicy.ExecuteAsync( + ct => client.AddOrReplaceFileToTransactionAsync( + fileStream, + transactionId, + fileId, + uploadOptions, + ct), + cancellationToken); } /// @@ -123,68 +106,18 @@ public async Task AddOrReplaceFileToTransactionAsync( string filePath, string transactionId, string fileId, - FileUploadOptions uploadOptions) - => await AddOrReplaceFileToTransactionAsync( - filePath, - transactionId, - fileId, - uploadOptions, - default); - - /// - public async Task AddOrReplaceFileToTransactionAsync( - string filePath, - string transactionId, - string fileId, - FileUploadOptions uploadOptions, - CancellationToken cancellationToken = default) - { - await retryPolicy - .ExecuteAsync( - ct => client.AddOrReplaceFileToTransactionAsync( - filePath, - transactionId, - fileId, - uploadOptions, - ct), - cancellationToken); - } - - /// - public async Task CreateTransactionAsync( - Transaction transaction) - => await CreateTransactionAsync(transaction, default); - - /// - public async Task CreateTransactionAsync( - Transaction transaction, + FileUploadOptions? uploadOptions, CancellationToken cancellationToken = default) { - return await retryPolicy - .ExecuteAsync( - ct => client.CreateTransactionAsync( - transaction, - ct), - cancellationToken); - } - - /// - public async Task DeleteTransactionAsync( - string transactionId, - CancellationToken cancellationToken = default) - => await DeleteTransactionAsync( - transactionId, - default, + await retryPolicy.ExecuteAsync( + ct => client.AddOrReplaceFileToTransactionAsync( + filePath, + transactionId, + fileId, + uploadOptions, + ct), cancellationToken); - - /// - public async Task DeleteTransactionAsync( - string transactionId, - DeleteTransactionOptions options) - => await DeleteTransactionAsync( - transactionId, - options, - default); + } /// public async Task DeleteTransactionAsync( @@ -192,104 +125,60 @@ public async Task DeleteTransactionAsync( DeleteTransactionOptions? options = null, CancellationToken cancellationToken = default) { - await retryPolicy - .ExecuteAsync( - ct => client.DeleteTransactionAsync( - transactionId, - options, - ct), - cancellationToken); + await retryPolicy.ExecuteAsync( + ct => client.DeleteTransactionAsync(transactionId, options, ct), + cancellationToken); } - /// - public async Task GetDocumentAsync( - string transactionId, - string fileId) - => await GetDocumentAsync(transactionId, fileId, default); - /// public async Task GetDocumentAsync( string transactionId, string fileId, CancellationToken cancellationToken = default) { - return await retryPolicy - .ExecuteAsync( - ct => client.GetDocumentAsync( - transactionId, - fileId, - ct), - cancellationToken); + return await retryPolicy.ExecuteAsync( + ct => client.GetDocumentAsync(transactionId, fileId, ct), + cancellationToken); } - /// - public async Task GetReceiptAsync(string transactionId) - => await GetReceiptAsync(transactionId, default); - /// public async Task GetReceiptAsync( string transactionId, CancellationToken cancellationToken = default) { - return await retryPolicy - .ExecuteAsync( - ct => client.GetReceiptAsync( - transactionId, - ct), - cancellationToken); + return await retryPolicy.ExecuteAsync( + ct => client.GetReceiptAsync(transactionId, ct), + cancellationToken); } - /// - public async Task GetTransactionAsync(string transactionId) - => await GetTransactionAsync(transactionId, default); - /// public async Task GetTransactionAsync( string transactionId, CancellationToken cancellationToken = default) { - return await retryPolicy - .ExecuteAsync( - ct => client.GetTransactionAsync( - transactionId, - ct), - cancellationToken); + return await retryPolicy.ExecuteAsync( + ct => client.GetTransactionAsync(transactionId, ct), + cancellationToken); } - /// - public async Task> GetTransactionResponseAsync( - string transactionId) - => await GetTransactionResponseAsync(transactionId, default); - /// public async Task> GetTransactionResponseAsync( string transactionId, CancellationToken cancellationToken = default) { - return await retryPolicy - .ExecuteAsync( - ct => client.GetTransactionResponseAsync( - transactionId, - ct), - cancellationToken); + return await retryPolicy.ExecuteAsync( + ct => client.GetTransactionResponseAsync(transactionId, ct), + cancellationToken); } - /// - public async Task StartTransactionAsync( - string transactionId) - => await StartTransactionAsync(transactionId, default); - /// public async Task StartTransactionAsync( string transactionId, CancellationToken cancellationToken = default) { - await retryPolicy - .ExecuteAsync( - ct => client.StartTransactionAsync( - transactionId, - ct), - cancellationToken); + await retryPolicy.ExecuteAsync( + ct => client.StartTransactionAsync(transactionId, ct), + cancellationToken); } /// @@ -314,9 +203,9 @@ private static AsyncPolicy GetDefaultPolicy() { return Policy .Handle(ex => - !(ex is BadAuthorizationException) && - !(ex is BadRequestException) && - !(ex is NotFoundException)) + ex is not BadAuthorizationException && + ex is not BadRequestException && + ex is not NotFoundException) // When an HttpClient times out it doesn't throw a TimeoutException like you'd expect. // Instead it throws a TaskCanceledException, that's why we check the cancellation token. diff --git a/src/Signhost.APIClient/Signhost.APIClient.csproj b/src/Signhost.APIClient/Signhost.APIClient.csproj index bcf9f4e..96b5568 100644 --- a/src/Signhost.APIClient/Signhost.APIClient.csproj +++ b/src/Signhost.APIClient/Signhost.APIClient.csproj @@ -3,6 +3,7 @@ net10.0;net9.0;net8.0;netstandard2.0;net462 10 Signhost.APIClient + enable @@ -45,6 +46,6 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - +