Skip to content

Instantly share code, notes, and snippets.

@adamralph
Created October 22, 2018 19:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adamralph/5dc87f9d7f0390108697f87dec6f11cd to your computer and use it in GitHub Desktop.
Save adamralph/5dc87f9d7f0390108697f87dec6f11cd to your computer and use it in GitHub Desktop.
My solution to the saga homework for https://particular.net/adsd
namespace UdiWorld
{
using System;
using System.Threading.Tasks;
using NServiceBus;
public class UserBecamePreferred
{
public Guid UserId { get; set; }
}
public class UserBecameUnpreferred
{
public Guid UserId { get; set; }
}
public class UdiCoinsPurchased
{
public Guid UserId { get; set; }
public int Amount { get; set; }
}
public class BuyItem
{
public Guid UserId { get; set; }
public Guid ItemId { get; set; }
public int Price { get; set; }
}
public class DecrementOneWeekTotal
{
public int Amount { get; set; }
}
public class DecrementTwoWeekTotal
{
public int Amount { get; set; }
}
public class FulfillPurchase
{
public Guid UserId { get; set; }
public Guid ItemId { get; set; }
}
public class BalanceInsufficient
{
public Guid UserId { get; set; }
public Guid ItemId { get; set; }
}
public class InAppPurchases : Saga<InAppPurchases.State>,
IAmStartedByMessages<UserBecamePreferred>,
IAmStartedByMessages<UserBecameUnpreferred>,
IAmStartedByMessages<UdiCoinsPurchased>,
IAmStartedByMessages<BuyItem>,
IHandleTimeouts<DecrementOneWeekTotal>,
IHandleTimeouts<DecrementTwoWeekTotal>
{
public Task Handle(UserBecamePreferred message, IMessageHandlerContext context)
{
Data.IsPreferred = true;
return Task.CompletedTask;
}
public Task Handle(UserBecameUnpreferred message, IMessageHandlerContext context)
{
Data.IsPreferred = false;
return Task.CompletedTask;
}
public Task Handle(UdiCoinsPurchased message, IMessageHandlerContext context)
{
Data.Balance += message.Amount;
return Task.CompletedTask;
}
public async Task Handle(BuyItem message, IMessageHandlerContext context)
{
var totalOrderValue = Data.IsPreferred
? Data.TwoWeekTotal
: Data.OneWeekTotal;
var discount = totalOrderValue > 100
? 0.2
: 0.1;
var price = (int)(message.Price * (1 - discount));
if (Data.Balance > price)
{
Data.Balance -= price;
Data.OneWeekTotal += message.Price;
await RequestTimeout(context, TimeSpan.FromDays(7), new DecrementOneWeekTotal { Amount = message.Price });
Data.TwoWeekTotal += message.Price;
await RequestTimeout(context, TimeSpan.FromDays(14), new DecrementTwoWeekTotal { Amount = message.Price });
await context.Send(new FulfillPurchase { UserId = message.UserId, ItemId = message.ItemId });
}
else
{
await context.Publish(new BalanceInsufficient { UserId = message.UserId, ItemId = message.ItemId });
}
}
public Task Timeout(DecrementOneWeekTotal state, IMessageHandlerContext context)
{
Data.OneWeekTotal -= state.Amount;
return Task.CompletedTask;
}
public Task Timeout(DecrementTwoWeekTotal state, IMessageHandlerContext context)
{
Data.TwoWeekTotal -= state.Amount;
return Task.CompletedTask;
}
protected override void ConfigureHowToFindSaga(SagaPropertyMapper<State> mapper)
{
mapper.ConfigureMapping<UserBecamePreferred>(m => m.UserId).ToSaga(s => s.UserId);
mapper.ConfigureMapping<UserBecameUnpreferred>(m => m.UserId).ToSaga(s => s.UserId);
mapper.ConfigureMapping<UdiCoinsPurchased>(m => m.UserId).ToSaga(s => s.UserId);
mapper.ConfigureMapping<BuyItem>(m => m.UserId).ToSaga(s => s.UserId);
}
public class State : ContainSagaData
{
public Guid UserId { get; set; }
public bool IsPreferred { get; set; }
public int OneWeekTotal { get; set; }
public int TwoWeekTotal { get; set; }
public int Balance { get; set; }
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment