-
Notifications
You must be signed in to change notification settings - Fork 0
/
processes.tex
134 lines (111 loc) Β· 5.07 KB
/
processes.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
\section{Erlang Processes}
\subsection{Reduced Latency}
The secret to reducing latency is simple. We try to deliver rendered HTML
as soon as possible and render JavaScript only when WebSocket initialization is complete.
It takes three steps and three Erlang processes for doing that.
\includeimage{images/page-lifetime.png}{Page Lifetime}
\paragraph{}
N2O request lifetime begins with the start of HTTP process serving the first HTML page.
After that it dies and spawns Transition process.
Then the browser initiates WebSocket connections to the similar URL endpoint.
N2O creates persistent WebSocket process and the Transition process dies.
\paragraph{}
Your page could also spawn processes with {\bf wf:async}.
These are persistent processes that act like regular Erlang processes.
This is a usual approach to organize non-blocking UI for file uploads
and other time consuming operations.
\newpage
\subsection{Page Serving Process}
This processes are applicable only to the case when you serving not static HTML,
but dynamically rendered pages with NITRO, DTL or ET template engines.
The very first HTTP handler only renders HTML. During page initialization
function Module:{\bf main/0} is called. This function should return raw HTML or
NITRO elements that could be rendered into raw HTML. All created on the way
JavaScript actions are stored in the transition process.
\vspace{1\baselineskip}
\begin{lstlisting}
main() -> #dtl { file = "login",
app = review,
bindings = [ { body,
#button { id = send,
postback = chat } } ] }.
\end{lstlisting}
\vspace{1\baselineskip}
\paragraph{}
HTTP handler will die immediately after returning HTML. Transition process
stores actions and waits for a request from a WebSocket handler.
\subsection{Transition Process}
Right after receiving HTML the browser initiates WebSocket connection
thus starting WebSocket handler on the server. After responding with
JavaScript actions the Transition process dies and the only process left
running is WebSocket handler. At this point initialization phase is complete.
\vspace{1\baselineskip}
\begin{lstlisting}
transition(Actions) ->
receive {'N2O',Pid} -> Pid ! Actions end.
\end{lstlisting}
\vspace{1\baselineskip}
Transition process is only applicable to dynamically rendered pages
served by {\bf n2o\_document} endpoint. You never deal with it manually.
\subsection{Events Process}
After that all client/server communication is performed over
WebSocket channel. All events coming from the browser are
handled by N2O, which renders elements to HTML and actions to
JavaScript. Each user at any time has only one WebSocket process
per connection.
\vspace{1\baselineskip}
\begin{lstlisting}
event(init) -> wf:reg(room);
event(chat) -> #insert_top(history,#span{body="message"}),
wf:flush(room).
\end{lstlisting}
\vspace{1\baselineskip}
This code will register all WebSocket processes under the same
topic in pubsub and broadcast history changing to all registered
process in the system under the same topic using {\bf \#flush}
NITRO protocol message.
\paragraph{}
During page initialization before Module:{\bf event(init)},
Module:{\bf main/0} is called to render initial postbacks for
elements. So you can share the same code to use SPA or DSL/DTL approach.
\subsection{Async Processes}
These are user processes that were created with {\bf wf:async} invocation.
This processes was very useful to organize persistent stateful connection
for legacy async technology like COMET for XHR channel. If you have problem with
proxying WebSocket stream you can easily use XHR fallback that is
provided by {\bf xhr.js} N2O companion library.
Async processes are optional and only needed when you have a UI event taking too much
time to be processed, like gigabyte file uploads. You can create
multiple async processes per user. Starting from N2O 2.9 all async
processes are being created as {\bf gen\_server} under
{\bf n2o\_sup} supervision tree.
\vspace{1\baselineskip}
\begin{lstlisting}
event(init) -> wf:reg(room),
wf:async("looper", fun async/1);
async(init) -> ok;
aynsc(Chat) -> io:format("Chat: ~p~n",[Chat]).
\end{lstlisting}
\vspace{1\baselineskip}
\newpage
\subsection{SPA Mode}
In SPA mode N2O can serve no HTML at all. N2O elements are
bound during initialization handshake and thus can be used
regularly as in DSL mode.
\paragraph{}
In the example provided in n2o/samples you can find two different
front end to the same {\bf review} application which consist of
two page modules {\bf index} and {\bf login}. You can access this application
involving no HTML rendering by using static file serving that could be
switched to direct nginx serving in production.
\vspace{1\baselineskip}
\begin{lstlisting}
open http://localhost:8000/static/app/login.htm
\end{lstlisting}
\vspace{1\baselineskip}
Or you can see DTL rendered HTML pages which resides at following address:
\vspace{1\baselineskip}
\begin{lstlisting}
open http://localhost:8000/login.htm
\end{lstlisting}
\vspace{1\baselineskip}