Fast Haskell RPC
Go to file
2021-01-11 23:53:17 -05:00
bench rename MessageHandlers to RequestHandlers 2020-12-18 21:19:36 -05:00
examples add example to README 2020-12-18 21:20:00 -05:00
src/Network/RPC/Curryer enable 2x+ performance improvement for 10 MB+ messages by removing intermediate byte list in envelope parser 2021-01-11 23:53:17 -05:00
test use more specific type for server->client sendMessage 2020-12-25 21:36:37 -05:00
.gitignore first pass at basic message-passing interface 2020-09-11 10:42:22 -04:00
bench.sh setup criterion benchmarking 2020-10-18 13:41:29 -04:00
cabal.project enable 2x+ performance improvement for 10 MB+ messages by removing intermediate byte list in envelope parser 2021-01-11 23:53:17 -05:00
Changelog.markdown update GHC requirements 2020-12-27 21:04:51 -05:00
curryer-rpc.cabal comment out -fprof-auto flag to squelch hackage warning 2020-12-27 22:01:01 -05:00
LICENSE add README and LICENSE 2020-10-04 13:56:43 -04:00
README.markdown update GHC requirements 2020-12-27 21:04:51 -05:00

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 8.6+

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 ()