gRPC-haskell/core/src/Network/GRPC/LowLevel/GRPC.hs

78 lines
2.7 KiB
Haskell

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE StandaloneDeriving #-}
module Network.GRPC.LowLevel.GRPC(
GRPC
, withGRPC
, GRPCIOError(..)
, throwIfCallError
, grpcDebug
, grpcDebug'
, threadDelaySecs
, MetadataMap(..)
, C.StatusDetails(..)
) where
import Control.Concurrent (threadDelay, myThreadId)
import Control.Exception
import Data.Typeable
import Network.GRPC.LowLevel.GRPC.MetadataMap (MetadataMap(..))
import qualified Network.GRPC.Unsafe as C
import qualified Network.GRPC.Unsafe.Op as C
-- | Functions as a proof that the gRPC core has been started. The gRPC core
-- must be initialized to create any gRPC state, so this is a requirement for
-- the server and client create/start functions.
data GRPC = GRPC
withGRPC :: (GRPC -> IO a) -> IO a
withGRPC = bracket (C.grpcInit >> return GRPC)
(\_ -> grpcDebug "withGRPC: shutting down" >> C.grpcShutdown)
-- | Describes all errors that can occur while running a GRPC-related IO
-- action.
data GRPCIOError = GRPCIOCallError C.CallError
-- ^ Errors that can occur while the call is in flight. These
-- errors come from the core gRPC library directly.
| GRPCIOTimeout
-- ^ Indicates that we timed out while waiting for an
-- operation to complete on the 'CompletionQueue'.
| GRPCIOShutdown
-- ^ Indicates that the 'CompletionQueue' is shutting down
-- and no more work can be processed. This can happen if the
-- client or server is shutting down.
| GRPCIOShutdownFailure
-- ^ Thrown if a 'CompletionQueue' fails to shut down in a
-- reasonable amount of time.
| GRPCIOUnknownError
| GRPCIOBadStatusCode C.StatusCode C.StatusDetails
| GRPCIODecodeError String
| GRPCIOInternalUnexpectedRecv String -- debugging description
| GRPCIOHandlerException String
deriving (Eq, Show, Typeable)
instance Exception GRPCIOError
throwIfCallError :: C.CallError -> Either GRPCIOError ()
throwIfCallError C.CallOk = Right ()
throwIfCallError x = Left $ GRPCIOCallError x
grpcDebug :: String -> IO ()
{-# INLINE grpcDebug #-}
#ifdef DEBUG
grpcDebug = grpcDebug'
#else
grpcDebug _ = return ()
#endif
grpcDebug' :: String -> IO ()
{-# INLINE grpcDebug' #-}
grpcDebug' str = do
tid <- myThreadId
putStrLn $ "[" ++ show tid ++ "]: " ++ str
threadDelaySecs :: Int -> IO ()
threadDelaySecs = threadDelay . (* 10^(6::Int))