Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,5 @@ public async Task MerchantSettlementDomainEventHandler_Handle_MerchantFeeSettled
Result result = await this.EventHandler.Handle(TestData.DomainEvents.MerchantFeeSettledEvent, CancellationToken.None);
result.IsSuccess.ShouldBeTrue();
}

[Fact]
public async Task MerchantSettlementDomainEventHandler_Handle_MerchantFeeSettledEvent_Retry_EventIsHandled()
{
this.Mediator.SetupSequence(m => m.Send(It.IsAny<IRequest<Result>>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(Result.Failure(new List<String>() { "Append failed due to WrongExpectedVersion"}))
.ReturnsAsync(Result.Failure(new List<String>() { "DeadlineExceeded"}))
.ReturnsAsync(Result.Success());

Result result = await this.EventHandler.Handle(TestData.DomainEvents.MerchantFeeSettledEvent, CancellationToken.None);
result.IsSuccess.ShouldBeTrue();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,7 @@ public async Task MerchantStatementDomainEventHandler_Handle_StatementGeneratedE
Result result = await this.EventHandler.Handle(TestData.DomainEvents.StatementGeneratedEvent, CancellationToken.None);
result.IsSuccess.ShouldBeTrue();
}

[Fact]
public async Task MerchantStatementDomainEventHandler_Handle_StatementGeneratedEvent_Retry_EventIsHandled()
{
this.Mediator.SetupSequence(m => m.Send(It.IsAny<IRequest<Result>>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(Result.Failure(new List<String>() { "Append failed due to WrongExpectedVersion" }))
.ReturnsAsync(Result.Failure(new List<String>() { "DeadlineExceeded" }))
.ReturnsAsync(Result.Success());

Result result = await this.EventHandler.Handle(TestData.DomainEvents.StatementGeneratedEvent, CancellationToken.None);
result.IsSuccess.ShouldBeTrue();
}


[Fact]
public async Task MerchantStatementDomainEventHandler_Handle_TransactionHasBeenCompletedEvent_EventIsHandled()
{
Expand All @@ -56,15 +44,4 @@ public async Task MerchantStatementDomainEventHandler_Handle_TransactionHasBeenC
result.IsSuccess.ShouldBeTrue();
}

[Fact]
public async Task MerchantStatementDomainEventHandler_Handle_TransactionHasBeenCompletedEvent_Retry_EventIsHandled()
{
this.Mediator.SetupSequence(m => m.Send(It.IsAny<IRequest<Result>>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(Result.Failure(new List<String>() { "Append failed due to WrongExpectedVersion" }))
.ReturnsAsync(Result.Failure(new List<String>() { "DeadlineExceeded" }))
.ReturnsAsync(Result.Success());

Result result = await this.EventHandler.Handle(TestData.DomainEvents.TransactionHasBeenCompletedEvent, CancellationToken.None);
result.IsSuccess.ShouldBeTrue();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ public TransactionDomainEventHandlerTests(ITestOutputHelper testOutputHelper) :
[InlineData(typeof(TransactionDomainEvents.MerchantFeePendingSettlementAddedToTransactionEvent))]
[InlineData(typeof(TransactionDomainEvents.SettledMerchantFeeAddedToTransactionEvent))]
[InlineData(typeof(SettlementDomainEvents.MerchantFeeSettledEvent))]
//[InlineData(typeof(CustomerEmailReceiptRequestedEvent))]
//[InlineData(typeof(CustomerEmailReceiptResendRequestedEvent))]
[InlineData(typeof(TransactionDomainEvents.CustomerEmailReceiptRequestedEvent))]
[InlineData(typeof(TransactionDomainEvents.CustomerEmailReceiptResendRequestedEvent))]
public async Task TransactionDomainEventHandler_EventPassedIn_EventIsHandled(Type eventType) {
DomainEvent domainEvent = eventType.Name switch {
nameof(FloatDomainEvents.FloatCreditPurchasedEvent) => new FloatDomainEvents.FloatCreditPurchasedEvent(TestData.FloatAggregateId, TestData.EstateId, TestData.CreditPurchasedDateTime, TestData.FloatCreditAmount, TestData.FloatCreditCostPrice),
Expand All @@ -127,39 +127,6 @@ public async Task TransactionDomainEventHandler_EventPassedIn_EventIsHandled(Typ
var result = await this.TransactionDomainEventHandler.Handle(domainEvent, CancellationToken.None);
result.IsSuccess.ShouldBeTrue();
}

[Theory]
[InlineData(typeof(FloatDomainEvents.FloatCreditPurchasedEvent))]
[InlineData(typeof(TransactionDomainEvents.TransactionCostInformationRecordedEvent))]
//[InlineData(typeof(TransactionDomainEvents.TransactionHasBeenCompletedEvent))]
[InlineData(typeof(TransactionDomainEvents.MerchantFeePendingSettlementAddedToTransactionEvent))]
[InlineData(typeof(TransactionDomainEvents.SettledMerchantFeeAddedToTransactionEvent))]
[InlineData(typeof(SettlementDomainEvents.MerchantFeeSettledEvent))]
//[InlineData(typeof(CustomerEmailReceiptRequestedEvent))]
//[InlineData(typeof(CustomerEmailReceiptResendRequestedEvent))]
public async Task TransactionDomainEventHandler_EventPassedIn_Retry_EventIsHandled(Type eventType)
{
this.Mediator.SetupSequence(m => m.Send(It.IsAny<IRequest<Result>>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(Result.Failure(new List<String>() { "Append failed due to WrongExpectedVersion" }))
.ReturnsAsync(Result.Failure(new List<String>() { "DeadlineExceeded" }))
.ReturnsAsync(Result.Success());

DomainEvent domainEvent = eventType.Name switch
{
nameof(FloatDomainEvents.FloatCreditPurchasedEvent) => new FloatDomainEvents.FloatCreditPurchasedEvent(TestData.FloatAggregateId, TestData.EstateId, TestData.CreditPurchasedDateTime, TestData.FloatCreditAmount, TestData.FloatCreditCostPrice),
nameof(TransactionDomainEvents.TransactionCostInformationRecordedEvent) => TestData.TransactionCostInformationRecordedEvent,
nameof(TransactionDomainEvents.TransactionHasBeenCompletedEvent) => TestData.DomainEvents.TransactionHasBeenCompletedEvent,
nameof(TransactionDomainEvents.MerchantFeePendingSettlementAddedToTransactionEvent) => new TransactionDomainEvents.MerchantFeePendingSettlementAddedToTransactionEvent(TestData.TransactionId, TestData.EstateId, TestData.MerchantId, TestData.CalculatedFeeValue, 0, TestData.TransactionFeeId, TestData.TransactionFeeValue, TestData.TransactionFeeCalculateDateTime, TestData.TransactionFeeSettlementDueDate, TestData.TransactionDateTime),
nameof(TransactionDomainEvents.SettledMerchantFeeAddedToTransactionEvent) => TestData.SettledMerchantFeeAddedToTransactionEvent(TestData.SettlementDate),
nameof(SettlementDomainEvents.MerchantFeeSettledEvent) => new SettlementDomainEvents.MerchantFeeSettledEvent(TestData.SettlementAggregateId, TestData.EstateId, TestData.MerchantId, TestData.TransactionId, TestData.CalculatedFeeValue, 0, TestData.TransactionFeeId, TestData.TransactionFeeValue, TestData.TransactionFeeCalculateDateTime, TestData.SettlementDate),
//nameof(TransactionDomainEvents.CustomerEmailReceiptRequestedEvent) => TestData.CustomerEmailReceiptRequestedEvent,
//nameof(TransactionDomainEvents.CustomerEmailReceiptResendRequestedEvent) => TestData.CustomerEmailReceiptResendRequestedEvent,
_ => throw new NotSupportedException($"Event {eventType.Name} not supported")
};

var result = await this.TransactionDomainEventHandler.Handle(domainEvent, CancellationToken.None);
result.IsSuccess.ShouldBeTrue();
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,28 +55,23 @@ public async Task<Result> Handle(IDomainEvent domainEvent,
}

private async Task<Result> HandleSpecificDomainEvent(CallbackReceivedEnrichedEvent domainEvent,
CancellationToken cancellationToken)
{
IAsyncPolicy<Result> retryPolicy = PolicyFactory.CreatePolicy(policyTag: "MerchantSettlementDomainEventHandler - MerchantFeeSettledEvent");

return await PolicyFactory.ExecuteWithPolicyAsync(async () => {
if (domainEvent.TypeString == typeof(CallbackHandler.DataTransferObjects.Deposit).ToString()) {
// Work out the merchant id from the reference field (second part, split on hyphen)
String merchantReference = domainEvent.Reference.Split("-")[1];
CancellationToken cancellationToken) {
if (domainEvent.TypeString == typeof(CallbackHandler.DataTransferObjects.Deposit).ToString()) {
// Work out the merchant id from the reference field (second part, split on hyphen)
String merchantReference = domainEvent.Reference.Split("-")[1];

Result<Merchant> result = await this.EstateReportingRepository.GetMerchantFromReference(domainEvent.EstateId, merchantReference, cancellationToken);
if (result.IsFailed)
return ResultHelpers.CreateFailure(result);
Result<Merchant> result = await this.EstateReportingRepository.GetMerchantFromReference(domainEvent.EstateId, merchantReference, cancellationToken);
if (result.IsFailed)
return ResultHelpers.CreateFailure(result);

// We now need to deserialise the message from the callback
CallbackHandler.DataTransferObjects.Deposit callbackMessage = JsonConvert.DeserializeObject<CallbackHandler.DataTransferObjects.Deposit>(domainEvent.CallbackMessage);
// We now need to deserialise the message from the callback
CallbackHandler.DataTransferObjects.Deposit callbackMessage = JsonConvert.DeserializeObject<CallbackHandler.DataTransferObjects.Deposit>(domainEvent.CallbackMessage);

MerchantCommands.MakeMerchantDepositCommand command = new(domainEvent.EstateId, result.Data.MerchantId, DataTransferObjects.Requests.Merchant.MerchantDepositSource.Automatic, new MakeMerchantDepositRequest { DepositDateTime = callbackMessage.DateTime, Reference = callbackMessage.Reference, Amount = callbackMessage.Amount, });
return await this.Mediator.Send(command, cancellationToken);
}
MerchantCommands.MakeMerchantDepositCommand command = new(domainEvent.EstateId, result.Data.MerchantId, DataTransferObjects.Requests.Merchant.MerchantDepositSource.Automatic, new MakeMerchantDepositRequest { DepositDateTime = callbackMessage.DateTime, Reference = callbackMessage.Reference, Amount = callbackMessage.Amount, });
return await this.Mediator.Send(command, cancellationToken);
}

return Result.Success();
}, retryPolicy, "MerchantSettlementDomainEventHandler - MerchantFeeSettledEvent");
return Result.Success();
}

#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
using Shared.DomainDrivenDesign.EventSourcing;
using Shared.EventStore.EventHandling;
using SimpleResults;
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Prometheus;
using TransactionProcessor.BusinessLogic.Common;
using TransactionProcessor.BusinessLogic.Requests;
using TransactionProcessor.BusinessLogic.Services;
using TransactionProcessor.DomainEvents;

namespace TransactionProcessor.BusinessLogic.EventHandling;
Expand All @@ -20,24 +24,31 @@ public MerchantSettlementDomainEventHandler(IMediator mediator) {

public async Task<Result> Handle(IDomainEvent domainEvent,
CancellationToken cancellationToken) {

Stopwatch sw = Stopwatch.StartNew();
String g = domainEvent.GetType().Name;
String m = this.GetType().Name;
Counter counterCalls = AggregateService.GetCounterMetric($"{m}_{g}_events_processed");
Histogram histogramMetric = AggregateService.GetHistogramMetric($"{m}_{g}");
counterCalls.Inc();

Task<Result> t = domainEvent switch {
SettlementDomainEvents.MerchantFeeSettledEvent mfse => this.HandleSpecificDomainEvent(mfse, cancellationToken),
_ => null
};

Result result = Result.Success();
if (t != null)
return await t;

return Result.Success();
result = await t;
sw.Stop();
histogramMetric.Observe(sw.Elapsed.TotalSeconds);
return result;
}

private async Task<Result> HandleSpecificDomainEvent(SettlementDomainEvents.MerchantFeeSettledEvent domainEvent,
CancellationToken cancellationToken) {
IAsyncPolicy<Result> retryPolicy = PolicyFactory.CreatePolicy(policyTag: "MerchantSettlementDomainEventHandler - MerchantFeeSettledEvent");

return await PolicyFactory.ExecuteWithPolicyAsync(async () => {
MerchantStatementCommands.AddSettledFeeToMerchantStatementCommand command = new(domainEvent.EstateId, domainEvent.MerchantId, domainEvent.FeeCalculatedDateTime, domainEvent.CalculatedValue, domainEvent.TransactionId, domainEvent.FeeId);
MerchantStatementCommands.AddSettledFeeToMerchantStatementCommand command = new(domainEvent.EstateId, domainEvent.MerchantId, domainEvent.FeeCalculatedDateTime, domainEvent.CalculatedValue, domainEvent.TransactionId, domainEvent.FeeId);

return await this.Mediator.Send(command, cancellationToken);
}, retryPolicy, "MerchantSettlementDomainEventHandler - MerchantFeeSettledEvent");
return await this.Mediator.Send(command, cancellationToken);
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
using MediatR;
using System;
using MediatR;
using Polly;
using Shared.DomainDrivenDesign.EventSourcing;
using Shared.EventStore.EventHandling;
using SimpleResults;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Prometheus;
using TransactionProcessor.BusinessLogic.Common;
using TransactionProcessor.BusinessLogic.Requests;
using TransactionProcessor.BusinessLogic.Services;
using TransactionProcessor.DomainEvents;

namespace TransactionProcessor.BusinessLogic.EventHandling
Expand Down Expand Up @@ -41,7 +45,26 @@ public MerchantStatementDomainEventHandler(IMediator mediator)
public async Task<Result> Handle(IDomainEvent domainEvent,
CancellationToken cancellationToken)
{
return await this.HandleSpecificDomainEvent((dynamic)domainEvent, cancellationToken);
Stopwatch sw = Stopwatch.StartNew();
String g = domainEvent.GetType().Name;
String m = this.GetType().Name;
Counter counterCalls = AggregateService.GetCounterMetric($"{m}_{g}_events_processed");
Histogram histogramMetric = AggregateService.GetHistogramMetric($"{m}_{g}");
counterCalls.Inc();

Task<Result> t = domainEvent switch
{
MerchantStatementDomainEvents.StatementGeneratedEvent de => this.HandleSpecificDomainEvent(de, cancellationToken),
TransactionDomainEvents.TransactionHasBeenCompletedEvent de => this.HandleSpecificDomainEvent(de, cancellationToken),
_ => null
};

Result result = Result.Success();
if (t != null)
result = await t;
sw.Stop();
histogramMetric.Observe(sw.Elapsed.TotalSeconds);
return result;
}

/// <summary>
Expand All @@ -51,25 +74,16 @@ public async Task<Result> Handle(IDomainEvent domainEvent,
/// <param name="cancellationToken">The cancellation token.</param>
private async Task<Result> HandleSpecificDomainEvent(MerchantStatementDomainEvents.StatementGeneratedEvent domainEvent,
CancellationToken cancellationToken) {
MerchantStatementCommands.EmailMerchantStatementCommand command = new(domainEvent.EstateId, domainEvent.MerchantId, domainEvent.MerchantStatementId);

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

return await PolicyFactory.ExecuteWithPolicyAsync(async () => {
MerchantStatementCommands.EmailMerchantStatementCommand command = new(domainEvent.EstateId, domainEvent.MerchantId, domainEvent.MerchantStatementId);

return await this.Mediator.Send(command, cancellationToken);
}, retryPolicy, "MerchantStatementDomainEventHandler - StatementGeneratedEvent");
return await this.Mediator.Send(command, cancellationToken);
}

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

return await PolicyFactory.ExecuteWithPolicyAsync(async () => {
MerchantStatementCommands.AddTransactionToMerchantStatementCommand command = new(domainEvent.EstateId, domainEvent.MerchantId, domainEvent.CompletedDateTime, domainEvent.TransactionAmount, domainEvent.IsAuthorised, domainEvent.TransactionId);
MerchantStatementCommands.AddTransactionToMerchantStatementCommand command = new(domainEvent.EstateId, domainEvent.MerchantId, domainEvent.CompletedDateTime, domainEvent.TransactionAmount, domainEvent.IsAuthorised, domainEvent.TransactionId);

return await this.Mediator.Send(command, cancellationToken);
},retryPolicy, "MerchantStatementDomainEventHandler - TransactionHasBeenCompletedEvent");
return await this.Mediator.Send(command, cancellationToken);
}

#endregion
Expand Down
Loading
Loading