├── .gitattributes
├── .gitignore
├── .travis.yml
├── CNAME
├── README.md
├── index.htm
├── index.html
├── login.htm
├── man
├── index.htm
├── login.htm
└── sample.htm
├── priv
├── k6
│ ├── config.js
│ └── main.js
└── static
│ ├── back.jpg
│ ├── index.htm
│ ├── login.htm
│ ├── synrc.css
│ └── websocket.svg
├── rebar.config
├── src
├── index.erl
├── login.erl
├── routes.erl
├── sample.app.src
└── sample.erl
├── sys.config
└── vm.args
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.html linguist-detectable=false
2 | *.htm linguist-detectable=false
3 | *.css linguist-detectable=false
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ebin
2 | log
3 | logs
4 | .applist
5 | Mnesia.nonode@nohost
6 | deps
7 | .rebar
8 | review
9 | _build
10 | rebar.lock
11 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: erlang
2 | otp_release:
3 | - 21.3
4 | - 22.0
5 | - 23.0
6 | notifications:
7 | email:
8 | - maxim@synrc.com
9 | script:
10 | - "curl -fsSL https://raw.github.com/synrc/mad/master/mad > mad"
11 | - "chmod +x mad"
12 | - "./mad dep com"
13 | - "rebar3 dialyzer"
14 |
--------------------------------------------------------------------------------
/CNAME:
--------------------------------------------------------------------------------
1 | sample.n2o.dev
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | SAMPLE: WebSocket Application
2 | =============================
3 |
4 | [](https://travis-ci.com/synrc/sample)
5 |
6 | NITRO/N2O pages that work on top of raw COWBOY/RANCH connections.
7 |
8 | Intro
9 | -----
10 |
11 | SAMPLE application consist of two page modules `login` and `index`.
12 | It creates WebSocket connection to `n2o` server.
13 | The permanent example is accesible at https://sample.n2o.dev/index.htm.
14 |
15 | Index
16 | -----
17 |
18 | Init event.
19 | Chat event.
20 | Client event.
21 | File Transfer event.
22 |
23 | Login
24 | -----
25 |
26 | Channel init.
27 | Login event.
28 |
29 | Setup
30 | -----
31 |
32 | To run review application just clone, build and run:
33 |
34 | ```
35 | $ rebar3 get-deps
36 | $ rebar3 shell
37 | ```
38 |
39 | Then open it in browser:
40 |
41 | ```
42 | $ open http://localhost:8001/app/login.htm
43 | ```
44 |
45 | Credits
46 | -------
47 | * Brought with ❤ by N2O community
48 |
--------------------------------------------------------------------------------
/index.htm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Chat
8 |
9 |
10 |
11 |
12 | room
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | SAMPLE
10 |
11 |
12 |
13 |
14 |
15 |
16 |
21 |
22 |
23 |
24 | SAMPLE WS
25 |
26 |
27 |
45 |
46 |
47 |
48 | REBAR3
49 |
50 |
51 | Picture 1. OTP tools
52 |
53 | $ git clone git://github.com/synrc/sample
54 | $ cd sample
55 | $ rebar3 shell
56 |
57 | $ open https://127.0.0.1:8001/app/index.htm
58 |
59 |
60 |
61 | START
62 |
63 |
64 | Picture 2. Minimal Configuration
65 |
66 | {deps, [{cowboy, ".*", {git, "git://github.com/voxoz/cowboy2", []}},
67 | {nitro, ".*", {git, "git://github.com/synrc/nitro", []}},
68 | {n2o, ".*", {git, "git://github.com/synrc/n2o", []}},
69 | {kvs, ".*", {git, "git://github.com/synrc/kvs", []}},
70 | {syn, ".*", {git, "git://github.com/ostinelli/syn", {tag,"2.1.1"}}}
71 | ]}.
72 |
73 |
74 |
75 |
76 | Picture 3. Development Release
77 |
78 | Eshell V10.1.1 (abort with ^G)
79 | 1> application:which_applications().
80 | [{sample,"SAMPLE WebSocket application","0.7.0"},
81 | {nitro,"NITRO HTML5 DSL","3.10"},
82 | {syn,"A global Process Registry and Process Group manager.","2.1.1"},
83 | {cowboy,"Small, fast, modern HTTP server.","2.8.0"},
84 | {ranch,"Socket acceptor pool for TCP protocols.","1.7.1"},
85 | {ssl,"Erlang/OTP SSL application","10.1"},
86 | {public_key,"Public key infrastructure","1.9.1"},
87 | {kvs,"KVS Abstract Chain Database","7.9.1"},
88 | {cowlib,"Support library for manipulating Web protocols.","2.9.1"},
89 | {crypto,"CRYPTO","4.8"},
90 | {asn1,"The Erlang ASN1 compiler version 5.0.14","5.0.14"},
91 | {n2o,"N2O MQTT TCP WebSocket","7.10.0"},
92 | {inets,"INETS CXC 138 49","7.3"},
93 | {mnesia,"MNESIA CXC 138 12","4.18"},
94 | {syntax_tools,"Syntax tools","2.1.6"},
95 | {compiler,"ERTS CXC 138 10","7.2.6"},
96 | {stdlib,"ERTS CXC 138 10","3.13.2"},
97 | {kernel,"ERTS CXC 138 10","7.1"}]
98 |
99 |
100 |
101 |
102 |
109 |
110 |
120 |
121 |
122 |
125 |
126 |
127 |
128 |
--------------------------------------------------------------------------------
/login.htm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Login
8 |
9 |
13 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/man/index.htm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | INDEX
10 |
11 |
12 |
13 |
14 |
15 |
16 |
21 |
22 |
23 |
24 | INDEX
25 |
26 |
27 |
28 |
29 |
30 |
31 | INTRO
32 |
33 | Index page provides basic chat functionality and file upload feature.
34 |
35 |
36 |
37 |
38 | PROTOCOL
39 |
40 | event(init)
41 | event(chat)
42 | event(#client{})
43 | event(#ftp{})
44 | event(logout)
45 |
46 |
47 |
48 |
49 | This module may refer to:
50 |
51 | sample,
52 | login.
53 |
54 |
55 |
56 |
57 |
58 |
61 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/man/login.htm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | LOGIN
10 |
11 |
12 |
13 |
14 |
15 |
16 |
21 |
22 |
23 |
24 | LOGIN
25 |
26 |
27 |
28 |
29 |
30 |
31 | INTRO
32 |
33 | Login page providees nickname introduction and room selection.
34 |
35 |
36 |
37 |
38 | PRTOCOL
39 |
40 | event(init)
41 | event(login)
42 |
43 |
44 |
45 |
46 | This module may refer to:
47 |
48 | sample,
49 | index.
50 |
51 |
52 |
53 |
54 |
55 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/man/sample.htm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | SAMPLE
10 |
11 |
12 |
13 |
14 |
15 |
16 |
21 |
22 |
23 |
24 | SAMPLE
25 |
26 |
27 |
28 |
29 |
30 |
31 | INTRO
32 |
33 | SAMPLE is a regular Erlang application.
34 |
35 |
36 |
37 |
38 | HEADER
39 |
40 |
41 | Picture 1. HOW TO SETUP BOTH APP AND SUP IN ERLANG
42 |
43 | -module(sample).
44 | -behaviour(supervisor).
45 | -behaviour(application).
46 | -export([init/1, start/0, start/2, stop/1, main/1]).
47 |
48 |
49 |
50 |
51 |
52 |
53 | OTP
54 |
55 | Note that suring start you should specify mauth module.
56 | Dafault implementation performs client topic autosubscription.
57 |
58 |
59 | Picture 2. Implements Erlang/OTP service API
60 |
61 | start() -> start(normal,[]).
62 | start(_,_) -> supervisor:start_link({local,SAMPLE},SAMPLE,[]).
63 | stop(_) -> ok.
64 |
65 |
66 |
67 |
68 |
69 |
70 | COWBOY
71 |
72 | SAMPLE application uses COWBOY as a static HTTP server
73 | and as a WebSocket server.
74 |
75 |
76 | Picture 3. COWBOY setup
77 |
78 | start(_,_) -> cowboy:start_tls(http,n2o_cowboy:env(?MODULE),
79 | #{env=>#{dispatch=>n2o_cowboy:points() }}),
80 | supervisor:start_link({local,sample},sample,[]).
81 |
82 |
83 |
84 |
85 |
86 |
87 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/priv/k6/config.js:
--------------------------------------------------------------------------------
1 | {
2 | "hosts": {
3 | "local": "127.0.0.1"
4 | },
5 | "stages": [
6 | {
7 | "duration": "1m",
8 | "target": 10
9 | }
10 | ],
11 | "thresholds": {
12 | "http_req_duration": ["avg<100", "p(95)<200"]
13 | },
14 | "noConnectionReuse": true,
15 | "type": "browser",
16 | "vus": "10",
17 | "duration": "3m",
18 | "userAgent": "MyK6UserAgentString/1.0"
19 | }
20 |
--------------------------------------------------------------------------------
/priv/k6/main.js:
--------------------------------------------------------------------------------
1 | import { browser } from 'k6/experimental/browser';
2 | import { check } from 'k6';
3 |
4 | export const options = {
5 | scenarios: { ui: { executor: 'shared-iterations', options: { browser: { type: 'chromium' }, }, }, },
6 | thresholds: { checks: ['rate==1.0'], },
7 | };
8 |
9 | export default async function () {
10 | const context = browser.newContext();
11 | const page = context.newPage();
12 | try {
13 | await page.goto('http://localhost:8001/app/login.htm');
14 | const button = page.locator('#loginButton');
15 | button.click();
16 | await page.waitForNavigation();
17 | check(page, { body: (p) => p.locator('#logout').textContent() === 'Logout ', });
18 | } finally {
19 | page.close();
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/priv/static/back.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/synrc/sample/69eaa0dfe7ea5f3da68c64dec2b2a6efc10aa3a0/priv/static/back.jpg
--------------------------------------------------------------------------------
/priv/static/index.htm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Chat
9 |
10 |
11 |
12 |
13 | room
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/priv/static/login.htm:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Login
8 |
9 |
13 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/priv/static/synrc.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | box-sizing: border-box;
5 | }
6 |
7 | body {
8 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
9 | color: #737373;
10 | background: url('back.jpg') center / cover;
11 | margin: 0;
12 | }
13 |
14 | button {
15 | padding: 10px 20px;
16 | font-size: 18px;
17 | color: white;
18 | background: #4990E2;
19 | font-weight: bold;
20 | font-family: inherit;
21 | line-height: 1;
22 | border: none;
23 | text-transform: uppercase;
24 | border-radius: 4px;
25 | box-shadow: 0px 10px 15px -5px rgba(100, 100, 100, .35);
26 | margin: 10px;
27 | }
28 |
29 | button:hover {
30 | background: #1a84ff;
31 | }
32 |
33 | button:focus {
34 | outline: none;
35 | background: #1f63b2;
36 | }
37 |
38 | img {
39 | width: 140px;
40 | margin: auto;
41 | padding: 0;
42 | display: block;
43 | }
44 |
45 | .login {
46 | display: flex;
47 | flex-direction: column;
48 | height: 100vh;
49 | align-items: center;
50 | }
51 |
52 | .login h1 {
53 | color: #4990E2;
54 | font-size: 34px;
55 | margin: 30px 0;
56 | text-shadow: 1px 2px 8px rgba(100, 100, 100, .3);
57 | }
58 |
59 | .login img {
60 | margin-top: 20px;
61 | }
62 |
63 | .login form {
64 | width: 300px;
65 | background: white;
66 | padding: 20px;
67 | display: flex;
68 | justify-content: center;
69 | flex-wrap: wrap;
70 | border-radius: 4px;
71 | box-shadow: 0px 4px 40px rgba(100, 100, 100, .35);
72 | }
73 |
74 | .login label {
75 | width: 100%;
76 | display: block;
77 | font-size: 18px;
78 | }
79 |
80 | .login input {
81 | width: 100%;
82 | display: block;
83 | border: none;
84 | font-family: inherit;
85 | color: inherit;
86 | font-size: 19px;
87 | line-height: 1.4;
88 | border-bottom: 1px solid #4990E2;
89 | margin-bottom: 20px;
90 | }
91 |
92 | .login input:focus {
93 | outline: none;
94 | }
95 |
96 | .login footer {
97 | margin-top: auto;
98 | margin-bottom: 30px;
99 | font-size: 18px;
100 | background: white;
101 | padding: 4px 10px;
102 | border-radius: 4px;
103 | box-shadow: 0px 4px 40px rgba(100, 100, 100, .35);
104 | }
105 |
106 | .chat {
107 | text-align: center;
108 | }
109 |
110 | .chat header {
111 | display: inline-block;
112 | max-width: 200px;
113 | vertical-align: top;
114 | margin-right: 50px;
115 | margin-top: 20px;
116 | }
117 |
118 | .chat img {
119 | margin-bottom: 20px;
120 | }
121 |
122 | .chat h2 {
123 | color: #4990E2;
124 | font-size: 28px;
125 | margin: 10px 0;
126 | text-shadow: 1px 2px 8px rgba(100, 100, 100, .3);
127 | }
128 |
129 | .chat main {
130 | display: inline-block;
131 | vertical-align: top;
132 | text-align: left;
133 | max-width: 600px;
134 | margin: 40px 10px;
135 | }
136 |
137 | .chat form {
138 | display: flex;
139 | flex-wrap: wrap;
140 | justify-content: space-between;
141 | margin: 0px 0 70px;
142 | }
143 |
144 | .chat textarea:focus {
145 | outline: none;
146 | }
147 |
148 | .chat textarea {
149 | width: 100% !important;
150 | margin-bottom: 20px;
151 | border: none;
152 | font-family: inherit;
153 | color: inherit;
154 | font-size: 18px;
155 | line-height: 1.2;
156 | padding: 8px 16px;
157 | border-radius: 4px;
158 | box-shadow: 0px 4px 40px rgba(100, 100, 100, .35);
159 | }
160 |
161 | ::-webkit-input-placeholder {
162 | color: #ccc;
163 | }
164 |
165 | ::-moz-placeholder {
166 | color: #ccc;
167 | }
168 |
169 | ::-ms-input-placeholder {
170 | color: #ccc;
171 | }
172 |
173 | .chat span>button {
174 | margin-right: 5px;
175 | }
176 |
177 | history {
178 | display: block;
179 | }
180 |
181 | message {
182 | display: block;
183 | font-size: 18px;
184 | background: white;
185 | padding: 8px 16px;
186 | margin: 15px 0;
187 | border-radius: 4px;
188 | box-shadow: 0px 4px 40px rgba(100, 100, 100, .35);
189 | white-space: pre-wrap;
190 | overflow-x:auto;
191 | }
192 |
193 | author {
194 | display: inline;
195 | font-weight: bold;
196 | }
197 |
198 | author:empty {
199 | display: none;
200 | }
201 |
202 | author::after {
203 | content: ': ';
204 | }
--------------------------------------------------------------------------------
/priv/static/websocket.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/rebar.config:
--------------------------------------------------------------------------------
1 | {deps, [{cowboy, "2.8.0"},
2 | {syn,"2.1.1"},
3 | {nitro, "7.4.1"},
4 | {n2o,"8.12.1"},
5 | {kvs, "9.4.2"}]}.
6 |
7 | {relx, [{release, {sample, "0.7.0"},[sample]},
8 | {dev_mode, false},
9 | {sys_config, "sys.config"},
10 | {vm_args, "vm.args"},
11 | {include_erts, true},
12 | {extended_start_script, true}]}.
13 |
14 | {shell,[{config, "sys.config"},
15 | {apps, [sample]}]}.
16 |
17 | {dialyzer, [
18 | {plt_apps, top_level_deps}
19 | ]}.
20 |
21 | {project_plugins, [rebar3_format]}.
22 | {format, [
23 | {files, ["src/*.erl", "test/*.erl"]},
24 | {formatter, otp_formatter},
25 | {options, #{ line_length => 108,
26 | paper => 250,
27 | spaces_around_fields => false,
28 | inlining => all,
29 | inline_clause_bodies => true,
30 | inline_expressions => true,
31 | inline_qualified_function_composition => true,
32 | inline_simple_funs => true,
33 | inline_items => all,
34 | inline_fields => true,
35 | inline_attributes => true
36 | }}]}.
37 |
--------------------------------------------------------------------------------
/src/index.erl:
--------------------------------------------------------------------------------
1 | -module(index).
2 |
3 | -compile(export_all).
4 |
5 | -include_lib("nitro/include/nitro.hrl").
6 |
7 | -include_lib("n2o/include/n2o.hrl").
8 |
9 | -include_lib("kvs/include/cursors.hrl").
10 |
11 | event(init) ->
12 | Room = n2o:session(room),
13 | Key = {topic, Room},
14 | n2o:reg(Key),
15 | n2o:reg(n2o:sid()),
16 | nitro:clear(history),
17 | nitro:update(logout,
18 | #button{id = logout, body = "Logout " ++ n2o:user(),
19 | postback = logout}),
20 | nitro:update(heading, [#h2{id = heading, body = Room}]),
21 | nitro:update(upload, #upload{}),
22 | nitro:update(send,
23 | #button{id = send, body = <<"Chat">>, postback = chat,
24 | source = [message]}),
25 | [event(#client{data = E})
26 | || E <- lists:reverse(kvs:feed(Key))];
27 | event(logout) ->
28 | n2o:user([]),
29 | nitro:redirect("/app/login.htm");
30 | event(chat) -> chat(nitro:q(message), nitro);
31 | event(#client{data =
32 | {'$msg', _, _, _, User, Message}}) ->
33 | nitro:wire(#jq{target = message,
34 | method = [focus, select]}),
35 | nitro:insert_top(history,
36 | nitro:render(#message{body =
37 | [#author{body = User}, Message]}));
38 | event(#ftp{sid = Sid, filename = Filename,
39 | status = {event, stop}} =
40 | Data) ->
41 | Name =
42 | hd(lists:reverse(string:tokens(nitro:to_list(Filename),
43 | "/"))),
44 | chat(nitro:render(#link{href =
45 | iolist_to_binary(["/app/", Sid, "/", Name]),
46 | body = Name}),
47 | index);
48 | event(Event) -> ok.
49 |
50 | jse(X) -> X.
51 |
52 | chat(Message, F) ->
53 | Room = n2o:session(room),
54 | User = n2o:user(),
55 | Msg = {'$msg',
56 | kvs:seq([], []),
57 | [],
58 | [],
59 | User,
60 | F:jse(Message)},
61 | kvs:append(Msg, {topic, Room}),
62 | n2o:send({topic, Room}, #client{data = Msg}).
63 |
--------------------------------------------------------------------------------
/src/login.erl:
--------------------------------------------------------------------------------
1 | -module(login).
2 |
3 | -compile(export_all).
4 |
5 | -include_lib("nitro/include/nitro.hrl").
6 |
7 | -include_lib("n2o/include/n2o.hrl").
8 |
9 | event(init) ->
10 | nitro:update(loginButton,
11 | #button{id = loginButton, body = "Login",
12 | postback = login, source = [user, pass]});
13 | event(login) ->
14 | User = nitro:to_list(nitro:q(user)),
15 | Room = nitro:to_list(nitro:q(pass)),
16 | n2o:user(User),
17 | n2o:session(room, Room),
18 | nitro:redirect("/app/index.htm?room=" ++ Room),
19 | ok;
20 | event(_) -> [].
21 |
--------------------------------------------------------------------------------
/src/routes.erl:
--------------------------------------------------------------------------------
1 | -module(routes).
2 |
3 | -include_lib("n2o/include/n2o.hrl").
4 |
5 | -export([init/2, finish/2]).
6 |
7 | finish(State, Ctx) -> {ok, State, Ctx}.
8 |
9 | init(State, #cx{req = Req} = Cx) ->
10 | #{path := Path} = Req,
11 | {ok,
12 | State,
13 | Cx#cx{path = Path, module = route_prefix(Path)}}.
14 |
15 | route_prefix(<<"/ws/", P/binary>>) -> route(P);
16 | route_prefix(<<"/", P/binary>>) -> route(P);
17 | route_prefix(P) -> route(P).
18 |
19 | % Don't use fancy routers, be like poor man's pattern mach.
20 |
21 | route(<<>>) -> login;
22 | route(<<"index", _/binary>>) -> index; % github static
23 | route(<<"login", _/binary>>) -> login; % github static
24 | route(<<"app/index", _/binary>>) -> index; % priv static
25 | route(<<"app/login", _/binary>>) -> login; % priv static
26 | route(_) -> login.
27 |
--------------------------------------------------------------------------------
/src/sample.app.src:
--------------------------------------------------------------------------------
1 | {application, sample,
2 | [{description, "SAMPLE WebSocket application"},
3 | {vsn, "4.11.0"},
4 | {registered, []},
5 | {applications, [public_key,kernel,stdlib,crypto,kvs,mnesia,n2o,nitro,syn,cowlib,ssl,ranch,cowboy]},
6 | {mod, { sample, []}},
7 | {env, []},
8 | {modules,[]}]}.
9 |
--------------------------------------------------------------------------------
/src/sample.erl:
--------------------------------------------------------------------------------
1 | -module(sample).
2 |
3 | -behaviour(supervisor).
4 |
5 | -behaviour(application).
6 |
7 | -compile(export_all).
8 |
9 | main(A) -> mad:main(A).
10 |
11 | stop(_) -> ok.
12 |
13 | start() -> start(normal, []).
14 |
15 | start(_, _) ->
16 | cowboy:start_clear(http,
17 | [{port, application:get_env(n2o, port, 8001)}],
18 | #{env => #{dispatch => n2o_cowboy:points()}}),
19 | supervisor:start_link({local, sample}, sample, []).
20 |
21 | init([]) ->
22 | kvs:join(),
23 | {ok, {{one_for_one, 5, 10}, []}}.
24 |
--------------------------------------------------------------------------------
/sys.config:
--------------------------------------------------------------------------------
1 | [
2 | {n2o, [{port,8001},
3 | {igor,"deps/n2o/src/protos"},
4 | {app,sample},
5 | {upload,"./priv/static/"},
6 | {routes,routes},
7 | {mq,n2o_syn},
8 | {formatter,n2o_bert},
9 | {protocols,[n2o_heart,nitro_n2o,n2o_ftp]},
10 | {session,n2o_session},
11 | {origin,<<"*">>},
12 | {pickler,n2o_secret},
13 | {event,pickle}]},
14 | {kvs, [{dba,kvs_mnesia},
15 | {dba_st,kvs_stream},
16 | {schema, [kvs, kvs_stream ]} ]}
17 | ].
18 |
--------------------------------------------------------------------------------
/vm.args:
--------------------------------------------------------------------------------
1 | +W w
2 | -kernel net_ticktime 60
3 | -env ERL_CRASH_DUMP log/crash.dump
4 | +e 256000
5 | -env ERL_FULLSWEEP_AFTER 1000
6 | +Q 65536
7 | +P 256000
8 | +A 32
9 | +K true
10 | -smp auto
11 | -setcookie emq_dist_cookie
12 | -name sample-1@127.0.0.1
13 | +zdbbl 32768
14 |
--------------------------------------------------------------------------------