-- | Event store backend. You only need to import this
-- module if you're planning on implementing a custom
-- event store backend.
module Data.CQRS.EventStore.Backend
       ( EventStoreBackend(..)
       , RawEvent
       , RawSnapshot(..)
       ) where

import Data.ByteString (ByteString)
import Data.Conduit (Source)
import Data.CQRS.GUID
import Data.CQRS.PersistedEvent (PersistedEvent)

-- | Raw event type. The data associated with an event is not
-- translated in any way.
type RawEvent = PersistedEvent ByteString

-- | Raw snapshot.
data RawSnapshot =
  RawSnapshot { rsVersion :: Int
              , rsSnapshotData :: ByteString
              }

-- | Event stores are the backend used for reading and storing all the
-- information about recorded events.
data EventStoreBackend =
  EventStoreBackend {
    -- | Store a sequence of events for aggregate identified by GUID
    -- into the event store, starting at the provided version number.
    -- If the version number does not match the expected value, a
    -- failure occurs.
    esbStoreEvents :: GUID -> Int -> [RawEvent] -> IO (),
    -- | Retrieve the sequence of events associated with the aggregate
    -- identified by the given GUID. Only events at or after the given
    -- version number are retrieved. The events are returned in
    -- increasing order of version number.
    esbRetrieveEvents :: GUID -> Int -> Source IO RawEvent,
    -- | Enumerate all events later than given logical timestamp.
    esbEnumerateAllEvents :: Int -> Source IO RawEvent,
    -- | Write snapshot for aggregate identified by GUID and
    -- the given version number. The version number is NOT checked
    -- for validity. If the event store does not support snapshots
    -- this function may do nothing.
    esbWriteSnapshot :: GUID -> RawSnapshot -> IO (),
    -- | Get latest snapshot of an aggregate identified by GUID.
    -- Returns the version number of the snapshot in addition to the
    -- data. An event store which does not support snapshots is
    -- permitted to return 'Nothing' in all cases.
    esbGetLatestSnapshot :: GUID -> IO (Maybe RawSnapshot),
    -- | Get the latest version global number.
    esbGetLatestVersion :: IO Int,
    -- | Run transaction against the event store. The transaction is
    -- expected to commit if the supplied IO action runs to completion
    -- (i.e. doesn't throw an exception) and to rollback otherwise.
    esbWithTransaction :: forall a . IO a -> IO a,
    -- | Close the event store.
    esbCloseEventStoreBackend :: IO ()
    }