Skip to content

Commit c30d556

Browse files
Merge pull request #837 from TransactionProcessing/task/#826_retry_process_settlement_command
Build in retries to Process Settlement at the domain service
2 parents d83517c + 7904ac5 commit c30d556

File tree

2 files changed

+107
-0
lines changed

2 files changed

+107
-0
lines changed

TransactionProcessor.BusinessLogic.Tests/Services/SettlementDomainServiceTests.cs

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,106 @@ public async Task SettlementDomainService_ProcessSettlement_SettlementIsProcesse
8282
result.Data.ShouldNotBe(Guid.Empty);
8383
}
8484

85+
[Fact]
86+
public async Task SettlementDomainService_ProcessSettlement_RunOutOfRetries_SettlementIsNotProcessed()
87+
{
88+
this.AggregateService.Setup(s => s.GetLatest<SettlementAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
89+
.ReturnsAsync(Result.Success(TestData.GetSettlementAggregateWithPendingMerchantFees(10)));
90+
this.AggregateService.SetupSequence(s => s.GetLatest<TransactionAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
91+
.ReturnsAsync(Result.Success(TestData.GetCompletedAuthorisedSaleTransactionAggregateWithPendingFee(TestData.FeeIds.GetValueOrDefault(0))))
92+
.ReturnsAsync(Result.Success(TestData.GetCompletedAuthorisedSaleTransactionAggregateWithPendingFee(TestData.FeeIds.GetValueOrDefault(1))))
93+
.ReturnsAsync(Result.Success(TestData.GetCompletedAuthorisedSaleTransactionAggregateWithPendingFee(TestData.FeeIds.GetValueOrDefault(2))))
94+
.ReturnsAsync(Result.Success(TestData.GetCompletedAuthorisedSaleTransactionAggregateWithPendingFee(TestData.FeeIds.GetValueOrDefault(3))))
95+
.ReturnsAsync(Result.Success(TestData.GetCompletedAuthorisedSaleTransactionAggregateWithPendingFee(TestData.FeeIds.GetValueOrDefault(4))))
96+
.ReturnsAsync(Result.Success(TestData.GetCompletedAuthorisedSaleTransactionAggregateWithPendingFee(TestData.FeeIds.GetValueOrDefault(5))))
97+
.ReturnsAsync(Result.Success(TestData.GetCompletedAuthorisedSaleTransactionAggregateWithPendingFee(TestData.FeeIds.GetValueOrDefault(6))))
98+
.ReturnsAsync(Result.Success(TestData.GetCompletedAuthorisedSaleTransactionAggregateWithPendingFee(TestData.FeeIds.GetValueOrDefault(7))))
99+
.ReturnsAsync(Result.Success(TestData.GetCompletedAuthorisedSaleTransactionAggregateWithPendingFee(TestData.FeeIds.GetValueOrDefault(8))))
100+
.ReturnsAsync(Result.Success(TestData.GetCompletedAuthorisedSaleTransactionAggregateWithPendingFee(TestData.FeeIds.GetValueOrDefault(9))));
101+
this.AggregateService.SetupSequence(s => s.Save(It.IsAny<SettlementAggregate>(), It.IsAny<CancellationToken>()))
102+
.ReturnsAsync(Result.Success())
103+
.ReturnsAsync(Result.Failure(new List<String> { "WrongExpectedVersion" }))
104+
.ReturnsAsync(Result.Success())
105+
.ReturnsAsync(Result.Failure(new List<String> { "WrongExpectedVersion" }))
106+
.ReturnsAsync(Result.Success())
107+
.ReturnsAsync(Result.Failure(new List<String> { "WrongExpectedVersion" }))
108+
.ReturnsAsync(Result.Success())
109+
.ReturnsAsync(Result.Failure(new List<String> { "WrongExpectedVersion" }))
110+
.ReturnsAsync(Result.Success())
111+
.ReturnsAsync(Result.Failure(new List<String> { "WrongExpectedVersion" }))
112+
.ReturnsAsync(Result.Failure(new List<String> { "WrongExpectedVersion" }));
113+
this.AggregateService.SetupSequence(s => s.Save(It.IsAny<TransactionAggregate>(), It.IsAny<CancellationToken>()))
114+
.ReturnsAsync(Result.Success())
115+
.ReturnsAsync(Result.Success())
116+
.ReturnsAsync(Result.Success())
117+
.ReturnsAsync(Result.Success())
118+
.ReturnsAsync(Result.Success())
119+
.ReturnsAsync(Result.Success())
120+
.ReturnsAsync(Result.Success())
121+
.ReturnsAsync(Result.Success())
122+
.ReturnsAsync(Result.Success())
123+
.ReturnsAsync(Result.Success());
124+
125+
this.AggregateService.Setup(e => e.Get<MerchantAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
126+
.ReturnsAsync(TestData.Aggregates.CreatedMerchantAggregate());
127+
128+
SettlementCommands.ProcessSettlementCommand command =
129+
new(TestData.SettlementDate, TestData.MerchantId,
130+
TestData.EstateId);
131+
132+
Result<Guid> result = await settlementDomainService.ProcessSettlement(command, CancellationToken.None);
133+
134+
result.IsSuccess.ShouldBeFalse();
135+
this.AggregateService.Verify(s => s.Save(It.IsAny<SettlementAggregate>(), It.IsAny<CancellationToken>()), Times.Exactly(11));
136+
}
137+
138+
[Fact]
139+
public async Task SettlementDomainService_ProcessSettlement_RetryOnWrongExpected_SettlementIsProcessed()
140+
{
141+
this.AggregateService.Setup(s => s.GetLatest<SettlementAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
142+
.ReturnsAsync(Result.Success(TestData.GetSettlementAggregateWithPendingMerchantFees(10)));
143+
this.AggregateService.SetupSequence(s => s.GetLatest<TransactionAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
144+
.ReturnsAsync(Result.Success(TestData.GetCompletedAuthorisedSaleTransactionAggregateWithPendingFee(TestData.FeeIds.GetValueOrDefault(0))))
145+
.ReturnsAsync(Result.Success(TestData.GetCompletedAuthorisedSaleTransactionAggregateWithPendingFee(TestData.FeeIds.GetValueOrDefault(1))))
146+
.ReturnsAsync(Result.Success(TestData.GetCompletedAuthorisedSaleTransactionAggregateWithPendingFee(TestData.FeeIds.GetValueOrDefault(2))))
147+
.ReturnsAsync(Result.Success(TestData.GetCompletedAuthorisedSaleTransactionAggregateWithPendingFee(TestData.FeeIds.GetValueOrDefault(3))))
148+
.ReturnsAsync(Result.Success(TestData.GetCompletedAuthorisedSaleTransactionAggregateWithPendingFee(TestData.FeeIds.GetValueOrDefault(4))))
149+
.ReturnsAsync(Result.Success(TestData.GetCompletedAuthorisedSaleTransactionAggregateWithPendingFee(TestData.FeeIds.GetValueOrDefault(5))))
150+
.ReturnsAsync(Result.Success(TestData.GetCompletedAuthorisedSaleTransactionAggregateWithPendingFee(TestData.FeeIds.GetValueOrDefault(6))))
151+
.ReturnsAsync(Result.Success(TestData.GetCompletedAuthorisedSaleTransactionAggregateWithPendingFee(TestData.FeeIds.GetValueOrDefault(7))))
152+
.ReturnsAsync(Result.Success(TestData.GetCompletedAuthorisedSaleTransactionAggregateWithPendingFee(TestData.FeeIds.GetValueOrDefault(8))))
153+
.ReturnsAsync(Result.Success(TestData.GetCompletedAuthorisedSaleTransactionAggregateWithPendingFee(TestData.FeeIds.GetValueOrDefault(9))));
154+
this.AggregateService.SetupSequence(s => s.Save(It.IsAny<SettlementAggregate>(), It.IsAny<CancellationToken>()))
155+
.ReturnsAsync(Result.Success())
156+
.ReturnsAsync(Result.Failure(new List<String>{ "WrongExpectedVersion" }))
157+
.ReturnsAsync(Result.Success())
158+
.ReturnsAsync(Result.Success());
159+
this.AggregateService.SetupSequence(s => s.Save(It.IsAny<TransactionAggregate>(), It.IsAny<CancellationToken>()))
160+
.ReturnsAsync(Result.Success())
161+
.ReturnsAsync(Result.Success())
162+
.ReturnsAsync(Result.Success())
163+
.ReturnsAsync(Result.Success())
164+
.ReturnsAsync(Result.Success())
165+
.ReturnsAsync(Result.Success())
166+
.ReturnsAsync(Result.Success())
167+
.ReturnsAsync(Result.Success())
168+
.ReturnsAsync(Result.Success())
169+
.ReturnsAsync(Result.Success());
170+
171+
this.AggregateService.Setup(e => e.Get<MerchantAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
172+
.ReturnsAsync(TestData.Aggregates.CreatedMerchantAggregate());
173+
174+
SettlementCommands.ProcessSettlementCommand command =
175+
new(TestData.SettlementDate, TestData.MerchantId,
176+
TestData.EstateId);
177+
178+
Result<Guid> result = await settlementDomainService.ProcessSettlement(command, CancellationToken.None);
179+
180+
result.IsSuccess.ShouldBeTrue();
181+
result.Data.ShouldNotBe(Guid.Empty);
182+
this.AggregateService.Verify(s => s.Save(It.IsAny<SettlementAggregate>(), It.IsAny<CancellationToken>()), Times.Exactly(4));
183+
}
184+
85185
[Fact]
86186
public async Task SettlementDomainService_ProcessSettlement_MerchantWithImmediateSettlement_SettlementIsProcessed()
87187
{

TransactionProcessor.BusinessLogic/Services/SettlementDomainService.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,11 @@ private async Task<Result> ApplyTransactionUpdates(Func<TransactionAggregate, Ta
100100

101101
public async Task<Result<Guid>> ProcessSettlement(SettlementCommands.ProcessSettlementCommand command,
102102
CancellationToken cancellationToken) {
103+
104+
IAsyncPolicy<Result<Guid>> retryPolicy = PolicyFactory.CreatePolicy<Guid>(policyTag: "SettlementDomainService - ProcessSettlement");
105+
106+
return await PolicyFactory.ExecuteWithPolicyAsync<Guid>(async () => {
107+
103108
Guid settlementAggregateId = Helpers.CalculateSettlementAggregateId(command.SettlementDate, command.MerchantId, command.EstateId);
104109
List<(Guid transactionId, Guid merchantId, CalculatedFee calculatedFee)> feesToBeSettled = new();
105110

@@ -161,6 +166,8 @@ public async Task<Result<Guid>> ProcessSettlement(SettlementCommands.ProcessSett
161166
}
162167

163168
return Result.Success(settlementAggregateId);
169+
}, retryPolicy, "SettlementDomainService - ProcessSettlement");
170+
164171
}
165172

166173
public async Task<Result> AddMerchantFeePendingSettlement(SettlementCommands.AddMerchantFeePendingSettlementCommand command,

0 commit comments

Comments
 (0)