Skip to content

Instantly share code, notes, and snippets.

@BashkaMen
Last active August 15, 2021 11:42
Show Gist options
  • Save BashkaMen/ad1737cbeffd37e178133e87ba01cefe to your computer and use it in GitHub Desktop.
Save BashkaMen/ad1737cbeffd37e178133e87ba01cefe to your computer and use it in GitHub Desktop.
type Order = { Id: Guid; Amount: int }
type Client = { Id: Guid; OpenOrders: int; Balance: int }
type CreateOrderAggregate = { Client: Client; Order: Order }
module CreateOrderAggregate =
let execute (agg: CreateOrderAggregate) =
if agg.Client.Balance >= agg.Order.Amount && agg.Client.OpenOrders < 5 then Ok agg
else Error NoMoney
type Handler(conn: AppStoreConnection) =
interface ITransient
member this.Restore id amount = taskResult {
let! client = conn.Value
|> Sql.query "select c.id, c.balance,
(select count(*) from orders o where o.owner_id = @id) as order_count
from clients c
where id = @id"
|> Sql.parameters [ "@id", Sql.uuid id ]
|> Sql.executeAsync ^ fun r -> {
Id = r.uuid "id"
Balance = r.int "balance"
OpenOrders = r.int "order_count"
}
|> Task.map (List.tryHead >> Result.ofOption EntityNotFound)
let order = {
Id = Guid.NewGuid()
Amount = amount
}
return { Client = client; Order = order }
}
member this.Store (agg: CreateOrderAggregate) =
conn.Value
|> Sql.executeTransactionAsync [
"INSERT INTO orders (id, owner_id, amount)
VALUES (@id, @owner_id, @amount)", [
[
"@id", Sql.uuid agg.Order.Id
"@owner_id", Sql.uuid agg.Client.Id
"@amount", Sql.int agg.Order.Amount
]
]
"UPDATE clients SET balance = @balance", [
[ "@balance", Sql.int agg.Client.Balance ]
]
]
|> Task.Ignore
member this.Execute id amount = taskResult {
let! state = this.Restore id amount
let! state = CreateOrderAggregate.execute state
do! this.Store state
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment