module Eventful.Store.Class
(
EventStore (..)
, GloballyOrderedEventStore (..)
, ExpectedVersion (..)
, EventWriteError (..)
, StoredEvent (..)
, GloballyOrderedEvent (..)
, EventVersion (..)
, SequenceNumber (..)
, transactionalExpectedWriteHelper
) where
import Data.Aeson
import Web.HttpApiData
import Web.PathPieces
import Eventful.UUID
data EventStore serialized m
= EventStore
{ getLatestVersion :: UUID -> m EventVersion
, getEvents :: UUID -> Maybe EventVersion -> m [StoredEvent serialized]
, storeEvents :: ExpectedVersion -> UUID -> [serialized] -> m (Maybe EventWriteError)
}
newtype GloballyOrderedEventStore serialized m =
GloballyOrderedEventStore
{ getSequencedEvents :: SequenceNumber -> m [GloballyOrderedEvent (StoredEvent serialized)]
}
data ExpectedVersion
= AnyVersion
| NoStream
| StreamExists
| ExactVersion EventVersion
deriving (Show, Eq)
data EventWriteError
= EventStreamNotAtExpectedVersion EventVersion
deriving (Show, Eq)
transactionalExpectedWriteHelper
:: (Monad m)
=> (UUID -> m EventVersion)
-> (UUID -> [serialized] -> m ())
-> ExpectedVersion -> UUID -> [serialized] -> m (Maybe EventWriteError)
transactionalExpectedWriteHelper getLatestVersion' storeEvents' expected =
go expected getLatestVersion' storeEvents'
where
go AnyVersion = transactionalExpectedWriteHelper' Nothing
go NoStream = transactionalExpectedWriteHelper' (Just $ (==) (1))
go StreamExists = transactionalExpectedWriteHelper' (Just (> (1)))
go (ExactVersion vers) = transactionalExpectedWriteHelper' (Just $ (==) vers)
transactionalExpectedWriteHelper'
:: (Monad m)
=> Maybe (EventVersion -> Bool)
-> (UUID -> m EventVersion)
-> (UUID -> [serialized] -> m ())
-> UUID -> [serialized] -> m (Maybe EventWriteError)
transactionalExpectedWriteHelper' Nothing _ storeEvents' uuid events =
storeEvents' uuid events >> return Nothing
transactionalExpectedWriteHelper' (Just f) getLatestVersion' storeEvents' uuid events = do
latestVersion <- getLatestVersion' uuid
if f latestVersion
then storeEvents' uuid events >> return Nothing
else return $ Just $ EventStreamNotAtExpectedVersion latestVersion
data StoredEvent event
= StoredEvent
{ storedEventProjectionId :: UUID
, storedEventVersion :: EventVersion
, storedEventEvent :: event
} deriving (Show, Eq, Functor, Foldable, Traversable)
data GloballyOrderedEvent event
= GloballyOrderedEvent
{ globallyOrderedEventSequenceNumber :: SequenceNumber
, globallyOrderedEventEvent :: event
} deriving (Show, Eq, Functor, Foldable, Traversable)
newtype EventVersion = EventVersion { unEventVersion :: Int }
deriving (Show, Read, Ord, Eq, Enum, Num, FromJSON, ToJSON)
newtype SequenceNumber = SequenceNumber { unSequenceNumber :: Int }
deriving (Show, Read, Ord, Eq, Enum, Num, FromJSON, ToJSON,
PathPiece, ToHttpApiData, FromHttpApiData)