Skip to content

Instantly share code, notes, and snippets.

@eulerfx
eulerfx / EventSourcingMonoids.fs
Last active April 8, 2024 10:48
F# event-sourcing with monoids
type Monoid<'a> = {
unit : 'a
op : 'a -> 'a -> 'a
}
let endo<'a> =
{ unit = id
op = fun (f:'a -> 'a) (g:'a -> 'a) -> f << g }
@eulerfx
eulerfx / EventMachines.md
Last active September 8, 2023 22:42
The relationship between state machines and event sourcing

A state machine is defined as follows:

  • Input - a set of inputs
  • Output - a set of outputs
  • State - a set of states
  • S0 ∈ S - an initial state
  • T : Input * State -> Output * State - a transition function

If you model your services (aggregates, projections, process managers, sagas, whatever) as state machines, one issue to address is management of State. There must be a mechanism to provide State to the state machine, and to persist resulting State for subsequent retrieval. One way to address this is by storing State is a key-value store. Another way is to use a SQL database. Yet another way is event sourcing. The benefit of even sourcing is that you never need to store State itself. Instead, you rely on the Output of a service to reconstitute state. In order to do that, the state machine transition function needs to be factored into two functions as follows:

@eulerfx
eulerfx / CSvsES.md
Last active May 21, 2023 08:44
Command Sourcing vs Event Sourcing

Both command sourcing (CS) and event sourcing (ES) rely on determinism for correctness.

The correctness condition for ES is the determinism (purity) of the function State -> Event -> State. Given that this function is deterministic, aka it always maps the same inputs to the same ouputs, we can rely on it to reconstitute state at any point in time. Determinism is typically achieved by ensuring that the Event has all required information to make the state transition, ie no side effects. The Event then is a sort of "closure" of all pertinent information about the event.

The correctness condition for CS is the determinism of the function State -&gt; Command -&gt; Event. Herein lies one of the distinctions between command sourcing and event sourcing - a program can control its output, but it not its input. Since one can't control the input, aka command, one can't in general, enrich it with all required information to make the above function deterministic. A consequence of this is that you can't simply replay a

@eulerfx
eulerfx / PurchaseOrder.cs
Last active September 30, 2022 20:20
An example or a DDD application service.
// A repository.
public interface IPurchaseOrderRepository
{
PurchaseOrder Get(string id);
// The commit method would likely be moved to a Unit of Work managed by infrastructure.
void Commit();
}
// A marker interface for a domain event.
public interface IDomainEvent { }
@eulerfx
eulerfx / ImmutableVo.cs
Created October 15, 2013 22:19
Immutable Money value object in C#
public class Money : IEquatable<Money>
{
public Money(string currency, decimal amount)
{
this.Currency = currency;
this.Amount = amount;
}
public string Currency { get; private set; }
public decimal Amount { get; private set; }
let ParallelThrottledIgnore (startOnCallingThread:bool) (parallelism:int) (xs:seq<Async<_>>) = async {
let! ct = Async.CancellationToken
let sm = new SemaphoreSlim(parallelism)
let count = ref 1
let res = TaskCompletionSource<_>()
let tryWait () =
try sm.Wait () ; true
with _ -> false
let tryComplete () =
if Interlocked.Decrement count = 0 then
@eulerfx
eulerfx / Commands.md
Last active October 26, 2021 19:27
Discussion of the notion of commands and events within reactive system

There are some clear distinctions between commands and events but there are also some not so clear. I discuss the notion of a command as an interpretation of an event.

Commands are requests to do something, they are named in the imperative tense and capture intent. In CQRS, commands are distinguished from queries because they invoke behaviors therefore causing state changes whereas queries don't. In some frameworks, there is a distinction between commands and events in that one sends commands and publishes events. Commands are sent to a single logical handler whereas events are broadcast to potentially multiple handlers.

Events are characterized as being in the past tense. In addition to naming this imposes the constraint that events can't be rejected - you can't change the past. Furthermore, an event can be regarded as an outcome of a command - a causality relation.

There are perspectives where the distinction blurs. For example, what is the distinction between a command handler and an event handler?

@eulerfx
eulerfx / ListConverter.fs
Created January 6, 2013 00:44
A Json.NET converter for the F# list type.
open System
open System.Collections.Generic
open Microsoft.FSharp.Reflection
open Newtonsoft.Json
open Newtonsoft.Json.Converters
type ListConverter() =
inherit JsonConverter()
override x.CanConvert(t:Type) =
@eulerfx
eulerfx / Async.WithCancellation.fs
Created June 21, 2018 20:45
F# Async Cancellation Helper
let withCancellation (ct:CancellationToken) (a:Async<'a>) : Async<'a> = async {
let! ct2 = Async.CancellationToken
use cts = CancellationTokenSource.CreateLinkedTokenSource (ct, ct2)
let tcs = new TaskCompletionSource<'a>()
use _reg = cts.Token.Register (fun () -> tcs.TrySetCanceled() |> ignore)
let a = async {
try
let! a = a
tcs.TrySetResult a |> ignore
with ex ->
@eulerfx
eulerfx / HopacIoCh.fs
Created December 10, 2014 16:11
An F# Hopac input-output channel to ensure that inputs passed to a function are processed one at a time in fifo order
open Hopac
open Hopac.Infixes
open Hopac.Job.Infixes
open Hopac.Extensions
type IoCh<'i, 'o> = Ch<'i * IVar<'o>>
module IoCh =
let create (f:'i -> Job<'o>) : Job<IoCh<'i, 'o>> =