diff --git a/MessagingService.BusinessLogic/Services/MessagingDomainService.cs b/MessagingService.BusinessLogic/Services/MessagingDomainService.cs index fe99a28..76dbf42 100644 --- a/MessagingService.BusinessLogic/Services/MessagingDomainService.cs +++ b/MessagingService.BusinessLogic/Services/MessagingDomainService.cs @@ -6,14 +6,10 @@ namespace MessagingService.BusinessLogic.Services { using System; using System.Collections.Generic; - using System.Diagnostics.Contracts; - using System.Net.Mail; using System.Threading; using System.Threading.Tasks; - using EmailMessage.DomainEvents; using EmailMessageAggregate; using EmailServices; - using Microsoft.Extensions.Logging; using Models; using Shared.DomainDrivenDesign.EventSourcing; using Shared.EventStore.Aggregate; @@ -158,20 +154,23 @@ public async Task> SendSMSMessage(Guid connectionIdentifier, { Result result = await ApplySMSUpdates(async (SMSAggregate smsAggregate) => { // Check if this message has been sent before - if (smsAggregate.GetMessageStatus() != SMSMessageAggregate.MessageStatus.NotSet) - { + if (smsAggregate.GetMessageStatus() != SMSMessageAggregate.MessageStatus.NotSet) { return Result.Success(); } // send message to provider (record event) - smsAggregate.SendRequestToProvider(sender, destination, message); + Result stateResult = smsAggregate.SendRequestToProvider(sender, destination, message); + if (stateResult.IsFailed) + return stateResult; // Make call to SMS provider here SMSServiceProxyResponse smsResponse = await this.SmsServiceProxy.SendSMS(messageId, sender, destination, message, cancellationToken); // response message from provider (record event) - smsAggregate.ReceiveResponseFromProvider(smsResponse.SMSIdentifier); + stateResult= smsAggregate.ReceiveResponseFromProvider(smsResponse.SMSIdentifier); + if (stateResult.IsFailed) + return stateResult; return Result.Success(); }, messageId, cancellationToken, false); @@ -219,14 +218,18 @@ await this.EmailServiceProxy.SendEmail(messageId, emailAggregate.FromAddress, public async Task ResendSMSMessage(Guid connectionIdentifier, Guid messageId, CancellationToken cancellationToken){ Result result = await ApplySMSUpdates(async (SMSAggregate smsAggregate) => { // re-send message to provider (record event) - smsAggregate.ResendRequestToProvider(); + Result stateResult = smsAggregate.ResendRequestToProvider(); + if (stateResult.IsFailed) + return stateResult; // Make call to SMS provider here SMSServiceProxyResponse smsResponse = await this.SmsServiceProxy.SendSMS(messageId, smsAggregate.Sender, smsAggregate.Destination, smsAggregate.Message, cancellationToken); // response message from provider (record event) - smsAggregate.ReceiveResponseFromProvider(smsResponse.SMSIdentifier); + stateResult = smsAggregate.ReceiveResponseFromProvider(smsResponse.SMSIdentifier); + if (stateResult.IsFailed) + return stateResult; return Result.Success(); }, messageId, cancellationToken); @@ -273,27 +276,30 @@ public async Task UpdateMessageStatus(EmailCommands.UpdateMessageStatusC public async Task UpdateMessageStatus(SMSCommands.UpdateMessageStatusCommand command, CancellationToken cancellationToken) { Result result = await ApplySMSUpdates(async (SMSAggregate smsAggregate) => { + Result stateResult; switch (command.Status) { case SMSServices.MessageStatus.Delivered: case SMSServices.MessageStatus.Sent: case SMSServices.MessageStatus.InProgress: - smsAggregate.MarkMessageAsDelivered(command.Description, command.Timestamp); + stateResult = smsAggregate.MarkMessageAsDelivered(command.Description, command.Timestamp); break; case SMSServices.MessageStatus.Expired: - smsAggregate.MarkMessageAsExpired(command.Description, command.Timestamp); + stateResult = smsAggregate.MarkMessageAsExpired(command.Description, command.Timestamp); break; case SMSServices.MessageStatus.Rejected: - smsAggregate.MarkMessageAsRejected(command.Description, command.Timestamp); + stateResult = smsAggregate.MarkMessageAsRejected(command.Description, command.Timestamp); break; case SMSServices.MessageStatus.Undeliverable: - smsAggregate.MarkMessageAsUndeliverable(command.Description, command.Timestamp); + stateResult = smsAggregate.MarkMessageAsUndeliverable(command.Description, command.Timestamp); break; default: - smsAggregate.MarkMessageAsRejected(command.Description, command.Timestamp); + stateResult = smsAggregate.MarkMessageAsRejected(command.Description, command.Timestamp); break; } - + if (stateResult.IsFailed) + return stateResult; + return Result.Success(); }, command.MessageId, cancellationToken); return result; diff --git a/MessagingService.SMSAggregate.Tests/SMSAggregateTests.cs b/MessagingService.SMSAggregate.Tests/SMSAggregateTests.cs index 96b1428..23ddff4 100644 --- a/MessagingService.SMSAggregate.Tests/SMSAggregateTests.cs +++ b/MessagingService.SMSAggregate.Tests/SMSAggregateTests.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Text; +using SimpleResults; namespace MessagingService.SMSAggregate.Tests { @@ -95,7 +96,9 @@ public void SMSAggregate_MarkMessageAsDelivered_IncorrectState_ErrorThrown(Messa break; } - Should.Throw(() => smsAggregate.MarkMessageAsDelivered(TestData.ProviderStatusDescription, TestData.DeliveredDateTime)); + var result = smsAggregate.MarkMessageAsDelivered(TestData.ProviderStatusDescription, TestData.DeliveredDateTime); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Fact] @@ -147,7 +150,9 @@ public void SMSAggregate_MarkMessageAsExpired_IncorrectState_ErrorThrown(Message break; } - Should.Throw(() => smsAggregate.MarkMessageAsExpired(TestData.ProviderStatusDescription, TestData.DeliveredDateTime)); + var result = smsAggregate.MarkMessageAsExpired(TestData.ProviderStatusDescription, TestData.DeliveredDateTime); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Fact] @@ -199,7 +204,9 @@ public void SMSAggregate_MarkMessageAsUndeliverable_IncorrectState_ErrorThrown(M break; } - Should.Throw(() => smsAggregate.MarkMessageAsUndeliverable(TestData.ProviderStatusDescription, TestData.DeliveredDateTime)); + var result = smsAggregate.MarkMessageAsUndeliverable(TestData.ProviderStatusDescription, TestData.DeliveredDateTime); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Fact] @@ -251,7 +258,9 @@ public void SMSAggregate_MarkMessageAsRejected_IncorrectState_ErrorThrown(Messag break; } - Should.Throw(() => smsAggregate.MarkMessageAsRejected(TestData.ProviderStatusDescription, TestData.DeliveredDateTime)); + var result = smsAggregate.MarkMessageAsRejected(TestData.ProviderStatusDescription, TestData.DeliveredDateTime); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Fact] @@ -288,7 +297,9 @@ public void SMSAggregate_ResendRequestToProvider_NotSet_ErrorThrown() { SMSAggregate smsAggregate = SMSAggregate.Create(TestData.MessageId); - Should.Throw(() => smsAggregate.ResendRequestToProvider()); + var result = smsAggregate.ResendRequestToProvider(); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Fact] @@ -297,7 +308,9 @@ public void SMSAggregate_ResendRequestToProvider_InProgress_ErrorThrown() SMSAggregate smsAggregate = SMSAggregate.Create(TestData.MessageId); smsAggregate.SendRequestToProvider(TestData.Sender, TestData.Destination, TestData.Message); - Should.Throw(() => smsAggregate.ResendRequestToProvider()); + var result = smsAggregate.ResendRequestToProvider(); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Fact] @@ -308,7 +321,9 @@ public void SMSAggregate_ResendRequestToProvider_Rejected_ErrorThrown() smsAggregate.SendRequestToProvider(TestData.Sender, TestData.Destination, TestData.Message); smsAggregate.ReceiveResponseFromProvider(TestData.ProviderSMSReference); smsAggregate.MarkMessageAsRejected(TestData.ProviderStatusDescription, TestData.RejectedDateTime); - Should.Throw(() => smsAggregate.ResendRequestToProvider()); + var result = smsAggregate.ResendRequestToProvider(); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Fact] @@ -319,7 +334,9 @@ public void SMSAggregate_ResendRequestToProvider_Expired_ErrorThrown() smsAggregate.SendRequestToProvider(TestData.Sender, TestData.Destination, TestData.Message); smsAggregate.ReceiveResponseFromProvider(TestData.ProviderSMSReference); smsAggregate.MarkMessageAsExpired(TestData.ProviderStatusDescription, TestData.ExpiredDateTime); - Should.Throw(() => smsAggregate.ResendRequestToProvider()); + var result = smsAggregate.ResendRequestToProvider(); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Fact] @@ -330,7 +347,9 @@ public void SMSAggregate_ResendRequestToProvider_Undelivered_ErrorThrown() smsAggregate.SendRequestToProvider(TestData.Sender, TestData.Destination, TestData.Message); smsAggregate.ReceiveResponseFromProvider(TestData.ProviderSMSReference); smsAggregate.MarkMessageAsUndeliverable(TestData.ProviderStatusDescription, TestData.UndeliveredDateTime); - Should.Throw(() => smsAggregate.ResendRequestToProvider()); + var result = smsAggregate.ResendRequestToProvider(); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Fact] diff --git a/MessagingService.SMSMessageAggregate/SMSAggregate.cs b/MessagingService.SMSMessageAggregate/SMSAggregate.cs index 6d69ab3..7444a15 100644 --- a/MessagingService.SMSMessageAggregate/SMSAggregate.cs +++ b/MessagingService.SMSMessageAggregate/SMSAggregate.cs @@ -1,4 +1,6 @@ -namespace MessagingService.SMSMessageAggregate{ +using SimpleResults; + +namespace MessagingService.SMSMessageAggregate{ using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; @@ -18,53 +20,63 @@ public static MessageStatus GetDeliveryStatus(this SMSAggregate aggregate, Int32 return aggregate.DeliveryStatusList[resendAttempt.Value]; } - public static void MarkMessageAsDelivered(this SMSAggregate aggregate, + public static Result MarkMessageAsDelivered(this SMSAggregate aggregate, String providerStatus, DateTime failedDateTime){ if (aggregate.DeliveryStatusList[aggregate.ResendCount] == MessageStatus.Delivered) - return; - - aggregate.CheckMessageCanBeSetToDelivered(); + return Result.Success(); + Result result = aggregate.CheckMessageCanBeSetToDelivered(); + if (result.IsFailed) + return result; SMSMessageDeliveredEvent messageDeliveredEvent = new(aggregate.AggregateId, providerStatus, failedDateTime); aggregate.ApplyAndAppend(messageDeliveredEvent); + return Result.Success(); } - public static void MarkMessageAsExpired(this SMSAggregate aggregate, + public static Result MarkMessageAsExpired(this SMSAggregate aggregate, String providerStatus, DateTime failedDateTime){ if (aggregate.DeliveryStatusList[aggregate.ResendCount] == MessageStatus.Expired) - return; - aggregate.CheckMessageCanBeSetToExpired(); - + return Result.Success(); + Result result = aggregate.CheckMessageCanBeSetToExpired(); + if (result.IsFailed) + return result; SMSMessageExpiredEvent messageExpiredEvent = new(aggregate.AggregateId, providerStatus, failedDateTime); aggregate.ApplyAndAppend(messageExpiredEvent); + + return Result.Success(); } - public static void MarkMessageAsRejected(this SMSAggregate aggregate, + public static Result MarkMessageAsRejected(this SMSAggregate aggregate, String providerStatus, DateTime failedDateTime){ if (aggregate.DeliveryStatusList[aggregate.ResendCount] == MessageStatus.Rejected) - return; - aggregate.CheckMessageCanBeSetToRejected(); - + return Result.Success(); + Result result = aggregate.CheckMessageCanBeSetToRejected(); + if (result.IsFailed) + return result; SMSMessageRejectedEvent messageRejectedEvent = new(aggregate.AggregateId, providerStatus, failedDateTime); aggregate.ApplyAndAppend(messageRejectedEvent); + + return Result.Success(); } - public static void MarkMessageAsUndeliverable(this SMSAggregate aggregate, + public static Result MarkMessageAsUndeliverable(this SMSAggregate aggregate, String providerStatus, DateTime failedDateTime){ if (aggregate.DeliveryStatusList[aggregate.ResendCount] == MessageStatus.Undeliverable) - return; - aggregate.CheckMessageCanBeSetToUndeliverable(); - + return Result.Success(); + Result result = aggregate.CheckMessageCanBeSetToUndeliverable(); + if (result.IsFailed) + return result; SMSMessageUndeliveredEvent messageUndeliveredEvent = new(aggregate.AggregateId, providerStatus, failedDateTime); aggregate.ApplyAndAppend(messageUndeliveredEvent); + return Result.Success(); } public static void PlayEvent(this SMSAggregate aggregate, RequestSentToSMSProviderEvent domainEvent){ @@ -100,25 +112,29 @@ public static void PlayEvent(this SMSAggregate aggregate, RequestResentToSMSProv aggregate.DeliveryStatusList.Add(MessageStatus.InProgress); } - public static void ReceiveResponseFromProvider(this SMSAggregate aggregate, String providerSMSReference){ + public static Result ReceiveResponseFromProvider(this SMSAggregate aggregate, String providerSMSReference){ ResponseReceivedFromSMSProviderEvent responseReceivedFromProviderEvent = new(aggregate.AggregateId, providerSMSReference); aggregate.ApplyAndAppend(responseReceivedFromProviderEvent); + + return Result.Success(); } - public static void ResendRequestToProvider(this SMSAggregate aggregate){ + public static Result ResendRequestToProvider(this SMSAggregate aggregate){ if (aggregate.DeliveryStatusList[aggregate.ResendCount] != MessageStatus.Sent && aggregate.DeliveryStatusList[aggregate.ResendCount] != MessageStatus.Delivered){ - throw new InvalidOperationException($"Cannot re-send a message to provider that has not already been sent. Current Status [{aggregate.DeliveryStatusList[aggregate.ResendCount]}]"); + return Result.Invalid($"Cannot re-send a message to provider that has not already been sent. Current Status [{aggregate.DeliveryStatusList[aggregate.ResendCount]}]"); } RequestResentToSMSProviderEvent requestResentToSMSProviderEvent = new(aggregate.AggregateId); aggregate.ApplyAndAppend(requestResentToSMSProviderEvent); + + return Result.Success(); } - public static void SendRequestToProvider(this SMSAggregate aggregate, + public static Result SendRequestToProvider(this SMSAggregate aggregate, String sender, String destination, String message){ @@ -127,30 +143,36 @@ public static void SendRequestToProvider(this SMSAggregate aggregate, RequestSentToSMSProviderEvent requestSentToProviderEvent = new(aggregate.AggregateId, sender, destination, message); aggregate.ApplyAndAppend(requestSentToProviderEvent); + + return Result.Success(); } - private static void CheckMessageCanBeSetToDelivered(this SMSAggregate aggregate) { + private static Result CheckMessageCanBeSetToDelivered(this SMSAggregate aggregate) { if (aggregate.DeliveryStatusList[aggregate.ResendCount] != MessageStatus.Sent){ - throw new InvalidOperationException($"Message at status {aggregate.DeliveryStatusList[aggregate.ResendCount]} cannot be set to delivered"); + return Result.Invalid($"Message at status {aggregate.DeliveryStatusList[aggregate.ResendCount]} cannot be set to delivered"); } + return Result.Success(); } - private static void CheckMessageCanBeSetToExpired(this SMSAggregate aggregate){ + private static Result CheckMessageCanBeSetToExpired(this SMSAggregate aggregate){ if (aggregate.DeliveryStatusList[aggregate.ResendCount] != MessageStatus.Sent){ - throw new InvalidOperationException($"Message at status {aggregate.DeliveryStatusList[aggregate.ResendCount]} cannot be set to expired"); + return Result.Invalid($"Message at status {aggregate.DeliveryStatusList[aggregate.ResendCount]} cannot be set to expired"); } + return Result.Success(); } - private static void CheckMessageCanBeSetToRejected(this SMSAggregate aggregate){ + private static Result CheckMessageCanBeSetToRejected(this SMSAggregate aggregate){ if (aggregate.DeliveryStatusList[aggregate.ResendCount] != MessageStatus.Sent){ - throw new InvalidOperationException($"Message at status {aggregate.DeliveryStatusList[aggregate.ResendCount]} cannot be set to rejected"); + return Result.Invalid($"Message at status {aggregate.DeliveryStatusList[aggregate.ResendCount]} cannot be set to rejected"); } + return Result.Success(); } - private static void CheckMessageCanBeSetToUndeliverable(this SMSAggregate aggregate){ + private static Result CheckMessageCanBeSetToUndeliverable(this SMSAggregate aggregate){ if (aggregate.DeliveryStatusList[aggregate.ResendCount] != MessageStatus.Sent){ - throw new InvalidOperationException($"Message at status {aggregate.DeliveryStatusList[aggregate.ResendCount]} cannot be set to undeliverable"); + return Result.Invalid($"Message at status {aggregate.DeliveryStatusList[aggregate.ResendCount]} cannot be set to undeliverable"); } + return Result.Success(); } public static MessageStatus GetMessageStatus(this SMSAggregate aggregate) {