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