
INTRODUCTION
This post implies a good intro in N2O in Russian.
What is
Erlang / OTP Web Framework N2O and what its chip for web development can be found on the page in
github and the official site of
SynRC . There, everything as you like with graphs and presentations.
')
And here we consider the principles of the framework and talk about the eternal.
Considered version N2O: 1.1.0
It is always more interesting to see the result, rather than talk about it, I suggest that you first install N2O on your computer and only then delve into its insides. So clearer.
Get answers to your questions and see recommendations can be on the official IRC channel
# n2o on FreeNode.net.
INSTALLATION
Install Erlang if it is not installed yet. Installed.
Download N2O, compile and run:
git clone git://github.com/5HT/n2o.git cd n2o/samples make && make console
We look:
127.0.0.1:8000/

Opening several windows you can chat with yourself.
MANY THEORY
NICHE
It is intended primarily for developing horizontally scalable solutions with low latency for processing client requests.
Online games, chat rooms, instagrams, tweeters - this is not exactly what Erlang was created for, but where you need to use N2O.
Under the hood
N2O is a redesigned Nitrogen project that is a bit sad. In N2O, we have the fastest Web server Cowboy, work through WebSockets, exchange binary data wherever possible, HTML and DTL templates, the minimum amount of JavaScript without using third-party libraries.
Comparison of web frameworks on Erlang can be seen on the
link .
Ability to use:
- NoSQL solutions such as Mnesia, RIAK, KAI through a simple abstract model in the form of a KVS application.
- AVZ authorization libraries (Facebook, Google, Twitter, Github, Microsoft).
- Libraries of MQ Queues MQS for RabbitMQ.
- Erlang interpreter code in JavaScript with the ability to check at compile time - Shen .
- Any other Erlang solutions just by adding to the app.
In N2O, source code compilation is implemented on the fly, even without damage to open sessions, based on
Sync . Development is becoming more human.
With Sync, you can code without drochilova ( transl .)
Server data exchange with clients is implemented through WebSockets and has a minimal overhead. Possible data transfer formats:
- BLOB (RAW Binary), ideal for images
- Bert Encoded , for Erlang-terms
- Pickled , encoded data in Base64, or AES / RIPEMD160
Clustering and resiliency for the Web has become available more than ever before, with maximum ease of development.
_5HT: So that you do not e ___ cya. Your business is clack-clack and production
MODEL OF CONDUCT
N2O is built like Erlang itself in the transfer of messages, but not from process to process, but from client to server. Call it an event model.
We describe the timeline of the N2O embedded example of n2o_sample.
- When the page
/index
requested, the HTML markup described in the function index:body()
passed to the browser. - The page runs a javascript that initializes the connection through the WebSocket.
- Then, the payload in the form of JavaScript code is transmitted via WebSocket, and the page elements are initialized with data via
index:event(init)
. Here is one of the roles of JavaScript - for example, to create an event for the button on the client in the form of a JS function that sends information about the click to the server. - After clicking on the button, a Bert-Encoded message arrives on the server under the Base64
mushrooms and the index:event(Term)
function is performed where Term
is the term described in the button's record field: #button.postback
. For example, the #button{postback=sasay}
button after pressing will force the function index:event(sasay).
- The server, in turn, can also send data to the browser at any time. If the data is sent from another process
, then the following conditions must be met: at index:event(init)
main process servicing the client (browser tab) must be registered under some name by calling wf:reg/1
, and in process
after the end generating the code for updating the page ( wf:insert/2
, wf:wire/1
, etc.) the function wf:flush/1
should be called to send the update code to the browser, where it will then be executed by the JS machine.
The first thing that comes to mind is that the page dynamically changes not based on function calls from a JavaScript file, but based on the received JavaScript from the server in real time.
And this is the native interactive mode for a web application without using crutches like AJAX and LongPooling Comet. The future is here, kittens. His name is WebSockets.
A table of support for WS browsers can be seen
here , and check your browser
here .
MORE ABOUT THE APPLICATION STRUCTURE
If acquaintance with Erlang happened recently or just that, most likely there will be questions: what is where and in what place does it show your creativity.

Highlighted those folders and files that may be subject to editing. Consider the key parts.
n2o_sample
N2O already contains an example of a user application -
n2o_sample . n2o_sample is a separate Erlang application that runs on N2O. As can be seen in the picture above, it is located in the
apps/
directory - this is a collection of user applications, we can add our own ones there if it is necessary to divide n2o_sample into two or more independent applications.
Also n2o_sample, of course, can be renamed or replaced with something else. But for a start, I would not advise doing this, but using the existing code as a starting point in developing my application.
Application list
When you run n2o_sample, it, as Erlang relies on the application, runs all the applications that it depends on (dependencies from
deps/
, and user-defined, if any, from
apps/
). This code is in
n2o_sample/src/web_app.erl
:
-module(web_app). -behaviour(application). -export([start/2, stop/1]). start(_StartType, _StartArgs) -> application:start(crypto), application:start(sasl), application:start(ranch), application:start(cowboy), application:start(gproc), application:start(mimetypes), application:start(syntax_tools), application:start(compiler), application:start(erlydtl), application:start(rest), application:start(n2o), web_sup:start_link(). stop(_State) -> ok.
The
web_sup:start_link()
function starts the n2o_sample itself.
But if we want to expand this list of dependencies - you need to know that this is not the only place with a listing of applications. You also need to fix two more files:
reltool.config
and
.applist
, the latter being created after the first make command in the console. Keep in three places the same thing - a temporary crutch from @
darkproger , but he promised to fix everything (they have been waiting for the promised three years).
sys.config
Parameters for all applications are saved here. In one file. Conveniently. Then from the code we call
application:get_env(App,Key)
and that's it.
vm.args
Here you can specify the keys for the virtual machine as well as environment variables (instead of
$ export SOME_PARAM=value
).
priv / static /
The directory passed to the Cowboy web server as a static file file. Here you can place JavaScript code, throw pikchi and hentai.
n2o_sample/src/web_sup.erl
:
dispatch_rules() -> cowboy_router:compile( [{'_', [ {"/static/[...]", cowboy_static, {priv_dir, ?APP, <<"static">>, [{mimetypes,cow_mimetypes,all}]}}, ****
PAGES
To create dynamic pages, N2O allows you to include HTML files in your project as DTL templates. In the
deps/erlydtl/
directory there is an
ErlyDTL application which is intended for compiling DTL patterns into Erlang bytecode.
The templates themselves are located in the
n2o_sample/priv/templates/
directory and look like HTML files with external data source declarations through words enclosed in double curly braces
{{ }}
.
Thus, we can “lay out” the HTML layout with static information, and dynamically render the code to Erlang via the
{{ }}
connection.
For example, consider the body of the login: main / 0 function, which gives the browser the initial state of the page when going to
http://127.0.0.1/login/
:
#dtl{ file = "login", app=n2o_sample, bindings=[ {title,title()}, {body,body()} ]}.
- Here
login
is the name of the template: /priv/static/template/index.html; title
and body
- named inclusions in the HTML template {{title}} and {{body}};title()
and body()
- functions, the result of which will be substituted into the HTML template.
DEVELOPMENTS
Data exchange in N2O on the client is implemented via JavaScript, with the help of
/deps/n2o_scripts/n2o/bullet.js
files
/deps/n2o_scripts/n2o/bullet.js
(initializing the WebSocket connection) and
n2o.js
(processing the received data).
On the server side, endpoints are:
/n2o/src/endpoints/cowboy/bullet_handler.erl
(initialization of the WebSocket connection) and
n2o_bullet.erl
(data exchange).
API
Let us analyze the main API functions with which the most questions arise when meeting with N2O.
wf: comet / 1, wf: async / 1, wf: async / 2
Register the process under a unique name (
“comet”
for
comet/1
and
async/1
) within the node through
global:register_name/2
. If already registered, return its Pid.
wf: flush / 1
Withdraws via
wf_context:actions/0
saved in the state of the current process changes for the page and sends them via
wf:send/2
process (within the node) whose name is passed in the parameter.
wf: reg / 1, wf: reg / 2 (? REGISTRATOR = n2o_mq)
Register the process as
Property under a
non- unique name within the node through GProc. Re-registering the process via GProc under the same name will not work, the registration status is stored in the process's stack (
get/1
,
put/1
) and the term
skip
(
n2o_mq.erl
) will be returned. Additional info in Russian by Gproc
here .
The default logger is the
n2o_mq
module
n2o_mq
but it can be overridden, for example, to be able to register processes within the cluster.
wf: send / 2 (? REGISTRATOR = n2o_mq)
Sends the message passed to the function by the second argument to the process registered via
wf:reg/1
or
wf:reg/2
.
wf: q / 1
Retrieves the data transmitted from the client through the so-called postback elements, for example:
body() -> [ #textbox{ id=message }, #button{ postback={button_pressed}, source=[message] } ]. event({button_pressed}) -> wf:info("Message: ~p",[wf:q(message)]);
The text contained in the text box at the time the button is pressed will be printed to the console.
wf: qs / 1
Extract parameters from HTTP forms, for example:
wf:qs(<<"x">>)
will extract
<<"ABC">>
if the URL were
localhost:8000/index?x=ABC
localhost:8000/index?x=ABC
.
wf: wire / 1
It can take as an argument both JavaScript text and event codes declared in the “Actions” section of the
/n2o/include/wf.hrl
file, for example:
wf:wire(#alert{text="!"})
. JavaScript will also be wrapped in
#wire{actions=JS}
, which will result in the
wf:wire(#wire{sctions=JS})
construct.
wf: update / 2, wf: insert_top / 2, wf: remove / 1 and others
These are special cases of
wf:wire/1
, including ready-made JavaScript code for changing the DOM in the client’s browser.
wf: info, wf: warning, wf: error
These are the functions that are recommended to use, instead of
error_logger:info_msg/1
and the rest, respectively.
wf: f, wf: to_list, wf: to_binary, wf: html_encode, wf: url_encode, wf: hex_encode and others
Located in the “Convert and Utils API”
/n2o/src/wf.erl
file. All of them are add-ons over standard Erlang functions, but smarter and not so wooden.
wf:f
is an analogue of
io_lib:format
, then the list of functions-converters accepts any term to the input, then more web-specific functions. It makes no sense to describe them all in detail here, the only purpose was to show that they exist.
wf: pickle / 1, wf: depickle / 1 (? PICKLER = n2o_pickle)
Encoder and term decoder for transferring system calls between client and server.
n2o_pickle
encodes in Base64, while n2o_secret uses AES / RIPEMD160 encryption with a random key.
On this API everything, additional information can be found from the official docks on the
N2O API .
MUST PAY ATTENTION
Below are the free
SynRC software products that can speed up the output of your project to Erlang by tens of times.
KVS
KVS is an abstract KV noSQL database model that can feed table subsets via doubly linked lists and secondary indexes (
kvs:index/3
). Currently available with Mnesia, RIAK and KAI.
AVZ
AVZ - authorization system through Twitter, Google, Facebook, Github and Microsoft.
Shen
Shen is an Erlang interpreter of JavaScript code. Allows you to use the Erlang compiler to validate JavaScript.
Mqs
MQS - MQ library for RabbitMQ.
Feeds
Feeds - handler of the command pool for maintaining data consistency on all nodes of the cluster, also a cache server.
Skyline
SkyLine is an example of an online store on N2O.
COUNTACH
Countach is a social system and advanced app store. Production-ready. Uses KVS, AVZ and Feeds. Based on VOXOZ.
VOXOZ
VOXOZ - Open Erlang cloud platform (PaaS). Uses Docker, ErlangOnXen. More information on
blog.docker.io .
CONCLUSION
So that information is assimilated evenly, this is all for now. Special thanks to @
mtreskin for the advice on choosing the architecture and targeting nitrogen and n2o; as well as @
5HT for endless 24/7 consultation at IRC.