Created
April 8, 2014 12:53
-
-
Save AlexSugak/10119582 to your computer and use it in GitHub Desktop.
CQRS/Event Sourcing with F#, based on Greg Young's sample https://github.com/gregoryyoung/m-r and https://gist.github.com/ToJans/8219629#file-inventoryitems-hs
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
exception ItemAlreadyExists of string | |
exception ItemNotFound of string | |
exception DomainError of string | |
type Command = | |
| CreateInventoryItem of Id: int | |
| RenameInventoryItem of Id: int * Name: string | |
| RemoveItemsFromInventory of Id: int * Amount: int | |
| AddItemsToInventory of Id: int * Amount: int | |
| DeactivateInventoryItem of Id: int | |
type Event = | |
| InventoryItemCreated of Id: int | |
| InventoryItemRenamed of Id: int * Name: string | |
| ItemsRemovedFromInventory of Id: int * Amount: int | |
| ItemsCheckedInToInventory of Id: int * Amount: int | |
| InventoryItemDeactivated of Id: int | |
type InventoryItem = { | |
Id: int | |
Name: string option | |
Amount: int | |
IsDeactivated : bool | |
} | |
let apply item event = | |
match item, event with | |
| None, InventoryItemCreated(id) -> { Id = id; Name = None; IsDeactivated = false; Amount = 0; } | |
| None, _ -> raise (System.ArgumentException("unknown event")) | |
| Some(i), InventoryItemRenamed(id, name) -> { i with Name = Some(name); } | |
| Some(i), ItemsRemovedFromInventory(id, amount) -> { i with Amount = i.Amount - amount; } | |
| Some(i), ItemsCheckedInToInventory(id, amount) -> { i with Amount = i.Amount + amount; } | |
| Some(i), InventoryItemDeactivated(id) -> { i with IsDeactivated = true; } | |
| Some(i), _ -> i | |
let handle events command = | |
let item = events |> Seq.fold (fun acc e -> Some(apply acc e)) None | |
match item, command with | |
| None, CreateInventoryItem(id) -> [InventoryItemCreated(id)] | |
| Some(i), CreateInventoryItem(id) -> raise (ItemAlreadyExists("item already created")) | |
| None, _ -> raise (ItemNotFound("item not found")) | |
| Some(i), RenameInventoryItem(id, name) -> [InventoryItemRenamed(id, name)] | |
| Some(i), RemoveItemsFromInventory(id, amount) -> match i with | |
| i when i.Amount < amount -> raise (DomainError("item does not have enough inventory")) | |
| _ -> [ItemsRemovedFromInventory(id, amount)] | |
| Some(i), AddItemsToInventory(id, amount) -> [ItemsCheckedInToInventory(id, amount)] | |
| Some(i), DeactivateInventoryItem(id) -> match i with | |
| i when i.IsDeactivated -> raise (DomainError("item already deactivated")) | |
| _ -> [InventoryItemDeactivated(id)] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment