eventium-core-0.1.0: src/Eventium/EventBus.hs
module Eventium.EventBus
( synchronousEventBusWrapper,
storeAndPublishEvents,
)
where
import Eventium.Store.Class
import Eventium.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) =>
VersionedEventStoreWriter m event ->
[VersionedEventStoreWriter m event -> UUID -> event -> m ()] ->
VersionedEventStoreWriter m event
synchronousEventBusWrapper writer handlers = wrappedStore
where
-- NB: We need to use recursive let bindings so we can put wrappedStore
-- inside the event handlers
handlers' = map ($ wrappedStore) handlers
wrappedStore = EventStoreWriter $ storeAndPublishEvents writer handlers'
-- | Stores events in the store and then publishes them to the event handlers.
-- This is used in the 'synchronousEventBusWrapper'.
storeAndPublishEvents ::
(Monad m) =>
VersionedEventStoreWriter m event ->
[UUID -> event -> m ()] ->
UUID ->
ExpectedPosition EventVersion ->
[event] ->
m (Either (EventWriteError EventVersion) EventVersion)
storeAndPublishEvents store handlers uuid expectedVersion events = do
result <- storeEvents store uuid expectedVersion events
case result of
Left err -> return $ Left err
Right vers -> 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 $ Right vers