-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
202 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
Samples/Cleipnir.Flows.Sample.Presentation.AspNet/Flows/BankTransfer/IBankCentralClient.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
using Cleipnir.ResilientFunctions.Helpers; | ||
|
||
namespace Cleipnir.Flows.Sample.MicrosoftOpen.Flows.BankTransfer; | ||
|
||
public interface IBankCentralClient | ||
{ | ||
Task PostTransaction(Guid transactionId, string account, decimal amount); | ||
Task<decimal> GetAvailableFunds(string account); | ||
} | ||
|
||
public class BankCentralClient : IBankCentralClient | ||
{ | ||
public Task PostTransaction(Guid transactionId, string account, decimal amount) | ||
{ | ||
Console.WriteLine($"POSTING: {amount} to {account} account"); | ||
return Task.Delay(1_000).ContinueWith(_ => true); | ||
} | ||
|
||
public Task<decimal> GetAvailableFunds(string account) => 100M.ToTask(); | ||
} |
8 changes: 8 additions & 0 deletions
8
Samples/Cleipnir.Flows.Sample.Presentation.AspNet/Flows/BankTransfer/Transfer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
namespace Cleipnir.Flows.Sample.MicrosoftOpen.Flows.BankTransfer; | ||
|
||
public record Transfer( | ||
Guid TransactionId, | ||
string FromAccount, | ||
string ToAccount, | ||
decimal Amount | ||
); |
29 changes: 29 additions & 0 deletions
29
Samples/Cleipnir.Flows.Sample.Presentation.AspNet/Flows/BankTransfer/TransferFlow.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
using Cleipnir.ResilientFunctions.Domain; | ||
|
||
namespace Cleipnir.Flows.Sample.MicrosoftOpen.Flows.BankTransfer; | ||
|
||
[GenerateFlows] | ||
public class TransferFlow(IBankCentralClient bankCentralClient) : Flow<Transfer> | ||
{ | ||
public override async Task Run(Transfer transfer) | ||
{ | ||
var availableFunds = await bankCentralClient.GetAvailableFunds(transfer.FromAccount); | ||
if (availableFunds <= transfer.Amount) | ||
throw new InvalidOperationException("Insufficient funds on from account"); | ||
|
||
await bankCentralClient.PostTransaction( | ||
transfer.TransactionId, | ||
transfer.FromAccount, | ||
-transfer.Amount | ||
); | ||
|
||
await bankCentralClient.PostTransaction( | ||
transfer.TransactionId, | ||
transfer.ToAccount, | ||
transfer.Amount | ||
); | ||
} | ||
|
||
private DistributedSemaphore DistributedLock(string account) | ||
=> Workflow.Semaphores.Create("BankTransfer", account, maximumCount: 1); | ||
} |
2 changes: 0 additions & 2 deletions
2
Samples/Cleipnir.Flows.Sample.Presentation.AspNet/Flows/Batch/BatchOrderFlow.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
Samples/Cleipnir.Flows.Sample.Presentation.AspNet/Flows/MessageDriven/Other/Bus.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
83 changes: 83 additions & 0 deletions
83
Samples/Cleipnir.Flows.Sample.Presentation.AspNet/Flows/Rpc/Solution/OrderFlowWithCleanUp.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
using Cleipnir.Flows.Sample.MicrosoftOpen.Clients; | ||
|
||
namespace Cleipnir.Flows.Sample.MicrosoftOpen.Flows.Rpc.Solution; | ||
|
||
public class OrderFlowWithCleanUp( | ||
IPaymentProviderClient paymentProviderClient, | ||
IEmailClient emailClient, | ||
ILogisticsClient logisticsClient) | ||
: Flow<Order> | ||
{ | ||
public override async Task Run(Order order) | ||
{ | ||
var transactionId = Guid.NewGuid(); | ||
|
||
TrackAndTrace? trackAndTrace = null; | ||
var steps = new StepAndCleanUp[] | ||
{ | ||
new( | ||
Work: () => paymentProviderClient.Reserve(transactionId, order.CustomerId, order.TotalPrice), | ||
CleanUp: () => CleanUp(FailedAt.ProductsShipped, transactionId, trackAndTrace: null) | ||
), | ||
new( | ||
Work: async () => | ||
{ | ||
trackAndTrace = await Capture(async () => | ||
await logisticsClient.ShipProducts(order.CustomerId, order.ProductIds) | ||
); | ||
}, | ||
CleanUp: () => CleanUp(FailedAt.ProductsShipped, transactionId, trackAndTrace: null) | ||
), | ||
new( | ||
Work: () => paymentProviderClient.Capture(transactionId), | ||
CleanUp: () => CleanUp(FailedAt.FundsCaptured, transactionId, trackAndTrace) | ||
), | ||
new ( | ||
Work: () => emailClient.SendOrderConfirmation(order.CustomerId, trackAndTrace!, order.ProductIds), | ||
CleanUp: () => CleanUp(FailedAt.OrderConfirmationEmailSent, transactionId, trackAndTrace) | ||
) | ||
}; | ||
|
||
foreach (var step in steps) | ||
try | ||
{ | ||
await step.Work(); | ||
} | ||
catch (Exception) | ||
{ | ||
await step.CleanUp(); | ||
throw; | ||
} | ||
} | ||
|
||
private async Task CleanUp(FailedAt failedAt, Guid transactionId, TrackAndTrace? trackAndTrace) | ||
{ | ||
switch (failedAt) | ||
{ | ||
case FailedAt.FundsReserved: | ||
break; | ||
case FailedAt.ProductsShipped: | ||
await paymentProviderClient.CancelReservation(transactionId); | ||
break; | ||
case FailedAt.FundsCaptured: | ||
await paymentProviderClient.Reverse(transactionId); | ||
await logisticsClient.CancelShipment(trackAndTrace!); | ||
break; | ||
case FailedAt.OrderConfirmationEmailSent: | ||
//we accept this failure without cleaning up | ||
break; | ||
default: | ||
throw new ArgumentOutOfRangeException(nameof(failedAt), failedAt, null); | ||
} | ||
} | ||
|
||
private record StepAndCleanUp(Func<Task> Work, Func<Task> CleanUp); | ||
|
||
private enum FailedAt | ||
{ | ||
FundsReserved, | ||
ProductsShipped, | ||
FundsCaptured, | ||
OrderConfirmationEmailSent, | ||
} | ||
} |