curryer-rpc: Fast, Haskell RPC

[ library, program, rpc ] [ Propose Tags ]

Haskell-to-Haskell RPC using Winery serialization.


[Skip to Readme]

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

Versions [RSS] 0.1, 0.2, 0.2.1, 0.2.2, 0.3.0, 0.3.1, 0.3.2, 0.3.3, 0.3.4, 0.3.5
Change log Changelog.markdown
Dependencies async, base (>=4.12 && <4.19), binary, bytestring, containers, curryer-rpc, exceptions, fast-builder, hashable, network, network-byte-order, optparse-generic, stm, stm-containers, streamly (==0.9.0), streamly-bytestring (>=0.2.0), streamly-core (>=0.1.0), time, uuid, winery [details]
License LicenseRef-PublicDomain
Author AgentM
Maintainer agentm@themactionfaction.com
Category RPC
Home page https://github.com/agentm/curryer
Bug tracker https://github.com/agentm/curryer
Source repo head: git clone https://github.com/agentm/curryer
Uploaded by agentm at 2024-01-13T03:47:46Z
Distributions
Reverse Dependencies 1 direct, 0 indirect [details]
Executables SimpleKeyValueClient, SimpleKeyValueServer
Downloads 725 total (45 in the last 30 days)
Rating 2.0 (votes: 1) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs uploaded by user
Build status unknown [no reports yet]

Readme for curryer-rpc-0.3.5

[back to package description]

Curryer - Fast Haskell-to-Haskell RPC

Curryer (pun intended) is a fast, Haskell-exclusive RPC (remote procedure call) library. By using the latest Haskell serialization and streaming libraries, curryer aims to be the fastest and easiest means of communicating between Haskell-based processes.

Curryer is inspired by the now unmaintained distributed-process library, but is lighter-weight and uses a higher-performance serialization package.

Features

  • blocking and non-blocking remote function calls
  • asynchronous server-to-client callbacks (for server-initiated notifications)
  • timeouts
  • leverages winery for high-performance serialization

Requirements

  • GHC 9.0+

Code Example

Server:

data SetKey = SetKey String String
  deriving (Generic, Show)
  deriving Serialise via WineryVariant SetKey

data GetKey = GetKey String
  deriving (Generic, Show)
  deriving Serialise via WineryVariant GetKey

main :: IO ()
main = do
  kvmap <- M.newIO
  void $ serve kvRequestHandlers kvmap localHostAddr 8765 Nothing
  
kvRequestHandlers :: RequestHandlers (M.Map String String)
kvRequestHandlers = [ RequestHandler $ \state (SetKey k v) ->
                        atomically $ M.insert v k (connectionServerState state)
                    , RequestHandler $ \state (GetKey k) ->
                        atomically $ M.lookup k (connectionServerState state)
                    ]

Client:

data SetKey = SetKey String String
  deriving (Generic, Show)
  deriving Serialise via WineryVariant SetKey

data GetKey = GetKey String
  deriving (Generic, Show)
  deriving Serialise via WineryVariant GetKey

data CommandOptions = Get {name :: String}
                    | Set {name :: String, value :: String}
                    deriving (Generic, Show)

instance ParseRecord CommandOptions
                    
main :: IO ()
main = do
  opts <- getRecord "SimpleKeyValueClient"
  conn <- connect [] localHostAddr 8765
  case opts of
    Get k -> do
      eRet <- call conn (GetKey k)
      case eRet of
        Left err -> error (show err)
        Right (Just val) -> putStrLn val
        Right Nothing -> error "no such key"
    Set k v -> do
      eRet <- call conn (SetKey k v)
      case eRet of
        Left err -> error (show err)
        Right () -> pure ()