[Haskell-beginners] RPC library / generic application level protocol

Emanuel Koczwara poczta at emanuelkoczwara.pl
Sun Mar 16 17:32:36 UTC 2014


Hi,

I have an application in c++/qt (https://gitorious.org/micropos). Direct
connection with PostgreSQL is a big security hole, so I'm trying to
redesign my architecture. I want to add an application server between
PostgreSQL and client/admin and I want to write that application in
Haskell.

The core concept of my new architecture is a custom protocol. With that,
it would be possible with little effort to create web and mobile
clients, possibly using different technologies.

Totally custom protocol would be interesting, but writing a parser for c
++ _and_ python _and_ java (and haskell of course) will be too much for
me at the moment. XML-RPC looks too heavy, so I ended up with JSON-RPC
('id' attribute is ommited):

* authentication example:

| > { method: "auth-login", params: { name: <name>, passwd: <passwd> } }
| < { result: <status-object> }

| > { method: "auth-logout", params: null }
| < { result: <status-object> }

* uploading/downloading binary data/files example:

| > { method: "fs-upload", params: <binary-data> }
|  { result: <status-object> }

| > { method: "fs-download", params: <binary-data-id> }
| < { result: <status-object> }

* low level generic database methods:

| > { method: "db-create", params: { type: <type>, object: <object> } }
| < { result: <status-object> }

| > { method: "db-update", params: { type: <type>, object: <object> } }
| < { result: <status-object> }

| > { method: "db-delete", params: { type: <type>, id: <id> } }
| < { result: <status-object> }

| > { method: "db-list", params:
|     { type: <type>,
|       filter-by: [ <predicate-objects> ],
|       order-by: [ <ordering-objects> ] } }
| < { result: [ <ids> ] }

| > { method: "db-show", params: 
|     { type: <type>, 
|       ids: [ <ids> ], 
|       fields: [ <fields-options-objects> ] } }
| < { result: [ <objects> ] }

| > { method: "db-list-show", params: 
|     { type: <type>, 
|       filter-by: [ <predicate-objects> ], 
|       order-by: [ <ordering-objects> ],
|       fields: [ <fields-options-objects> ] } }
| < { result: [ <objects> ] }

* low level generic relations:

| > { method: "db-insert", params: 
|     { group-type: <type>, 
|       group-id: <id>, 
|       member-type: <type>, 
|       members: [ <ids> ] } }
| < { result: <status-object> }

| > { method: "db-remove", params: 
|     { group-type: <type>, 
|       group-id: <id>, 
|       member-type: <type>, 
|       members: [ <ids> ] } }
| < { result: <status-object> }

Example usage (this should add a record in 'client' table):

| > { method: "db-create", params: 
|     { type: client,
|       object:{ name:"John Doe", address: "...", ... } } }
| < { result: <status-object> }

This 'parsing engine' should be generated from some kind of 'routes
description' like in django, rails or yesod. For example something like
this:

| auth-login (user-name :: String) (user-password :: String)
| auth-logout

| auth-lock
| auth-unlock (user-name :: String) (user-code :: String)

| fs-upload (binary-data :: BinaryData)
| fs-download (binary-data-id :: BinaryDataId)

| db-create (type :: String) (object :: a)
| db-update (type :: String) (object :: a)
| db-delete (type :: String) (id :: String)

The user should supply all data definitions and conversion functions to
guarantee type corectness in case of a match, for example:

class FromJson a where
  fromJson :: String -> Maybe a

data Client = Client { name :: String, address :: String,  ... }

instance FromJason Client where
  fromJson = ...

This looks very generic. Am I reinventing the wheel? Which package
should I use for this task? msgpack-rpc looks interesting. Other
packages have very low download rate. Or maybe there is some kind of
generic appliaction server (but I'm looking for tcp/ip level, no http)?

Any hints are very welcome.

Thanks,
Emanuel




More information about the Beginners mailing list