kvs.htm 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. <html>
  2. <head>
  3. <meta charset="utf-8" />
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <meta name="description" content="" />
  7. <meta name="author" content="Maxim Sokhatsky" />
  8. <title>N2O</title>
  9. <link rel="stylesheet" href="https://n2o.space/n2o.css" />
  10. </head>
  11. <body>
  12. <header>
  13. <a href="../index.html"><img src="https://n2o.space/img/Synrc Neo.svg"></a>
  14. <h1>N2O API</h1>
  15. </header>
  16. <main>
  17. <section>
  18. <h3>INTRO</h3>
  19. <p>The <b>n2o</b> defines the way you create, configure and run
  20. arbitrary applications and protocols inside some hosts, into
  21. which N2O can be injected, such as <b>cowboy</b> and <b>emqttd</b>.
  22. Each application can spawn its instance in its own way, like
  23. web pages spawn WebSocket connections, workflow engines
  24. spawn business proceseses and chat applications spawns roster
  25. and chatroom processes. With N2O everything is managed by protocols.</p>
  26. <p>The N2O itself a an enbeddable protocol loop. However besides that
  27. it handles cache and session ETS tables along with flexible async
  28. processes with no ownership restriction. It also introduces logging
  29. approach, AES/CBC&mdash;128 pickling and with BERT/JSON formatter.</p>
  30. </section>
  31. <section>
  32. <h3>RECORDS</h3>
  33. <figure><figcaption>Listing 1. Erlang/OTP records</figcaption><code>
  34. #ok { data = [] :: term() }.
  35. #error { data = [] :: term() }.
  36. </code></figure>
  37. <figure><figcaption>Listing 2. N2O Protocol</figcaption><code>
  38. #reply { data = [] :: [] | binary(),
  39. req = [] :: [] | term(),
  40. state = [] :: [] | term() }.
  41. #unknown { data = [] :: [] | binary(),
  42. req = [] :: [] | term(),
  43. state = [] :: [] | term() }.
  44. </code></figure>
  45. <figure><figcaption>Listing 3. N2O State</figcaption><code>
  46. #cx { session = [] :: [] | binary(),
  47. formatter = bert :: bert | json,
  48. actions = [] :: list(tuple()),
  49. state = [] :: [] | term(),
  50. module = [] :: [] | atom(),
  51. lang = [] :: [] | atom(),
  52. path = [] :: [] | binary(),
  53. node = [] :: [] | atom(),
  54. pid = [] :: [] | pid(),
  55. vsn = [] :: [] | integer() }).
  56. </code></figure>
  57. </section>
  58. <section>
  59. <h3>PROTOCOLS</h3>
  60. <p>While all application protocols in the system
  61. are desired to be placed in the single effectful
  62. environment or same error handling path, <b>n2o</b> defines
  63. single protocol loop for all applications in its federation of protocols.</p>
  64. <p>In core bundle <b>n2o</b> is shipped with NITRO and FTP protocols which
  65. allows you to create real-time web applications with binary-based protocols,
  66. priving also robust and performant upload client and file transfer protocol.
  67. For bulding web based NITRO applications you need to include
  68. <b>nitro</b> dependency.</p>
  69. <h4>info(term(),term(),#cx{}) -> #reply{} | #unknown{}.</h4>
  70. <p>The <b>info/2</b> is a N2O protocol callback that will be called on each
  71. incoming request. N2O code should be embedded into applications host:
  72. MQTT (as ring of MQTT clients), or HTTP server or WebSocket, or raw TCP.</p>
  73. </section>
  74. <section>
  75. <h3>RPC MQTT</h3>
  76. <p>N2O provides RPC over MQ mechanism for MQTT devices. N2O spawn a set of
  77. <a href="n2o_vnode.htm">n2o_vnode</a> workers as <a href="n2o_async.htm">n2o_async</a>
  78. processes that listen to <b>events</b> topic. Response are sent to <b>actions</b> topic,
  79. which is subscribed automatically on MQTT session init.</p>
  80. <figure><figcaption>Listing 4. MQTT RPC Topics</figcaption><code>
  81. actions/:vsn/:module/:client
  82. events/:vsn/:node/:module/:client
  83. </code></figure>
  84. </section>
  85. <section>
  86. <h3>RPC WebSocket</h3>
  87. <p>In pure WebSocket case N2O implements <a href="n2o_proto.htm">n2o_proto</a> as cowboy module supporting binary and text messages.</p>
  88. <figure><figcaption>Listing 5. Cowboy stream protocol</figcaption><code>
  89. #binary { data :: binary() }.
  90. #text { data :: binary() }.
  91. </code></figure>
  92. </section>
  93. <section>
  94. <h3>EXAMPLE</h3>
  95. <p>Here is little example of overriding INIT protocol message from NITRO protocol
  96. and generate standart token stored in KVS.</p>
  97. <figure><figcaption>Listing 6. Custom INIT Protocol</figcaption><code>
  98. -module(custom_init).
  99. -compile(export_all).
  100. info({init, <<>>}, Req, State = #cx{session = Session}) ->
  101. {'Token', Token} = n2o_auth:gen_token([], Session),
  102. #cx{params = Client} = get(context),
  103. kvs:put(#'Token'{token = Token, client = Client}),
  104. n2o_nitro:info({init, n2o:format(Token)}, Req, State);
  105. info(Message,Req,State) -> {unknown,Message,Req,State}.
  106. </code></figure>
  107. </section>
  108. <section>
  109. <h3>CONFIG</h3>
  110. <p>Just put protocol implementation module name to <b>protocol</b> option in sys.config.</p>
  111. <figure><code>
  112. [{n2o,[{cache,n2o},
  113. {mq,n2o},
  114. {formatter,n2o_format},
  115. {logging,n2o_io},
  116. {log_modules,n2o},
  117. {log_level,n2o},
  118. {session,n2o_session},
  119. {pickler,n2o_secret},
  120. {protocols,[custom_init,n2o_ftp,n2o_nitro]},
  121. {timer,{0,10,0}}]}].
  122. </code></figure>
  123. <p>N2O is the facade of the following services: cache, mq, message formating, loging,
  124. sessions, pickling and protocol loops. The other part of N2O is <a href="n2o_async.htm">n2o_async</a> module
  125. for spawning supervised application processes tha use N2O API. In this simple
  126. configuration you may set any implementation to any service.</p>
  127. </section>
  128. <section>
  129. <h3>CACHE</h3>
  130. <p>Cache is fast expirable memory store. Just put values onto keys using these
  131. functions and system timer will clear expired entries eventually.
  132. You can select caching module implementation by seting <b>cache</b> n2o parameter to module name.
  133. Default n2o cache implementation just turns each ets store into expirable.</p>
  134. <h4>cache(Tab, Key, Value, Till) -> term().</h4>
  135. <p>Sets a Value with a given TTL.</p>
  136. <h4>cache(Tab, Key) -> term().</h4>
  137. <p>Gets a Value.</p>
  138. </section>
  139. <section>
  140. <h3>PUBSUB</h3>
  141. <p>The minimal requirement for any framework is to pub/sub API.
  142. N2O provides selectable API through <b>mq</b> environment parameter.</p>
  143. <h4>subscribe(Client, Topic, Options) -> term().</h4>
  144. <p>Subscribe an absctract client to a transient topic. In particular
  145. implementation the semantics could differ. In MQTT you can subscribe
  146. offline/online clients to any persistent topics.</p>
  147. <h4>unsubscribe(Client, Topic, Options) -> term().</h4>
  148. <p>Unsubscribe an abstract client from a transient topic. In MQTT
  149. we remove the subscription from persistent database.</p>
  150. <h4>publish(Topic, Message, Options) -> term().</h4>
  151. <p>Publish a message to a topic. In MQTT if clients are offline
  152. they will receive offline messages from the
  153. inflight srotarge once they become online.</p>
  154. </section>
  155. <section>
  156. <h3>FORMAT</h3>
  157. <p>Call this function for changeable at runtime socket binary formatting.
  158. Used to format data field of the returned values in protocol implementations.
  159. N2O provides selectable API through <b>formatter</b> environment parameter.</p>
  160. <h4>format(Message, bert | json) -> binary().</h4>
  161. <figure><code>
  162. > io:format("~ts~n",[n2o:format(#io{},json)]).
  163. {"t":104,"v":[{"t":100,"v":"io"},{"t":109,"v":""},{"t":109,"v":[131,106]}]}
  164. ok
  165. > n2o:format(#ok{code=undefined},bert).
  166. {binary,<<131,104,2,100,0,2,111,107,100,0,9,117,110,100,
  167. 101,102,105,110,101,100>>}
  168. </code></figure>
  169. </section>
  170. <section>
  171. <h3>LOG</h3>
  172. <p>First you need specify global module in sys.config,
  173. where functions <b>log_level</b> and <b>log_modules</b> are placed.
  174. See options in config with with same names as functions.</p>
  175. <p>Then implement these function in way of returning the list
  176. modules you want to trace, and global log level for them.</p>
  177. <figure><figcaption>Listing 7. Log Framework</figcaption>
  178. <code>
  179. log_modules() -> [n2o,n2o_async,n2o_proto].
  180. log_level() -> info.
  181. </code></figure>
  182. <p>In your code you should use following trace functions
  183. which are the same as callback API for n2o logging
  184. environment variable.</p>
  185. <h4>error(Module, Format, Args) -> ok | skip.</h4>
  186. <h4>info(Module, Format, Args) -> ok | skip.</h4>
  187. <h4>warning(Module, Format, Args) -> ok | skip.</h4>
  188. </section>
  189. <section>
  190. <h3>SESSION</h3>
  191. <p>Sessions are stored in <b>cookies</b> table and indexed by security token which
  192. is usually a password based token. All session variables from all users are stored in this table.
  193. each user see only its variables indexed by his token. Sessions like a cache are expirable.
  194. Technically, N2O sessions are the server controlling mechanism of JavaScript cookies.</p>
  195. <h4>session(Key, Value) -> term().</h4>
  196. <p>Sets a Value into ETS table <b>cookies</b> for a token from #cx.session which
  197. is set there earlier from INIT message or MQTT headers,
  198. before entering the top level N2O loop.</p>
  199. <figure><figcaption>Listing 8. Sessions</figcaption>
  200. <code>
  201. 1> rr(n2o).
  202. [bin,client,cx,direct,ev,flush,ftp,ftpack,handler,
  203. mqtt_client,mqtt_message,pickle,server]
  204. 2> put(context,#cx{session=10}).
  205. undefined
  206. 3> n2o:session(user,maxim).
  207. maxim
  208. 4> ets:tab2list(cookies).
  209. [{{10,user},
  210. <<"/">>,
  211. {1504,977449,476430},
  212. {{2017,9,9},{20,32,29}},
  213. maxim}]
  214. </code></figure>
  215. <h4>session(Key) -> term().</h4>
  216. <p>Gets a Value by any Key.</p>
  217. </section>
  218. <section>
  219. <h3>PICKLE</h3>
  220. <p>Call this function for changeable at runtime term pickling.</p>
  221. <h4>pickle(term()) -> binary().</h4>
  222. <h4>depickle(binary()) -> term().</h4>
  223. </section>
  224. <section>
  225. <p>This module may refer to:
  226. <a href="http://erlang.org/doc/man/io.html">io</a></b>,
  227. <a href="http://erlang.org/doc/man/ets.html">ets</a></b>,
  228. <a href="n2o_async.htm">n2o_asynrc</a></b>,
  229. <a href="n2o_vnode.htm">n2o_vnode</a></b>,
  230. <a href="n2o_proto.htm"><b>n2o_proto</b></a>.
  231. </p>
  232. </section>
  233. </main>
  234. <footer>
  235. 2005&mdash;2017 &copy; Synrc Research Center
  236. </footer>
  237. </body>
  238. </html>