-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Batteries included event sourcing and CQRS -- -- Please see the README on GitHub at -- https://github.com/tommyengstrom/domaindriven/tree/master/domaindriven-core#readme @package domaindriven-core @version 0.5.0 module DomainDriven.Persistance.Class class ReadModel p where { type Model p :: Type; type Event p :: Type; } applyEvent :: ReadModel p => p -> Model p -> Stored (Event p) -> Model p getModel :: ReadModel p => p -> IO (Model p) getEventList :: ReadModel p => p -> IO [Stored (Event p)] getEventStream :: ReadModel p => p -> SerialT IO (Stored (Event p)) class ReadModel p => WriteModel p transactionalUpdate :: forall m a. (WriteModel p, MonadUnliftIO m) => p -> (Model p -> m (Model p -> a, [Event p])) -> m a -- | Wrapper for stored data This ensures all events have a unique ID and a -- timestamp, without having to deal with that when implementing the -- model. data Stored a Stored :: a -> UTCTime -> UUID -> Stored a [$sel:storedEvent:Stored] :: Stored a -> a [$sel:storedTimestamp:Stored] :: Stored a -> UTCTime [$sel:storedUUID:Stored] :: Stored a -> UUID mkId :: MonadIO m => m UUID toStored :: MonadIO m => e -> m (Stored e) instance Control.DeepSeq.NFData a => Control.DeepSeq.NFData (DomainDriven.Persistance.Class.Stored a) instance Data.Traversable.Traversable DomainDriven.Persistance.Class.Stored instance Data.Foldable.Foldable DomainDriven.Persistance.Class.Stored instance GHC.Base.Functor DomainDriven.Persistance.Class.Stored instance Data.Aeson.Types.ToJSON.ToJSON a => Data.Aeson.Types.ToJSON.ToJSON (DomainDriven.Persistance.Class.Stored a) instance Data.Aeson.Types.FromJSON.FromJSON a => Data.Aeson.Types.FromJSON.FromJSON (DomainDriven.Persistance.Class.Stored a) instance GHC.Generics.Generic (DomainDriven.Persistance.Class.Stored a) instance GHC.Classes.Ord a => GHC.Classes.Ord (DomainDriven.Persistance.Class.Stored a) instance GHC.Classes.Eq a => GHC.Classes.Eq (DomainDriven.Persistance.Class.Stored a) instance GHC.Show.Show a => GHC.Show.Show (DomainDriven.Persistance.Class.Stored a) module DomainDriven.Persistance.ForgetfulInMemory createForgetful :: MonadIO m => (model -> Stored event -> model) -> model -> m (ForgetfulInMemory model event) -- | STM state without event persistance data ForgetfulInMemory model event ForgetfulInMemory :: IORef model -> (model -> Stored event -> model) -> model -> IORef [Stored event] -> QSem -> ForgetfulInMemory model event [$sel:stateRef:ForgetfulInMemory] :: ForgetfulInMemory model event -> IORef model [$sel:apply:ForgetfulInMemory] :: ForgetfulInMemory model event -> model -> Stored event -> model [$sel:seed:ForgetfulInMemory] :: ForgetfulInMemory model event -> model [$sel:events:ForgetfulInMemory] :: ForgetfulInMemory model event -> IORef [Stored event] [$sel:lock:ForgetfulInMemory] :: ForgetfulInMemory model event -> QSem instance GHC.Generics.Generic (DomainDriven.Persistance.ForgetfulInMemory.ForgetfulInMemory model event) instance DomainDriven.Persistance.Class.ReadModel (DomainDriven.Persistance.ForgetfulInMemory.ForgetfulInMemory model e) instance DomainDriven.Persistance.Class.WriteModel (DomainDriven.Persistance.ForgetfulInMemory.ForgetfulInMemory model e) module DomainDriven.Persistance.Postgres.Types data PersistanceError EncodingError :: String -> PersistanceError ValueError :: String -> PersistanceError type EventTableBaseName = String type EventVersion = Int type EventTableName = String type PreviousEventTableName = String type ChunkSize = Int type EventMigration = PreviousEventTableName -> EventTableName -> Connection -> IO () data EventTable MigrateUsing :: EventMigration -> EventTable -> EventTable InitialVersion :: EventTableBaseName -> EventTable newtype EventNumber EventNumber :: Int64 -> EventNumber [$sel:unEventNumber:EventNumber] :: EventNumber -> Int64 data NumberedModel m NumberedModel :: !m -> !EventNumber -> NumberedModel m [$sel:model:NumberedModel] :: NumberedModel m -> !m [$sel:eventNumber:NumberedModel] :: NumberedModel m -> !EventNumber data NumberedEvent e NumberedEvent :: !Stored e -> !EventNumber -> NumberedEvent e [$sel:event:NumberedEvent] :: NumberedEvent e -> !Stored e [$sel:eventNumber:NumberedEvent] :: NumberedEvent e -> !EventNumber data OngoingTransaction OngoingTransaction :: Connection -> LocalPool Connection -> OngoingTransaction [$sel:connection:OngoingTransaction] :: OngoingTransaction -> Connection [$sel:localPool:OngoingTransaction] :: OngoingTransaction -> LocalPool Connection data EventRowOut EventRowOut :: UUID -> EventNumber -> UTCTime -> Value -> EventRowOut [$sel:key:EventRowOut] :: EventRowOut -> UUID [$sel:commitNumber:EventRowOut] :: EventRowOut -> EventNumber [$sel:timestamp:EventRowOut] :: EventRowOut -> UTCTime [$sel:event:EventRowOut] :: EventRowOut -> Value fromEventRow :: (FromJSON e, MonadThrow m) => EventRowOut -> m (Stored e, EventNumber) instance GHC.Exception.Type.Exception DomainDriven.Persistance.Postgres.Types.PersistanceError instance GHC.Classes.Eq DomainDriven.Persistance.Postgres.Types.PersistanceError instance GHC.Show.Show DomainDriven.Persistance.Postgres.Types.PersistanceError instance GHC.Num.Num DomainDriven.Persistance.Postgres.Types.EventNumber instance GHC.Classes.Ord DomainDriven.Persistance.Postgres.Types.EventNumber instance GHC.Classes.Eq DomainDriven.Persistance.Postgres.Types.EventNumber instance GHC.Generics.Generic DomainDriven.Persistance.Postgres.Types.EventNumber instance GHC.Show.Show DomainDriven.Persistance.Postgres.Types.EventNumber instance GHC.Generics.Generic (DomainDriven.Persistance.Postgres.Types.NumberedModel m) instance GHC.Show.Show m => GHC.Show.Show (DomainDriven.Persistance.Postgres.Types.NumberedModel m) instance GHC.Generics.Generic (DomainDriven.Persistance.Postgres.Types.NumberedEvent e) instance GHC.Show.Show e => GHC.Show.Show (DomainDriven.Persistance.Postgres.Types.NumberedEvent e) instance GHC.Generics.Generic DomainDriven.Persistance.Postgres.Types.OngoingTransaction instance Database.PostgreSQL.Simple.FromRow.FromRow DomainDriven.Persistance.Postgres.Types.EventRowOut instance GHC.Generics.Generic DomainDriven.Persistance.Postgres.Types.EventRowOut instance GHC.Classes.Eq DomainDriven.Persistance.Postgres.Types.EventRowOut instance GHC.Show.Show DomainDriven.Persistance.Postgres.Types.EventRowOut instance Database.PostgreSQL.Simple.FromField.FromField DomainDriven.Persistance.Postgres.Types.EventNumber -- | Postgres events with state as an IORef module DomainDriven.Persistance.Postgres.Internal data PostgresEvent model event PostgresEvent :: Pool Connection -> EventTableName -> IORef (NumberedModel model) -> (model -> Stored event -> model) -> model -> ChunkSize -> PostgresEvent model event [$sel:connectionPool:PostgresEvent] :: PostgresEvent model event -> Pool Connection [$sel:eventTableName:PostgresEvent] :: PostgresEvent model event -> EventTableName [$sel:modelIORef:PostgresEvent] :: PostgresEvent model event -> IORef (NumberedModel model) [$sel:app:PostgresEvent] :: PostgresEvent model event -> model -> Stored event -> model [$sel:seed:PostgresEvent] :: PostgresEvent model event -> model -- | Number of events read from postgres per batch [$sel:chunkSize:PostgresEvent] :: PostgresEvent model event -> ChunkSize data PostgresEventTrans model event PostgresEventTrans :: OngoingTransaction -> EventTableName -> IORef (NumberedModel model) -> (model -> Stored event -> model) -> model -> ChunkSize -> PostgresEventTrans model event [$sel:transaction:PostgresEventTrans] :: PostgresEventTrans model event -> OngoingTransaction [$sel:eventTableName:PostgresEventTrans] :: PostgresEventTrans model event -> EventTableName [$sel:modelIORef:PostgresEventTrans] :: PostgresEventTrans model event -> IORef (NumberedModel model) [$sel:app:PostgresEventTrans] :: PostgresEventTrans model event -> model -> Stored event -> model [$sel:seed:PostgresEventTrans] :: PostgresEventTrans model event -> model -- | Number of events read from postgres per batch [$sel:chunkSize:PostgresEventTrans] :: PostgresEventTrans model event -> ChunkSize getEventTableName :: EventTable -> EventTableName -- | Create the table required for storing state and events, if they do not -- yet exist. createEventTable :: (FromJSON e, WriteModel (PostgresEventTrans m e)) => PostgresEventTrans m e -> IO () createEventTable' :: Connection -> EventTableName -> IO Int64 retireTable :: Connection -> EventTableName -> IO () createRetireFunction :: Connection -> IO () simplePool' :: MonadUnliftIO m => ConnectInfo -> m (Pool Connection) simplePool :: MonadUnliftIO m => IO Connection -> m (Pool Connection) -- | Setup the persistance model and verify that the tables exist. postgresWriteModelNoMigration :: (FromJSON e, WriteModel (PostgresEventTrans m e)) => Pool Connection -> EventTableName -> (m -> Stored e -> m) -> m -> IO (PostgresEvent m e) -- | Setup the persistance model and verify that the tables exist. postgresWriteModel :: Pool Connection -> EventTable -> (m -> Stored e -> m) -> m -> IO (PostgresEvent m e) newtype Exists Exists :: Bool -> Exists [$sel:exists:Exists] :: Exists -> Bool runMigrations :: OngoingTransaction -> EventTable -> IO () createPostgresPersistance :: forall event model. Pool Connection -> EventTableName -> (model -> Stored event -> model) -> model -> IO (PostgresEvent model event) queryEvents :: FromJSON a => Connection -> EventTableName -> IO [(Stored a, EventNumber)] queryEventsAfter :: FromJSON a => Connection -> EventTableName -> EventNumber -> IO [(Stored a, EventNumber)] newtype EventQuery EventQuery :: Query -> EventQuery [$sel:getPgQuery:EventQuery] :: EventQuery -> Query mkEventsAfterQuery :: EventTableName -> EventNumber -> EventQuery mkEventQuery :: EventTableName -> EventQuery headMay :: [a] -> Maybe a queryHasEventsAfter :: Connection -> EventTableName -> EventNumber -> IO Bool writeEvents :: forall a. ToJSON a => Connection -> EventTableName -> [Stored a] -> IO EventNumber getEventStream' :: FromJSON event => PostgresEventTrans model event -> SerialT IO (Stored event) -- | A transaction that is always rolled back at the end. This is useful -- when using cursors as they can only be used inside a transaction. withStreamReadTransaction :: forall t m a model event. (IsStream t, MonadAsync m, MonadCatch m) => PostgresEvent model event -> (PostgresEventTrans model event -> t m a) -> t m a withIOTrans :: forall a model event. PostgresEvent model event -> (PostgresEventTrans model event -> IO a) -> IO a mkEventStream :: FromJSON event => ChunkSize -> Connection -> EventQuery -> SerialT IO (Stored event, EventNumber) getModel' :: forall e m. FromJSON e => PostgresEventTrans m e -> IO m refreshModel :: forall m e. FromJSON e => PostgresEventTrans m e -> IO (m, EventNumber) exclusiveLock :: OngoingTransaction -> EventTableName -> IO () instance GHC.Generics.Generic (DomainDriven.Persistance.Postgres.Internal.PostgresEvent model event) instance GHC.Generics.Generic (DomainDriven.Persistance.Postgres.Internal.PostgresEventTrans model event) instance Database.PostgreSQL.Simple.FromRow.FromRow DomainDriven.Persistance.Postgres.Internal.Exists instance GHC.Generics.Generic DomainDriven.Persistance.Postgres.Internal.Exists instance GHC.Classes.Eq DomainDriven.Persistance.Postgres.Internal.Exists instance GHC.Show.Show DomainDriven.Persistance.Postgres.Internal.Exists instance GHC.Generics.Generic DomainDriven.Persistance.Postgres.Internal.EventQuery instance GHC.Show.Show DomainDriven.Persistance.Postgres.Internal.EventQuery instance Data.Aeson.Types.FromJSON.FromJSON e => DomainDriven.Persistance.Class.ReadModel (DomainDriven.Persistance.Postgres.Internal.PostgresEvent m e) instance (Data.Aeson.Types.ToJSON.ToJSON e, Data.Aeson.Types.FromJSON.FromJSON e) => DomainDriven.Persistance.Class.WriteModel (DomainDriven.Persistance.Postgres.Internal.PostgresEvent m e) module DomainDriven.Persistance.Postgres.Migration migrateValue1to1 :: Connection -> PreviousEventTableName -> EventTableName -> (Value -> Value) -> IO () migrate1to1 :: forall a b. (FromJSON a, ToJSON b) => Connection -> PreviousEventTableName -> EventTableName -> (Stored a -> Stored b) -> IO () migrate1toMany :: forall a b. (FromJSON a, ToJSON b) => Connection -> PreviousEventTableName -> EventTableName -> (Stored a -> [Stored b]) -> IO () migrate1toManyWithState :: forall a b state. (FromJSON a, ToJSON b) => Connection -> PreviousEventTableName -> EventTableName -> (state -> Stored a -> (state, [Stored b])) -> state -> IO () module DomainDriven.Persistance.Postgres data EventTable MigrateUsing :: EventMigration -> EventTable -> EventTable InitialVersion :: EventTableBaseName -> EventTable type EventMigration = PreviousEventTableName -> EventTableName -> Connection -> IO () type ChunkSize = Int type PreviousEventTableName = String type EventTableName = String type EventTableBaseName = String data PostgresEvent model event PostgresEvent :: Pool Connection -> EventTableName -> IORef (NumberedModel model) -> (model -> Stored event -> model) -> model -> ChunkSize -> PostgresEvent model event [$sel:connectionPool:PostgresEvent] :: PostgresEvent model event -> Pool Connection [$sel:eventTableName:PostgresEvent] :: PostgresEvent model event -> EventTableName [$sel:modelIORef:PostgresEvent] :: PostgresEvent model event -> IORef (NumberedModel model) [$sel:app:PostgresEvent] :: PostgresEvent model event -> model -> Stored event -> model [$sel:seed:PostgresEvent] :: PostgresEvent model event -> model -- | Number of events read from postgres per batch [$sel:chunkSize:PostgresEvent] :: PostgresEvent model event -> ChunkSize simplePool' :: MonadUnliftIO m => ConnectInfo -> m (Pool Connection) simplePool :: MonadUnliftIO m => IO Connection -> m (Pool Connection) -- | Setup the persistance model and verify that the tables exist. postgresWriteModelNoMigration :: (FromJSON e, WriteModel (PostgresEventTrans m e)) => Pool Connection -> EventTableName -> (m -> Stored e -> m) -> m -> IO (PostgresEvent m e) -- | Setup the persistance model and verify that the tables exist. postgresWriteModel :: Pool Connection -> EventTable -> (m -> Stored e -> m) -> m -> IO (PostgresEvent m e)