packages feed

eventstore-0.1.0.0: Database/EventStore/Internal/Operation/Common.hs

--------------------------------------------------------------------------------
-- |
-- Module : Database.EventStore.Internal.Operation.Common
-- Copyright : (C) 2014 Yorick Laupa
-- License : (see the file LICENSE)
--
-- Maintainer : Yorick Laupa <yo.eight@gmail.com>
-- Stability : provisional
-- Portability : non-portable
--
--------------------------------------------------------------------------------
module Database.EventStore.Internal.Operation.Common
    ( OperationParams(..)
    , createOperation
    -- * Re-exports
    , module Data.ProtocolBuffers
    ) where

--------------------------------------------------------------------------------
import Data.ProtocolBuffers
import Data.Serialize
import Data.UUID

--------------------------------------------------------------------------------
import Database.EventStore.Internal.Types

--------------------------------------------------------------------------------
data OperationParams request response
    = OperationParams
      { opSettings    :: !Settings
      , opRequestCmd  :: !Command
      , opResponseCmd :: !Command

      , opRequest     :: IO request
      , opSuccess     :: response -> IO Decision
      , opFailure     :: OperationException -> IO Decision
      }

--------------------------------------------------------------------------------
createOperation :: (Encode a, Decode b) => OperationParams a b -> Operation
createOperation params =
    Operation
    { operationCreatePackage = createPackage params
    , operationInspect       = inspection params
    }

--------------------------------------------------------------------------------
createPackage :: Encode a => OperationParams a b -> UUID -> IO Package
createPackage params uuid = do
    req <- opRequest params

    let pack = Package
               { packageCmd         = opRequestCmd params
               , packageCorrelation = uuid
               , packageFlag        = None
               , packageData        = runPut $ encodeMessage req
               }

    return pack

--------------------------------------------------------------------------------
inspection :: Decode b => OperationParams a b -> Package -> IO Decision
inspection params pack
    | found == exp_v = deeperInspection params pack
    | otherwise      = failed (InvalidServerResponse exp_v found)
  where
    exp_v  = opResponseCmd params
    failed = opFailure params
    found  = packageCmd pack

--------------------------------------------------------------------------------
deeperInspection :: Decode b => OperationParams a b -> Package -> IO Decision
deeperInspection params pack =
    case runGet decodeMessage bytes of
        Left e    -> failed (ProtobufDecodingError e)
        Right msg -> succeed msg
  where
    failed  = opFailure params
    succeed = opSuccess params
    bytes   = packageData pack