A Haskell port of the N2O Erlang Application Server: http://synrc.github.io/n2o/
Support:
The eponymous N2O protocol is an innovative Javascript RPC where client state is moved to the server.
The server pushes chunks of javascript code to client which get evaluated there. The client pushes browser clicks to the server to the handled there. Achieved statelessness of client code obviates such things as synchronization of client-side models with the server, and dramatically reduces client code size. After all, we want to program as little as possible in such a poor language as Javascript, and more in Erlang or Haskell.
The idea has been field-tested in large-scale deployments in such areas as online banking and online card games, and contrary to intuition, shows excellent user-perceived performance.
There is no such thing as installation of handlers of server events. Instead, the server can command browser to execute arbitrary Javascript code. In practice it means that small pieces of code are generated on server, such as qi('myelementid').innerHTML = '<p>bar</p>'
, so there is no need to synchronize client-side code with server-side changes: some client code is effectively moved to the server.
The sending is unidirectional, just like the receiving: there are no need to wait for 'RPC return value' or analogs. So typical client code is just ws.send(enc(tuple(atom('FOOEVENT'),bin(qi('myelementid').value))))
- some data are collected and sent, that's it. Typically there are no callbacks, loops or conditions.
Small and efficient protocol stack. Code size is one of the features we are proud of:
$ cloc static src/Network/N2O* | tail -n+6 | sed s/--*// | column -t
Language files blank comment code
JavaScript 6 29 10 147
Haskell 2 47 6 138
SUM: 8 76 16 285
The protocol is binary compatible with original N2O protocol. The browser part is taken as is from the Erlang version. However, the server implements only a subset of the upstream features (shown in bold). Basically it's BERT over Websockets only. See the upstream documentation for terminology.
- Formatters: TEXT, JSON, XML, BERT, MessagePack
- Protocols: heart, spa, bin, nitrogen, bpe, mq, roster, muc, rest, search
- Endpoints: gen_server, ws, http
- PubSub: Built-in
- Persistence: None
- DOM Language: None
For quickstart you need Git
for retrieving sources, glorious Haskell
compiler, Static Web Server webfsd
, Casper.js
which run on top of headless v8 Phantom.js
:
$ brew install ghc
$ brew install cabal-install
$ brew install webfs
$ npm install -g casperjs
$ git clone http://github.com/nponeccop/n2o.hs && cd n2o.hs
$ cabal update
$ cabal install
$ webfsd
$ dist/build/n2o/n2o
$ open http://localhost:8000/sample/client.html
$ casperjs test tests
The library and the example chat server:
$ pacman -Sy --needed git ghc cabal-install webfs
$ git clone http://github.com/nponeccop/n2o.hs && cd n2o.hs
$ cabal update
$ cabal install
$ webfsd
$ nohup dist/build/n2o/n2o &
$ open http://localhost:8000/sample/client.html
The PhantomJS headless browser tests:
$ pacman -S --needed npm phantomjs
$ npm install casperjs
$ open http://localhost:8000/sample/client.html
$ node_modules/.bin/casperjs test tests
For quickstart you need at least GHC via MinGHC and Git
. In git bash
do:
$ git clone http://github.com/nponeccop/n2o.hs && cd n2o.hs
$ stack build
Run n2o.exe
and StaticWebServer.exe
and open http://localhost:8000/sample/client.html in your browser.
- Andy Melnikov
- Maxim Sokhatsky