This is something I burned my fingers on. I used a projection in a read-model and this didn't go well. What happened is that I had these projections:
let updateRegisteredPatients (set: Set<_>) event =
match event with
| Registered pat ->
pat |> set.Add
| _ -> set
let registerdPatients =
{
Init = Set.empty
Update = updateRegisteredPatients
}
let admittedPatients events =
let registered =
events
|> (Projection.project registerdPatients)
|> Set.toList
events
|> List.fold (fun acc e ->
match e with
| Admitted hn ->
match registered
|> List.tryFind (fun pat -> pat.HospitalNumber = hn) with
| Some pat -> acc |> List.append [ pat ]
| None -> acc
| _ -> acc
) []
let registered () : ReadModel<_, _> =
let updateState state evs =
evs
|> List.fold (Projection.intoMap Projections.registerdPatients)
state
ReadModel.inMemory updateState Map.empty
let admitted () : ReadModel<_, _> =
let updateState state evs =
evs
|> Event.asEvents
|> Projections.admittedPatients
|> List.append state
ReadModel.inMemory updateState []
And then things fall apart. The read model only receives the new events. So, when a patient is admitted, only the admitted event is passed to the readmodel. This works fine for the registered patients read model, but the admitted patients read model passes these admitted events to the admittedPatients
projection that will always return an empty list, as it cannot reconstruct the registered patients.
This was quite hard to detect (meaning it took me more than half an hour). And generally, I try to avoid these kind of errors like the plague. So, my inclination now is to completely separate the event handling and projection logic from the read model logic and not to use projections in readmodels.