eventful-core-0.1.0: src/Eventful/EventBus.hs
module Eventful.EventBus
( synchronousEventBusWrapper
, storeAndPublishEvents
) where
import Eventful.Store.Class
import Eventful.UUID
-- | This function wraps an event store by sending events to event handlers
-- after running 'storeEvents'. This is useful to quickly wire up event
-- handlers in your application (like read models or process managers), and it
-- is also useful for integration testing along with an in-memory event store.
synchronousEventBusWrapper
:: (Monad m)
=> EventStore serialized m
-> [EventStore serialized m -> UUID -> serialized -> m ()]
-> EventStore serialized m
synchronousEventBusWrapper store handlers =
let
-- NB: We need to use recursive let bindings so we can put wrappedStore
-- inside the event handlers
handlers' = map ($ wrappedStore) handlers
wrappedStore =
EventStore
{ getLatestVersion = getLatestVersion store
, getEvents = getEvents store
, storeEvents = storeAndPublishEvents store handlers'
}
in wrappedStore
-- | Stores events in the store and them publishes them to the event handlers.
-- This is used in the 'synchronousEventBusWrapper'.
storeAndPublishEvents
:: (Monad m)
=> EventStore serialized m
-> [UUID -> serialized -> m ()]
-> ExpectedVersion
-> UUID
-> [serialized]
-> m (Maybe EventWriteError)
storeAndPublishEvents store handlers expectedVersion uuid events = do
result <- storeEvents store expectedVersion uuid events
case result of
Just err -> return $ Just err
Nothing -> do
-- NB: If a handler stores events, then its events will be published
-- before the events of the next handler. That is, we will be storing
-- events generated by handlers in depth-first order.
mapM_ (\handler -> mapM_ (handler uuid) events) handlers
return Nothing