123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- \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}
|