cqrs-example-0.9.0: src/CQRSExample/Aggregates.hs
module CQRSExample.Aggregates
( newTask
, Task(..)
, TaskId
, TaskStatus(..)
) where
import Control.DeepSeq (NFData(..))
import Control.Monad (unless)
import Data.CQRS.Command (Aggregate)
import Data.CQRS.GUID (GUID)
import Data.CQRS.Serializable (Serializable(..))
import Data.DeriveTH (derive, makeNFData)
import Data.Serialize (Serialize(..), getWord8, putWord8, encode, decode)
import Data.Text (Text)
import qualified Data.Text as T
import Data.Typeable (Typeable)
-- Tasks.
type TaskId = GUID
data TaskStatus = TaskStatusOpen
| TaskStatusComplete
| TaskStatusArchived
deriving (Typeable, Eq, Show)
data Task = Task
{ taskTitle :: Text
, taskStatus :: TaskStatus
} deriving (Typeable, Eq, Show)
newTask :: Text -> Task
newTask title = Task title TaskStatusOpen
-- Serialize instances. In the case of aggregates
-- compatibility is not that important and de-serialization
-- can fail without huge host, i.e. the aggregate has to
-- be reconstructed from events rather than using the
-- snapshot. It *is* important that a format change is
-- detected, though, which is why we're just 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.
$(derive makeNFData ''TaskStatus)
$(derive makeNFData ''Task)
-- Serializable instance.
instance Serializable Task where
serialize = encode
deserialize = either (const Nothing) Just . decode
-- Aggregate instance.
instance Aggregate Task