cqrs-example-0.10.0: src/CQRSExample/Aggregates.hs
{-# LANGUAGE DeriveGeneric #-}
module CQRSExample.Aggregates
( newTask
, Task(..)
, TaskId
, TaskStatus(..)
) where
import Control.DeepSeq (NFData(..))
import Control.Monad (unless)
import Data.Serialize (Serialize(..), getWord8, putWord8)
import Data.Text (Text)
import qualified Data.Text as T
import Data.Typeable (Typeable)
import Data.UUID.Types (UUID)
import GHC.Generics (Generic)
-- Tasks.
type TaskId = UUID
data TaskStatus = TaskStatusOpen
| TaskStatusComplete
| TaskStatusArchived
deriving (Typeable, Eq, Show, Generic)
data Task = Task
{ taskTitle :: Text
, taskStatus :: TaskStatus
} deriving (Typeable, Eq, Show, Generic)
newTask :: Text -> Task
newTask title = Task title TaskStatusOpen
-- Serialize instances for snapshots. In the case of snapshots,
-- compatibility is not that important and de-serialization can fail
-- without huge host, i.e. the aggregate can always be reconstructed
-- from events rather than using the snapshot. It *is* important that
-- a format change is detected, though, which is why we're putting in
-- a "version" marker.
instance Serialize TaskStatus where
put status = do
putWord8 1 -- Version number.
case status of
TaskStatusOpen -> putWord8 1
TaskStatusComplete -> putWord8 2
TaskStatusArchived -> putWord8 3
get = do
v <- getWord8 -- Version number.
unless (v == 1) $ fail "Not the correct version"
i <- getWord8
case i of
1 -> return TaskStatusOpen
2 -> return TaskStatusComplete
3 -> return TaskStatusArchived
_ -> error "Versioning inconsistency; this is BAD"
instance Serialize Task where
put (Task t1 t2) = do
putWord8 1 -- Version marker.
put $ T.unpack t1
put t2
get = do
v <- getWord8 -- Version number
unless (v == 1) $ fail "Not the correct version"
t1 <- fmap T.pack get
t2 <- get
return $ Task t1 t2
-- NFData instances.
instance NFData TaskStatus
instance NFData Task