packages feed

eventium-memory-0.1.0: src/Eventium/ReadModel/Memory.hs

module Eventium.ReadModel.Memory
  ( memoryReadModel,
  )
where

import Control.Concurrent.STM
import Control.Monad.IO.Class
import Eventium.ReadModel.Class
import Eventium.Store.Class
import Safe (maximumDef)

data MemoryReadModelData modeldata
  = MemoryReadModelData
  { memoryReadModelDataLatestSequenceNumber :: SequenceNumber,
    _memoryReadModelDataValue :: modeldata
  }
  deriving (Show)

-- | Creates a read model that wraps some pure data in a TVar and manages the
-- latest sequence number for you.
memoryReadModel ::
  (MonadIO m) =>
  modeldata ->
  (modeldata -> [GlobalStreamEvent serialized] -> m modeldata) ->
  IO (ReadModel (TVar (MemoryReadModelData modeldata)) serialized m)
memoryReadModel initialValue handleEvents = do
  tvar <- newTVarIO $ MemoryReadModelData (-1) initialValue
  return $ ReadModel tvar getLatestSequence handleTVarEvents
  where
    getLatestSequence tvar' = liftIO $ memoryReadModelDataLatestSequenceNumber <$> readTVarIO tvar'
    handleTVarEvents tvar' events = do
      (MemoryReadModelData latestSeq modelData) <- liftIO $ readTVarIO tvar'
      let latestSeq' = maximumDef latestSeq (streamEventPosition <$> events)
      modelData' <- handleEvents modelData events
      liftIO . atomically . writeTVar tvar' $ MemoryReadModelData latestSeq' modelData'