Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions dev/build-time-preprocessing-issues.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Issues with build time processing

It is possible to make the workflow easier by processing the `.hs` files and
inducing the desired behaviour but the CPP macros are hard to handle.

To handle the CPP macros we need to process the files after the CPP phase is
done. So we need to induce a hook after the CPP processing.

The CPP processing is taken care by the GHC and hence the build tool cannot
handle this. Or atleast cabal cannot.

To this hook needs to be incuced somewhere in the GHC pipeline itself. This is
too much of a hassle. and might not work as expected.

We can possibly stick to the template haskell helpers. The only problem I have
is sometimes I add an rpc function but I forget to export it. We can maybe have
some linter to solve that problem?

## Ignoring the CPP issue

The current implementation pre-preocess the `.hs` files.

There are many pitfalls given this implementation:
1. The changes are not transparent to the user.
2. The modifications are not robust. It fails in many cases.
- Fails with CPP
- Fails with recursive functions
108 changes: 108 additions & 0 deletions dev/design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Design Document

## Basic Design

There are 3 parts to `simple-rpc`.

1. Defination of the RPC function
2. Registering the RPC function in the server
3. Using the RPC function


## Current Implementation

### Defination

We define the RPC version of a function by using the template haskell helper
`rpcExport`.

`rpcExport` creates the corresponding RPC function.

Example,
```
module Action.Users (ensureDirectoryForUser) where

import Streamly.Internal.Unicode.String (str)
import qualified Streamly.Internal.System.Command as Cmd
import Simple.RPC.Server

raw_ensureDirectoryForUser :: String -> FilePath -> IO ()
raw_ensureDirectoryForUser user dir = do
Cmd.toStdout [str|sudo mkdir -p #{dir}|]
Cmd.toStdout [str|sudo chown -R #{user} #{dir}|]
$(rpcExport "raw_ensureDirectoryForUser" "ensureDirectoryForUser")
```

### Registeration

The executable that registers all the RPC functions (aka. the server) should be
of the following form.

```
module Main
( main
) where

import qualified Action.Users as Users
import Simple.RPC.Client

main :: IO ()
main =
mainWith "0.3.0"
[ evaluator Users.ensureDirectoryForUser ]
```

### Usage

```
module LocalLib (func) where

import Data.Function ((&))
import qualified Action.Users as Users

rpcConfig :: RunningConfig
rpcConfig = exec exeOnRemote & onSSH sshConf
where
sshConf = SSHConfig "user@remote-machine.com" 22
exeOnRemote = Executable "/opt/ssh-rpc/orchestrate" "0.3.0"

func :: IO ()
func =
...
call Users.ensureDirectoryForUser rpcConfig "username" "~/.config"
...
```

### Problems with the current implementation

1. During the definations, we have to manually export the RPC versions.
2. During the creation of the server executable we have to make sure all the RPC
functions are exported.

Both the above tasks can be automatic. Or atleast can be verified.

## Design Goal

Make the generation of rpc versions of exported functions more easier.

### Scratch notes on one method of solving the above problem

**User input:**

- `.cabal` file template. Like a `config.in` file. Call it `.cabal.in`
- source code `.hs` files

**User output:**

- `RPC.*` versions of all the corresponding modules
- `.cabal` file that also contains all the RPC modules and an rpc-executable

**Required components:**

- A way to get the type signatures of all the exported functions
- Option 1: Parse the `.hi` files
- Option 2: the `.hs` files

- A way to understand the `.cabal` file
- Parse the `.cabal` file and create the AST
- Modify the AST and create the final `.cabal` file
8 changes: 8 additions & 0 deletions dev/restrictions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Any random function cannot be RPC-fied.
Only non-polymorphic functions whose input params can be serialized can be RPC-fied.

We should make it easier to create an rpc server given the user specifies the
functions that need to be RPC-fied.
This includes:
1. Exporting the required RPC-fied functions automatically
2. Importing the required RPC-fied functions automatically and create a server