cqrs 0.2.1 → 0.3.0
raw patch · 6 files changed
+26/−16 lines, 6 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Data.CQRS.Event: applyEvent :: Event e a => e -> a -> a
+ Data.CQRS.Eventable: applyEvent :: Eventable a e => e -> a -> a
+ Data.CQRS.Eventable: class Eventable a e | a -> e
- Data.CQRS.Event: class Event e a | e -> a
+ Data.CQRS.Event: class Event e
- Data.CQRS.Event: decodeEvent :: Event e a => ByteString -> e
+ Data.CQRS.Event: decodeEvent :: Event e => ByteString -> e
- Data.CQRS.Event: encodeEvent :: Event e a => e -> ByteString
+ Data.CQRS.Event: encodeEvent :: Event e => e -> ByteString
- Data.CQRS.Transaction: getAggregateRoot :: (Default a, Event e a, Typeable a, Typeable e, Aggregate a) => GUID a -> TransactionT e IO (AggregateRef a e, a)
+ Data.CQRS.Transaction: getAggregateRoot :: (Default a, Event e, Typeable a, Typeable e, Aggregate a, Eventable a e) => GUID a -> TransactionT e IO (AggregateRef a e, a)
- Data.CQRS.Transaction: publishEvent :: (MonadIO m, Event e a) => AggregateRef a e -> e -> TransactionT e m ()
+ Data.CQRS.Transaction: publishEvent :: (MonadIO m, Event e, Eventable a e) => AggregateRef a e -> e -> TransactionT e m ()
- Data.CQRS.Transaction: retrieveEvents :: Event e a => Int -> Int -> (e -> IO ()) -> TransactionT e IO ()
+ Data.CQRS.Transaction: retrieveEvents :: Event e => Int -> Int -> (e -> IO ()) -> TransactionT e IO ()
- Data.CQRS.Transaction: runTransactionT :: (Typeable a, Typeable e, Event e a, Default a, Aggregate a) => EventStore -> TransactionT e IO c -> IO c
+ Data.CQRS.Transaction: runTransactionT :: (Typeable e, Event e) => EventStore -> TransactionT e IO c -> IO c
Files
- cqrs.cabal +2/−2
- src/Data/CQRS.hs +2/−0
- src/Data/CQRS/Event.hs +2/−4
- src/Data/CQRS/Eventable.hs +9/−0
- src/Data/CQRS/Internal/AggregateRef.hs +2/−2
- src/Data/CQRS/Transaction.hs +9/−8
cqrs.cabal view
@@ -1,5 +1,5 @@ Name: cqrs-Version: 0.2.1+Version: 0.3.0 Synopsis: Command-Query Responsibility Segregation Description: Haskell implementation of the CQRS architectural pattern. An SQLite3-based backend is included.@@ -27,13 +27,13 @@ OverloadedStrings Rank2Types ScopedTypeVariables- TemplateHaskell ghc-options: -Wall hs-source-dirs: src Exposed-modules: Data.CQRS Data.CQRS.Aggregate Data.CQRS.AggregateRef Data.CQRS.Event+ Data.CQRS.Eventable Data.CQRS.EventStore Data.CQRS.EventStore.Sqlite3 Data.CQRS.GUID
src/Data/CQRS.hs view
@@ -4,6 +4,7 @@ ( module Data.CQRS.Aggregate , module Data.CQRS.AggregateRef , module Data.CQRS.Event+ , module Data.CQRS.Eventable , module Data.CQRS.GUID , module Data.CQRS.Transaction ) where@@ -11,5 +12,6 @@ import Data.CQRS.Aggregate import Data.CQRS.AggregateRef import Data.CQRS.Event+import Data.CQRS.Eventable import Data.CQRS.GUID import Data.CQRS.Transaction
src/Data/CQRS/Event.hs view
@@ -6,10 +6,8 @@ import Data.ByteString (ByteString) --- | Event class for applying events to aggregates.-class Event e a | e -> a where- -- | Apply an event to the aggregate and return the updated aggregate.- applyEvent :: e -> a -> a+-- | Event class.+class Event e where -- | Encode event into a strict ByteString. encodeEvent :: e -> ByteString -- | Decode event from a strict ByteString. To avoid corrupt
+ src/Data/CQRS/Eventable.hs view
@@ -0,0 +1,9 @@+-- | Eventable type class.+module Data.CQRS.Eventable+ ( Eventable(..)+ ) where++-- | Type class for applying events to aggregates.+class Eventable a e | a -> e where+ -- | Apply an event to the aggregate and return the updated aggregate.+ applyEvent :: e -> a -> a
src/Data/CQRS/Internal/AggregateRef.hs view
@@ -13,7 +13,7 @@ import Control.Monad (liftM) import Control.Monad.IO.Class (MonadIO, liftIO) import Data.CQRS.GUID (GUID)-import Data.CQRS.Event (Event(..))+import Data.CQRS.Eventable (Eventable(..)) import Data.IORef (IORef, modifyIORef, newIORef, readIORef) import Data.Typeable (Typeable) @@ -35,7 +35,7 @@ return $ AggregateRef a' e' guid originatingVersion snapshotVersion -- | Publish event to aggregate.-publishEvent :: (MonadIO m, Event e a) => AggregateRef a e -> e -> m ()+publishEvent :: (MonadIO m, Eventable a e) => AggregateRef a e -> e -> m () publishEvent aggregateRef event = liftIO $ do -- Apply event to aggregate state. modifyIORef (arValue aggregateRef) $ applyEvent event
src/Data/CQRS/Transaction.hs view
@@ -15,6 +15,7 @@ import Data.CQRS.Internal.AggregateRef (AggregateRef, mkAggregateRef) import qualified Data.CQRS.Internal.AggregateRef as AR import Data.CQRS.Event (Event(..))+import Data.CQRS.Eventable (Eventable(..)) import Data.CQRS.EventStore (EventStore, withTransaction) import qualified Data.CQRS.EventStore as ES import Data.CQRS.GUID (GUID)@@ -31,7 +32,7 @@ -- Existential wrapper for AggregateRef. data BoxedAggregateRef e =- forall a . (Typeable a, Typeable e, Event e a, Default a, Aggregate a) => BoxedAggregateRef (AggregateRef a e)+ forall a . (Typeable a, Typeable e, Event e, Default a, Aggregate a, Eventable a e) => BoxedAggregateRef (AggregateRef a e) -- | Transaction monad itself. type Transaction e = StateT (TransactionState e)@@ -42,7 +43,7 @@ } -- | Run transaction against an event store.-runTransactionT :: (Typeable a, Typeable e, Event e a, Default a, Aggregate a) => EventStore -> TransactionT e IO c -> IO c+runTransactionT :: (Typeable e, Event e) => EventStore -> TransactionT e IO c -> IO c runTransactionT eventStore_ (TransactionT transaction) = do withTransaction eventStore_ $ do -- Run the computation.@@ -63,7 +64,7 @@ where s0 = TransactionState eventStore_ [ ] -- | Get an aggregate ref by GUID.-getById :: forall a e . (Typeable a, Typeable e, Event e a, Default a, Aggregate a) => GUID a -> TransactionT e IO (AggregateRef a e)+getById :: forall a e . (Typeable a, Typeable e, Event e, Default a, Aggregate a, Eventable a e) => GUID a -> TransactionT e IO (AggregateRef a e) getById guid = TransactionT $ do -- Check through list to see if we've given out a reference to the aggregate before. aggregateRefs <- fmap aggregateRefsToCommit get@@ -83,7 +84,7 @@ -- Get the latest snapshot from database, filling in a default -- if a) no snapshot exists, or b) snapshot state was not decodable.-getLatestSnapshot :: forall a e . (Typeable a, Typeable e, Event e a, Default a, Aggregate a) => GUID a -> Transaction e IO (Int,a)+getLatestSnapshot :: forall a e . (Typeable a, Typeable e, Event e, Default a, Aggregate a) => GUID a -> Transaction e IO (Int,a) getLatestSnapshot guid = do es <- fmap eventStore get r <- liftIO $ ES.getLatestSnapshot es guid@@ -96,7 +97,7 @@ return (0, def) -- Retrieve aggregate from event store.-getByIdFromEventStore :: forall a e . (Typeable a, Typeable e, Event e a, Default a, Aggregate a) => GUID a -> Transaction e IO (AggregateRef a e)+getByIdFromEventStore :: forall a e . (Typeable a, Typeable e, Event e, Default a, Aggregate a, Eventable a e) => GUID a -> Transaction e IO (AggregateRef a e) getByIdFromEventStore guid = do es <- fmap eventStore get -- Get latest snapshot (if any).@@ -113,7 +114,7 @@ return a' -- | Publish event for an aggregate root.-publishEvent :: (MonadIO m, Event e a) => AggregateRef a e -> e -> TransactionT e m ()+publishEvent :: (MonadIO m, Event e, Eventable a e) => AggregateRef a e -> e -> TransactionT e m () publishEvent aggregateRef event = lift $ AR.publishEvent aggregateRef event -- | Retrieve a range of events, invoking a callback function for each event.@@ -128,7 +129,7 @@ -- and "logical time" 30 (not inclusive). "Logical time" starts -- at 1. It is NOT an error to provide bounds for which there -- are no events.-retrieveEvents :: forall e a . (Event e a) => Int -> Int -> (e -> IO ()) -> TransactionT e IO ()+retrieveEvents :: forall e . (Event e) => Int -> Int -> (e -> IO ()) -> TransactionT e IO () retrieveEvents minVersion maxVersion h = TransactionT $ do es <- fmap eventStore get lift $ ES.readAllEvents es minVersion maxVersion $ \ed -> do@@ -136,7 +137,7 @@ liftIO $ h e -- | Get aggregate root.-getAggregateRoot :: (Default a, Event e a, Typeable a, Typeable e, Aggregate a) => GUID a -> TransactionT e IO (AggregateRef a e, a)+getAggregateRoot :: (Default a, Event e, Typeable a, Typeable e, Aggregate a, Eventable a e) => GUID a -> TransactionT e IO (AggregateRef a e, a) getAggregateRoot guid = do aggregateRef <- getById guid aggregate <- lift $ AR.readValue aggregateRef