Skip to content

Commit 48f6a21

Browse files
Merge pull request #740 from TransactionProcessing/task/#725_merchant_domain)event_hander_retry
Add TestLogger and refactor policy execution methods
2 parents b270fe9 + aab9705 commit 48f6a21

File tree

6 files changed

+42
-29
lines changed

6 files changed

+42
-29
lines changed

TransactionProcessor.BusinessLogic.Tests/DomainEventHandlers/MerchantSettlementDomainEventHandlerTests.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
using SimpleResults;
1818
using TransactionProcessor.BusinessLogic.Requests;
1919
using Grpc.Core;
20+
using Xunit.Abstractions;
21+
using Xunit.Sdk;
2022

2123
namespace TransactionProcessor.BusinessLogic.Tests.DomainEventHandlers
2224
{

TransactionProcessor.BusinessLogic/Common/PolicyFactory.cs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Threading.Tasks;
23
using EventStore.Client;
34
using Grpc.Core;
45
using Polly;
@@ -17,15 +18,25 @@ public static IAsyncPolicy<Result> CreatePolicy(Int32 retryCount=5, TimeSpan? re
1718

1819
AsyncRetryPolicy<Result> retryPolicy = CreateRetryPolicy(retryCount, retryDelayValue, policyTag);
1920

20-
return withFallBack switch {
21+
IAsyncPolicy<Result> policyWrap = withFallBack switch {
2122
true => CreateFallbackPolicy(policyTag, retryPolicy),
2223
_ => retryPolicy
2324
};
25+
return policyWrap;
26+
}
27+
28+
public static async Task<Result> ExecuteWithPolicyAsync(Func<Task<Result>> action, IAsyncPolicy<Result> policy, String policyTag = "")
29+
{
30+
Result result = await policy.ExecuteAsync(action);
31+
32+
// Log success if no retries were required
33+
Logger.LogWarning($"{policyTag} - Execution succeeded without retries.");
34+
35+
return result;
2436
}
2537

2638
private static AsyncRetryPolicy<Result> CreateRetryPolicy(int retryCount, TimeSpan retryDelay, String policyTag)
2739
{
28-
//
2940
return Policy<Result>
3041
.Handle<WrongExpectedVersionException>()
3142
.Or<RpcException>(ex => ex.StatusCode == StatusCode.DeadlineExceeded)
@@ -39,15 +50,15 @@ private static AsyncRetryPolicy<Result> CreateRetryPolicy(int retryCount, TimeSp
3950

4051
private static AsyncPolicyWrap<Result> CreateFallbackPolicy(String policyTag, AsyncRetryPolicy<Result> retryPolicy)
4152
{
42-
AsyncFallbackPolicy<Result> fallbackPolicy = Policy<Result>
43-
.Handle<WrongExpectedVersionException>()
44-
.Or<TimeoutException>()
45-
.FallbackAsync(async (cancellationToken) =>
46-
{
47-
Logger.LogWarning($"{policyTag} -All retries failed. Executing fallback action...");
48-
// Log failure, notify monitoring system, or enqueue for later processing
49-
return Result.Failure("Fallback action executed");
50-
});
53+
var fallbackPolicy = Policy<Result>
54+
.Handle<Exception>() // Catch-all for exceptions that aren't retried
55+
.FallbackAsync(
56+
fallbackValue: Result.Failure("An error occurred, no retry required."), // Ensure a valid Result return
57+
onFallbackAsync: (exception, context) =>
58+
{
59+
Logger.LogWarning($"{policyTag} - Non-retryable exception encountered: {exception.GetType().Name}");
60+
return Task.CompletedTask;
61+
});
5162

5263
return fallbackPolicy.WrapAsync(retryPolicy);
5364
}

TransactionProcessor.BusinessLogic/EventHandling/MerchantDomainEventHandler.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ private async Task<Result> HandleSpecificDomainEvent(CallbackReceivedEnrichedEve
6363
{
6464
IAsyncPolicy<Result> retryPolicy = PolicyFactory.CreatePolicy(2, policyTag: "MerchantSettlementDomainEventHandler - MerchantFeeSettledEvent");
6565

66-
return await retryPolicy.ExecuteAsync(async () => {
66+
return await PolicyFactory.ExecuteWithPolicyAsync(async () => {
6767
if (domainEvent.TypeString == typeof(CallbackHandler.DataTransferObjects.Deposit).ToString()) {
6868
// Work out the merchant id from the reference field (second part, split on hyphen)
6969
String merchantReference = domainEvent.Reference.Split("-")[1];
@@ -80,7 +80,7 @@ private async Task<Result> HandleSpecificDomainEvent(CallbackReceivedEnrichedEve
8080
}
8181

8282
return Result.Success();
83-
});
83+
}, retryPolicy, "MerchantSettlementDomainEventHandler - MerchantFeeSettledEvent");
8484
}
8585

8686
#endregion

TransactionProcessor.BusinessLogic/EventHandling/MerchantSettlementDomainEventHandler.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ private async Task<Result> HandleSpecificDomainEvent(SettlementDomainEvents.Merc
3434
CancellationToken cancellationToken) {
3535
IAsyncPolicy<Result> retryPolicy = PolicyFactory.CreatePolicy(2, policyTag: "MerchantSettlementDomainEventHandler - MerchantFeeSettledEvent");
3636

37-
return await retryPolicy.ExecuteAsync(async () => {
37+
return await PolicyFactory.ExecuteWithPolicyAsync(async () => {
3838
MerchantStatementCommands.AddSettledFeeToMerchantStatementCommand command = new(domainEvent.EstateId, domainEvent.MerchantId, domainEvent.FeeCalculatedDateTime, domainEvent.CalculatedValue, domainEvent.TransactionId, domainEvent.FeeId);
3939

4040
return await this.Mediator.Send(command, cancellationToken);
41-
});
41+
}, retryPolicy, "MerchantSettlementDomainEventHandler - MerchantFeeSettledEvent");
4242
}
4343
}

TransactionProcessor.BusinessLogic/EventHandling/MerchantStatementDomainEventHandler.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,22 +54,22 @@ private async Task<Result> HandleSpecificDomainEvent(MerchantStatementDomainEven
5454

5555
IAsyncPolicy<Result> retryPolicy = PolicyFactory.CreatePolicy(2, policyTag: "MerchantStatementDomainEventHandler - StatementGeneratedEvent");
5656

57-
return await retryPolicy.ExecuteAsync(async () => {
57+
return await PolicyFactory.ExecuteWithPolicyAsync(async () => {
5858
MerchantStatementCommands.EmailMerchantStatementCommand command = new(domainEvent.EstateId, domainEvent.MerchantId, domainEvent.MerchantStatementId);
5959

6060
return await this.Mediator.Send(command, cancellationToken);
61-
});
61+
}, retryPolicy, "MerchantStatementDomainEventHandler - StatementGeneratedEvent");
6262
}
6363

6464
private async Task<Result> HandleSpecificDomainEvent(TransactionDomainEvents.TransactionHasBeenCompletedEvent domainEvent,
6565
CancellationToken cancellationToken) {
6666
IAsyncPolicy<Result> retryPolicy = PolicyFactory.CreatePolicy(2, policyTag: "MerchantStatementDomainEventHandler - TransactionHasBeenCompletedEvent");
6767

68-
return await retryPolicy.ExecuteAsync(async () => {
68+
return await PolicyFactory.ExecuteWithPolicyAsync(async () => {
6969
MerchantStatementCommands.AddTransactionToMerchantStatementCommand command = new(domainEvent.EstateId, domainEvent.MerchantId, domainEvent.CompletedDateTime, domainEvent.TransactionAmount, domainEvent.IsAuthorised, domainEvent.TransactionId);
7070

7171
return await this.Mediator.Send(command, cancellationToken);
72-
});
72+
},retryPolicy, "MerchantStatementDomainEventHandler - TransactionHasBeenCompletedEvent");
7373
}
7474

7575
#endregion

TransactionProcessor.BusinessLogic/EventHandling/TransactionDomainEventHandler.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,25 +61,25 @@ private async Task<Result> HandleSpecificDomainEvent(FloatDomainEvents.FloatCred
6161

6262
IAsyncPolicy<Result> retryPolicy = PolicyFactory.CreatePolicy(2, policyTag: "TransactionDomainEventHandler - FloatCreditPurchasedEvent");
6363

64-
return await retryPolicy.ExecuteAsync(async () => {
64+
return await PolicyFactory.ExecuteWithPolicyAsync(async () => {
6565
FloatActivityCommands.RecordCreditPurchaseCommand command =
6666
new(domainEvent.EstateId, domainEvent.FloatId,
6767
domainEvent.CreditPurchasedDateTime, domainEvent.Amount, domainEvent.EventId);
6868

6969
return await this.Mediator.Send(command, cancellationToken);
70-
});
70+
},retryPolicy, "TransactionDomainEventHandler - FloatCreditPurchasedEvent");
7171
}
7272

7373
private async Task<Result> HandleSpecificDomainEvent(TransactionDomainEvents.TransactionCostInformationRecordedEvent domainEvent, CancellationToken cancellationToken){
7474

7575
IAsyncPolicy<Result> retryPolicy = PolicyFactory.CreatePolicy(2, policyTag: "TransactionDomainEventHandler - TransactionCostInformationRecordedEvent");
7676

77-
return await retryPolicy.ExecuteAsync(async () => {
77+
return await PolicyFactory.ExecuteWithPolicyAsync(async () => {
7878
FloatActivityCommands.RecordTransactionCommand command = new(domainEvent.EstateId,
7979
domainEvent.TransactionId);
8080

8181
return await this.Mediator.Send(command, cancellationToken);
82-
});
82+
}, retryPolicy, "TransactionDomainEventHandler - TransactionCostInformationRecordedEvent");
8383
}
8484

8585
private async Task<Result> HandleSpecificDomainEvent(TransactionDomainEvents.TransactionHasBeenCompletedEvent domainEvent,
@@ -93,38 +93,38 @@ private async Task<Result> HandleSpecificDomainEvent(TransactionDomainEvents.Mer
9393
CancellationToken cancellationToken) {
9494
IAsyncPolicy<Result> retryPolicy = PolicyFactory.CreatePolicy(2, policyTag: "TransactionDomainEventHandler - MerchantFeePendingSettlementAddedToTransactionEvent");
9595

96-
return await retryPolicy.ExecuteAsync(async () => {
96+
return await PolicyFactory.ExecuteWithPolicyAsync(async () => {
9797
SettlementCommands.AddMerchantFeePendingSettlementCommand command =
9898
new SettlementCommands.AddMerchantFeePendingSettlementCommand(domainEvent.TransactionId,
9999
domainEvent.CalculatedValue, domainEvent.FeeCalculatedDateTime,
100100
(CalculationType)domainEvent.FeeCalculationType, domainEvent.FeeId, domainEvent.FeeValue,
101101
domainEvent.SettlementDueDate, domainEvent.MerchantId, domainEvent.EstateId);
102102
return await this.Mediator.Send(command, cancellationToken);
103-
});
103+
}, retryPolicy, "TransactionDomainEventHandler - MerchantFeePendingSettlementAddedToTransactionEvent");
104104
}
105105

106106
private async Task<Result> HandleSpecificDomainEvent(TransactionDomainEvents.SettledMerchantFeeAddedToTransactionEvent domainEvent,
107107
CancellationToken cancellationToken) {
108108
IAsyncPolicy<Result> retryPolicy = PolicyFactory.CreatePolicy(2, policyTag: "TransactionDomainEventHandler - SettledMerchantFeeAddedToTransactionEvent");
109109

110-
return await retryPolicy.ExecuteAsync(async () => {
110+
return await PolicyFactory.ExecuteWithPolicyAsync(async () => {
111111
AddSettledFeeToSettlementCommand command = new AddSettledFeeToSettlementCommand(
112112
domainEvent.SettledDateTime.Date, domainEvent.MerchantId, domainEvent.EstateId, domainEvent.FeeId, domainEvent.TransactionId);
113113
return await this.Mediator.Send(command, cancellationToken);
114-
});
114+
},retryPolicy, "TransactionDomainEventHandler - SettledMerchantFeeAddedToTransactionEvent");
115115
}
116116

117117
private async Task<Result> HandleSpecificDomainEvent(SettlementDomainEvents.MerchantFeeSettledEvent domainEvent,
118118
CancellationToken cancellationToken)
119119
{
120120
IAsyncPolicy<Result> retryPolicy = PolicyFactory.CreatePolicy(2, policyTag: "TransactionDomainEventHandler - MerchantFeeSettledEvent");
121121

122-
return await retryPolicy.ExecuteAsync(async () => {
122+
return await PolicyFactory.ExecuteWithPolicyAsync(async () => {
123123
AddSettledMerchantFeeCommand command = new(domainEvent.TransactionId, domainEvent.CalculatedValue,
124124
domainEvent.FeeCalculatedDateTime, (CalculationType)domainEvent.FeeCalculationType, domainEvent.FeeId,
125125
domainEvent.FeeValue, domainEvent.SettledDateTime, domainEvent.SettlementId);
126126
return await this.Mediator.Send(command, cancellationToken);
127-
});
127+
}, retryPolicy, "TransactionDomainEventHandler - MerchantFeeSettledEvent");
128128
}
129129

130130
private async Task<Result> HandleSpecificDomainEvent(TransactionDomainEvents.CustomerEmailReceiptRequestedEvent domainEvent,

0 commit comments

Comments
 (0)