packages feed

websockets-rpc-0.7.0: README.md

websockets-rpc
===============

A simple message-based streaming RPC mechanism built using WebSockets

## Usage

The idea is pretty simple:

- A client initiates the RPC call to a server with a `Subscription`
- the client may send additional data at any time with `Supply`, who can also cancel the RPC call
- the server may respond incrementally with `Reply`
- the server finishes the RPC call with a `Complete`

```
client                                                         server
    ------------------------subscribe--------------------------->
    - - - - - - - - - - - - -supply - - - - - - - - - - - - - - >
    < - - - - - - - - - - - -reply- - - - - - - - - - - - - - - -
    <-----------------------complete-----------------------------
```

if the `supply` and `reply` parts were ommitted, it would be identical to a traditional RPC mechanism.


### Example

```haskell
import Network.WebSockets.RPC
import Data.Aeson

-- subscriptions from client to server
data MySubDSL = Foo
  deriving (FromJSON, ToJSON) -- you should figure this part out :)

-- supplies from client to server
data MySupDSL = Bar
  deriving (FromJSON, ToJSON)

-- replies from server to client
data MyRepDSL = Baz
  deriving (FromJSON, ToJSON)

-- onCompletes from server to client
data MyComDSL = Qux
  deriving (FromJSON, ToJSON)
```


Server:

```haskell
{-# LANGUAGE NamedFieldPuns, ScopedTypeVariables #-}


myServer :: (MonadIO m, MonadThrow m) => ServerAppT (WebSocketServerRPCT MySubDSL MySupDSL m)
myServer = rpcServer $ \RPCServerParams{reply,complete} eSubSup -> case eSubSup of
  Left Foo -> do
    forM_ [1..5] $ \_ -> do
      liftIO $ threadDelay 1000000
      reply Baz
    complete Qux
  Right Bar -> reply Baz
```

Client:

```haskell
{-# LANGUAGE NamedFieldPuns #-}


myClient :: (MonadIO m, MonadThrow m) => ClientAppT (WebSocketClientRPCT MyRepDSL MyComDSL m) ()
myClient = rpcClient $ \dispatch ->
  -- only going to make one RPC call for this example
  dispatch RPCClient
    { subscription = Foo
    , onReply = \RPCClientParams{supply,cancel} Baz -> do
        liftIO $ threadDelay 1000000
        supply Bar
        (q :: Bool) <- liftIO getRandom
        if q then cancel else pure ()
    , onComplete = \Qux -> liftIO $ putStrLn "finished"
    }
```

> the `threadDelay` calls are just to exemplify the asynchronisity of the system, nothing to do with avoiding race conditions >.>


To turn the `ServerAppT` and `ClientAppT` into natural [WebSockets](https://hackage.haskell.org/package/websockets)
types, use the morphisms from [Wai-Transformers](https://hackage.haskell.org/package/wai-trasformers).


## Contributing

this is my swamp