{-# OPTIONS_GHC -Wno-orphans #-} module KVStore.API.Protobuf (client, server) where import Data.ProtoLens.Labels () import Network.GRPC.Client (rpc) import Network.GRPC.Client qualified as Client import Network.GRPC.Client.StreamType.IO qualified as Client import Network.GRPC.Common import Network.GRPC.Common.Protobuf import Network.GRPC.Server qualified as Server import Network.GRPC.Server.StreamType (Services(..), Methods(..)) import Network.GRPC.Server.StreamType qualified as Server import Network.GRPC.Server.Protobuf qualified as Server import Proto.Kvstore import KVStore.API import KVStore.Util.Profiling {------------------------------------------------------------------------------- API -------------------------------------------------------------------------------} type Create = Protobuf KeyValueService "create" type Delete = Protobuf KeyValueService "delete" type Retrieve = Protobuf KeyValueService "retrieve" type Update = Protobuf KeyValueService "update" {------------------------------------------------------------------------------- Metadata -------------------------------------------------------------------------------} type instance RequestMetadata (Protobuf KeyValueService meth) = NoMetadata type instance ResponseInitialMetadata (Protobuf KeyValueService meth) = NoMetadata type instance ResponseTrailingMetadata (Protobuf KeyValueService meth) = NoMetadata {------------------------------------------------------------------------------- Client -------------------------------------------------------------------------------} client :: Client.Connection -> KVStore client conn = KVStore { create = fmap fromCreateResponse . Client.nonStreaming conn (rpc @Create) . createRequest , retrieve = fmap fromRetrieveResponse . Client.nonStreaming conn (rpc @Retrieve) . retrieveRequest , update = fmap fromUpdateResponse . Client.nonStreaming conn (rpc @Update) . updateRequest , delete = fmap fromDeleteResponse . Client.nonStreaming conn (rpc @Delete) . deleteRequest } {------------------------------------------------------------------------------- Server -------------------------------------------------------------------------------} server :: KVStore -> [Server.SomeRpcHandler IO] server kvstore = Server.fromServices $ Service methods NoMoreServices where methods :: Methods IO (Server.ProtobufMethodsOf KeyValueService) methods = Method (markNonStreaming "create" $ fmap createResponse . create kvstore . fromCreateRequest) $ Method (markNonStreaming "delete" $ fmap deleteResponse . delete kvstore . fromDeleteRequest) $ Method (markNonStreaming "retrieve" $ fmap retrieveResponse . retrieve kvstore . fromRetrieveRequest) $ Method (markNonStreaming "update" $ fmap updateResponse . update kvstore . fromUpdateRequest) $ NoMoreMethods {------------------------------------------------------------------------------- Marshalling -------------------------------------------------------------------------------} createRequest :: (Key, Value) -> Input Create createRequest (Key key, Value value) = defMessage & #key .~ key & #value .~ value fromCreateRequest :: Input Create -> (Key, Value) fromCreateRequest req = ( Key $ req ^. #key , Value $ req ^. #value ) createResponse :: () -> Output Create createResponse _ = defMessage fromCreateResponse :: Output Create -> () fromCreateResponse _ = () retrieveRequest :: Key -> Input Retrieve retrieveRequest (Key key) = defMessage & #key .~ key fromRetrieveRequest :: Input Retrieve -> Key fromRetrieveRequest req = Key $ req ^. #key retrieveResponse :: Value -> Output Retrieve retrieveResponse (Value value) = defMessage & #value .~ value fromRetrieveResponse :: Output Retrieve -> Value fromRetrieveResponse resp = Value $ resp ^. #value updateRequest :: (Key, Value) -> Input Update updateRequest (Key key, Value value) = defMessage & #key .~ key & #value .~ value fromUpdateRequest :: Input Update -> (Key, Value) fromUpdateRequest req = ( Key $ req ^. #key , Value $ req ^. #value ) updateResponse :: () -> Output Update updateResponse _ = defMessage fromUpdateResponse :: Output Update -> () fromUpdateResponse _ = () deleteRequest :: Key -> Input Delete deleteRequest (Key key) = defMessage & #key .~ key fromDeleteRequest :: Input Delete -> Key fromDeleteRequest req = Key $ req ^. #key deleteResponse :: () -> Output Delete deleteResponse _ = defMessage fromDeleteResponse :: Output Delete -> () fromDeleteResponse _ = ()