[#24] improving Documentation

This commit is contained in:
Felipe Ripoll 2018-07-06 10:32:03 -06:00
parent b48a80bab1
commit 264ea96893
37 changed files with 3587 additions and 275 deletions

1
.gitignore vendored
View File

@ -1,7 +1,6 @@
/_build
/cover
/deps
/doc
erl_crash.dump
*.ez
*.beam

View File

@ -7,7 +7,10 @@ Storage and data-processing companion for the [poa-netstats-agent](https://githu
## Documentation
In order to build the documentation run
- [Initial Architecture](pages/initial_architecture.md)
- You can find the online documentation [here](https://rawgit.com/poanetwork/poa-netstats-warehouse/master/doc/index.html)
Or you can build the documenation locally running
```
mix deps.get

BIN
assets/general_overview.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
assets/high_scalable.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
assets/scaling.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

22
doc/.build Normal file
View File

@ -0,0 +1,22 @@
dist/app-480ffdc169.css
dist/app-9bd040e5e5.js
fonts/icomoon.eot
fonts/icomoon.svg
fonts/icomoon.ttf
fonts/icomoon.woff
dist/sidebar_items-ffeb4f1e51.js
api-reference.html
initial_architecture.html
search.html
404.html
POABackend.html
POABackend.Protocol.html
POABackend.Protocol.DataType.html
POABackend.Protocol.Message.html
POABackend.Protocol.MessageType.html
POABackend.CustomHandler.html
POABackend.CustomHandler.REST.html
POABackend.Receiver.html
POABackend.Receivers.Dashboard.html
POABackend.Receivers.DynamoDB.html
index.html

101
doc/404.html Normal file
View File

@ -0,0 +1,101 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="ExDoc v0.18.3">
<title>404 poa_backend v0.1.0</title>
<link rel="stylesheet" href="dist/app-480ffdc169.css" />
<script src="dist/sidebar_items-ffeb4f1e51.js"></script>
</head>
<body data-type="extras">
<script>try { if(localStorage.getItem('night-mode')) document.body.className += ' night-mode'; } catch (e) { }</script>
<div class="main">
<button class="sidebar-button sidebar-toggle">
<span class="icon-menu" aria-hidden="true"></span>
<span class="sr-only">Toggle Sidebar</span>
</button>
<button class="sidebar-button night-mode-toggle">
<span class="icon-theme" aria-hidden="true"></span>
<span class="sr-only">Toggle Theme</span>
</button>
<section class="sidebar">
<a href="api-reference.html" class="sidebar-projectLink">
<div class="sidebar-projectDetails">
<h1 class="sidebar-projectName">
poa_backend
</h1>
<h2 class="sidebar-projectVersion">
v0.1.0
</h2>
</div>
</a>
<form class="sidebar-search" action="search.html">
<button type="submit" class="search-button">
<span class="icon-search" aria-hidden="true"></span>
</button>
<input name="q" type="text" id="search-list" class="search-input" placeholder="Search" aria-label="Search" autocomplete="off" />
</form>
<ul class="sidebar-listNav">
<li><a id="extras-list" href="#full-list">Pages</a></li>
<li><a id="modules-list" href="#full-list">Modules</a></li>
</ul>
<div class="gradient"></div>
<ul id="full-list" class="sidebar-fullList"></ul>
</section>
<section class="content">
<div class="content-outer">
<div id="content" class="content-inner">
<h2>Page not found</h2>
<p>Sorry, but the page you were trying to get to, does not exist. You
may want to try searching this site using the sidebar or using our
<a href="api-reference.html" title="API Reference">API Reference</a> page to find what
you were looking for.</p>
<footer class="footer">
<p>
<span class="line">
Built using
<a href="https://github.com/elixir-lang/ex_doc" title="ExDoc" rel="help" target="_blank">ExDoc</a> (v0.18.3),
</span>
<span class="line">
designed by
<a href="https://twitter.com/dignifiedquire" target="_blank" title="@dignifiedquire">Friedel Ziegelmayer</a>.
</span>
</p>
</footer>
</div>
</div>
</section>
</div>
<script src="dist/app-9bd040e5e5.js"></script>
</body>
</html>

View File

@ -0,0 +1,396 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="ExDoc v0.18.3">
<title>POABackend.CustomHandler.REST poa_backend v0.1.0</title>
<link rel="stylesheet" href="dist/app-480ffdc169.css" />
<script src="dist/sidebar_items-ffeb4f1e51.js"></script>
</head>
<body data-type="modules">
<script>try { if(localStorage.getItem('night-mode')) document.body.className += ' night-mode'; } catch (e) { }</script>
<div class="main">
<button class="sidebar-button sidebar-toggle">
<span class="icon-menu" aria-hidden="true"></span>
<span class="sr-only">Toggle Sidebar</span>
</button>
<button class="sidebar-button night-mode-toggle">
<span class="icon-theme" aria-hidden="true"></span>
<span class="sr-only">Toggle Theme</span>
</button>
<section class="sidebar">
<a href="api-reference.html" class="sidebar-projectLink">
<div class="sidebar-projectDetails">
<h1 class="sidebar-projectName">
poa_backend
</h1>
<h2 class="sidebar-projectVersion">
v0.1.0
</h2>
</div>
</a>
<form class="sidebar-search" action="search.html">
<button type="submit" class="search-button">
<span class="icon-search" aria-hidden="true"></span>
</button>
<input name="q" type="text" id="search-list" class="search-input" placeholder="Search" aria-label="Search" autocomplete="off" />
</form>
<ul class="sidebar-listNav">
<li><a id="extras-list" href="#full-list">Pages</a></li>
<li><a id="modules-list" href="#full-list">Modules</a></li>
</ul>
<div class="gradient"></div>
<ul id="full-list" class="sidebar-fullList"></ul>
</section>
<section class="content">
<div class="content-outer">
<div id="content" class="content-inner">
<h1>
<small class="visible-xs">poa_backend v0.1.0</small>
POABackend.CustomHandler.REST
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/custom_handler/rest.ex#L1" title="View Source" class="view-source" rel="help">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
</h1>
<section id="moduledoc">
<p>This module implements the REST Custom Handler over HTTP/1.1.</p>
<h1>Plugin Architecture</h1>
<p>This plugin involves many processes. When the <code class="inline">POABackend.CustomHandler.Supervisor</code> calls the
<code class="inline">child_spec/2</code> function it will create its own supervision tree under that supervisor</p>
<p><img src="./REST_architecture.png" alt="REST plugin Architecture"/></p>
<ul>
<li><code class="inline">POABackend.CustomHandler.REST.Supervisor</code> is the main supervisor. It is in charge of supervise its three
children.
</li>
<li>The <code class="inline">Ranch/Cowboy</code> branch is managed by Ranch and Cowboy apps. They are in charge of expose the REST endpoints on top
of http.
</li>
<li>The Registry is an Elixir Registry in charge of track/untrack Activity Monitor Servers, created by the next child
</li>
<li><code class="inline">POABackend.CustomHandler.REST.Monitor.Supervisor</code> is a Supervisor with <code class="inline">:simple_one_for_one</code> strategy. It will start
dynamically <a href="https://hexdocs.pm/elixir/GenServer.html"><code class="inline">GenServer</code></a>s implemented by <code class="inline">POABackend.CustomHandler.REST.Monitor.Server</code> module.
</li>
</ul>
<h1>REST endpoints</h1>
<p>This Pluting also defines the endpoints needed to use the POA Protocol.</p>
<h2 id="module-ping-endpoint" class="section-heading">
<a href="#module-ping-endpoint" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
<em>ping</em> endpoint
</h2>
<pre><code class="elixir">POST /ping</code></pre>
<p>request:</p>
<pre><code class="elixir">Headers: {&quot;content-type&quot;, &quot;application/json&quot;}
payload:
{
id: String() # agent id
secret: String() # secret string for authentication/authorisation
}</code></pre>
<p>responses:</p>
<table>
<colgroup>
<col>
<col>
</colgroup>
<thead>
<tr>
<th style="text-align: left">Code</th><th style="text-align: left">Description</th>
</tr>
</thead>
<tr>
<td style="text-align: left">200</td><td style="text-align: left">Success <em>{“result”:”success”}</em></td>
</tr>
<tr>
<td style="text-align: left">401</td><td style="text-align: left">Unauthorized</td>
</tr>
<tr>
<td style="text-align: left">415</td><td style="text-align: left">Unsupported Media Type (only <em>application/json</em> allowed)</td>
</tr>
<tr>
<td style="text-align: left">422</td><td style="text-align: left">Unprocessable Entity. Required fields missing</td>
</tr>
</table>
<p>Example:</p>
<pre><code class="elixir">curl -v -d &#39;{&quot;id&quot;:&quot;agentID&quot;, &quot;secret&quot;:&quot;mysecret&quot;}&#39; -H &quot;Content-Type: application/json&quot; -X POST http://localhost:4002/ping
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 4002 (#0)
&gt; POST /ping HTTP/1.1
&gt; Host: localhost:4002
&gt; User-Agent: curl/7.53.1
&gt; Accept: */*
&gt; Content-Type: application/json
&gt; Content-Length: 37
&gt;
* upload completely sent off: 37 out of 37 bytes
&lt; HTTP/1.1 200 OK
&lt; server: Cowboy
&lt; date: Fri, 08 Jun 2018 13:27:58 GMT
&lt; content-length: 20
&lt; cache-control: max-age=0, private, must-revalidate
&lt; content-type: application/json; charset=utf-8
&lt;
* Connection #0 to host localhost left intact
{&quot;result&quot;:&quot;success&quot;}</code></pre>
<h2 id="module-data-endpoint" class="section-heading">
<a href="#module-data-endpoint" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
<em>data</em> endpoint
</h2>
<pre><code class="elixir">POST /data</code></pre>
<p>request:</p>
<pre><code class="elixir">Headers: {&quot;content-type&quot;, &quot;application/json&quot;}
payload:
{
id: String() # agent id
secret: String() # secret string for authentication/authorisation
type: String() # data type (for now only ethereum_metrics)
data: Object() # metric data itself
}</code></pre>
<p>responses:</p>
<table>
<colgroup>
<col>
<col>
</colgroup>
<thead>
<tr>
<th style="text-align: left">Code</th><th style="text-align: left">Description</th>
</tr>
</thead>
<tr>
<td style="text-align: left">200</td><td style="text-align: left">Success <em>{“result”:”success”}</em></td>
</tr>
<tr>
<td style="text-align: left">401</td><td style="text-align: left">Unauthorized</td>
</tr>
<tr>
<td style="text-align: left">415</td><td style="text-align: left">Unsupported Media Type (only <em>application/json</em> allowed)</td>
</tr>
<tr>
<td style="text-align: left">422</td><td style="text-align: left">Unprocessable Entity. Required fields missing</td>
</tr>
</table>
<p>Example:</p>
<pre><code class="elixir">curl -v -d &#39;{&quot;id&quot;:&quot;agentID&quot;, &quot;secret&quot;:&quot;mysecret&quot;, &quot;type&quot;:&quot;ethereum_metrics&quot;, &quot;data&quot;:{&quot;hello&quot;:&quot;world&quot;}}&#39; -H &quot;Content-Type: application/json&quot; -X POST http://localhost:4002/data
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 4002 (#0)
&gt; POST /data HTTP/1.1
&gt; Host: localhost:4002
&gt; User-Agent: curl/7.53.1
&gt; Accept: */*
&gt; Content-Type: application/json
&gt; Content-Length: 90
&gt;
* upload completely sent off: 90 out of 90 bytes
&lt; HTTP/1.1 200 OK
&lt; server: Cowboy
&lt; date: Fri, 08 Jun 2018 16:02:22 GMT
&lt; content-length: 20
&lt; cache-control: max-age=0, private, must-revalidate
&lt; content-type: application/json; charset=utf-8
&lt;
* Connection #0 to host localhost left intact
{&quot;result&quot;:&quot;success&quot;}</code></pre>
<h2 id="module-bye-endpoint" class="section-heading">
<a href="#module-bye-endpoint" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
<em>bye</em> endpoint
</h2>
<pre><code class="elixir">POST /bye</code></pre>
<p>request:</p>
<pre><code class="elixir">Headers: {&quot;content-type&quot;, &quot;application/json&quot;}
payload:
{
id: String() # agent id
secret: String() # secret string for authentication/authorisation
}</code></pre>
<p>responses:</p>
<table>
<colgroup>
<col>
<col>
</colgroup>
<thead>
<tr>
<th style="text-align: left">Code</th><th style="text-align: left">Description</th>
</tr>
</thead>
<tr>
<td style="text-align: left">200</td><td style="text-align: left">Success <em>{“result”:”success”}</em></td>
</tr>
<tr>
<td style="text-align: left">401</td><td style="text-align: left">Unauthorized</td>
</tr>
<tr>
<td style="text-align: left">415</td><td style="text-align: left">Unsupported Media Type (only <em>application/json</em> allowed)</td>
</tr>
<tr>
<td style="text-align: left">422</td><td style="text-align: left">Unprocessable Entity. Required fields missing</td>
</tr>
</table>
<p>Example:</p>
<pre><code class="elixir">curl -v -d &#39;{&quot;id&quot;:&quot;agentID&quot;, &quot;secret&quot;:&quot;mysecret&quot;}&#39; -H &quot;Content-Type: application/json&quot; -X POST http://localhost:4002/bye
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 4002 (#0)
&gt; POST /bye HTTP/1.1
&gt; Host: localhost:4002
&gt; User-Agent: curl/7.53.1
&gt; Accept: */*
&gt; Content-Type: application/json
&gt; Content-Length: 37
&gt;
* upload completely sent off: 37 out of 37 bytes
&lt; HTTP/1.1 200 OK
&lt; server: Cowboy
&lt; date: Fri, 08 Jun 2018 15:49:05 GMT
&lt; content-length: 20
&lt; cache-control: max-age=0, private, must-revalidate
&lt; content-type: application/json; charset=utf-8
&lt;
* Connection #0 to host localhost left intact
{&quot;result&quot;:&quot;success&quot;}
</code></pre>
</section>
<section id="summary" class="details-list">
<h1 class="section-heading">
<a class="hover-link" href="#summary">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this section</span>
</a>
Summary
</h1>
<div class="summary-functions summary">
<h2>
<a href="#functions">Functions</a>
</h2>
<div class="summary-row">
<div class="summary-signature">
<a href="#ping_monitor/1">ping_monitor(agent_id)</a>
</div>
<div class="summary-synopsis"><p>This function will initialize an Activity Monitor Server for a given Agent ID if it doesnt
exist already. If it exist this function will send a ping message to the Monitor Server in order to
restart the timeout countdown</p>
</div>
</div>
</div>
</section>
<section id="functions" class="details-list">
<h1 class="section-heading">
<a class="hover-link" href="#functions">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this section</span>
</a>
Functions
</h1>
<div class="detail" id="ping_monitor/1">
<div class="detail-header">
<a href="#ping_monitor/1" class="detail-link" title="Link to this function">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this function</span>
</a>
<span class="signature">ping_monitor(agent_id)</span>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/custom_handler/rest.ex#L274" class="view-source" rel="help" title="View Source">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
</div>
<section class="docstring">
<p>This function will initialize an Activity Monitor Server for a given Agent ID if it doesnt
exist already. If it exist this function will send a ping message to the Monitor Server in order to
restart the timeout countdown.</p>
<p>The Activity Monitor Server is a <a href="https://hexdocs.pm/elixir/GenServer.html"><code class="inline">GenServer</code></a> which will be initialized under the
<code class="inline">POABackend.CustomHandler.REST.Monitor.Supervisor</code> supervisor.</p>
</section>
</div>
</section>
<footer class="footer">
<p>
<span class="line">
Built using
<a href="https://github.com/elixir-lang/ex_doc" title="ExDoc" rel="help" target="_blank">ExDoc</a> (v0.18.3),
</span>
<span class="line">
designed by
<a href="https://twitter.com/dignifiedquire" target="_blank" title="@dignifiedquire">Friedel Ziegelmayer</a>.
</span>
</p>
</footer>
</div>
</div>
</section>
</div>
<script src="dist/app-9bd040e5e5.js"></script>
</body>
</html>

View File

@ -0,0 +1,330 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="ExDoc v0.18.3">
<title>POABackend.CustomHandler poa_backend v0.1.0</title>
<link rel="stylesheet" href="dist/app-480ffdc169.css" />
<script src="dist/sidebar_items-ffeb4f1e51.js"></script>
</head>
<body data-type="modules">
<script>try { if(localStorage.getItem('night-mode')) document.body.className += ' night-mode'; } catch (e) { }</script>
<div class="main">
<button class="sidebar-button sidebar-toggle">
<span class="icon-menu" aria-hidden="true"></span>
<span class="sr-only">Toggle Sidebar</span>
</button>
<button class="sidebar-button night-mode-toggle">
<span class="icon-theme" aria-hidden="true"></span>
<span class="sr-only">Toggle Theme</span>
</button>
<section class="sidebar">
<a href="api-reference.html" class="sidebar-projectLink">
<div class="sidebar-projectDetails">
<h1 class="sidebar-projectName">
poa_backend
</h1>
<h2 class="sidebar-projectVersion">
v0.1.0
</h2>
</div>
</a>
<form class="sidebar-search" action="search.html">
<button type="submit" class="search-button">
<span class="icon-search" aria-hidden="true"></span>
</button>
<input name="q" type="text" id="search-list" class="search-input" placeholder="Search" aria-label="Search" autocomplete="off" />
</form>
<ul class="sidebar-listNav">
<li><a id="extras-list" href="#full-list">Pages</a></li>
<li><a id="modules-list" href="#full-list">Modules</a></li>
</ul>
<div class="gradient"></div>
<ul id="full-list" class="sidebar-fullList"></ul>
</section>
<section class="content">
<div class="content-outer">
<div id="content" class="content-inner">
<h1>
<small class="visible-xs">poa_backend v0.1.0</small>
POABackend.CustomHandler <small>behaviour</small>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/custom_handler.ex#L1" title="View Source" class="view-source" rel="help">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
</h1>
<section id="moduledoc">
<p>A Custom Handler is responsible of handling data sent from Agents (i.e. REST over HTTP, WebSockets…) “speaking” the POA Protocol.</p>
<p>The main responsability is getting calls from Agents, transform the data into a <a href="POABackend.Protocol.Message.html#content">POABackend.Protocol.Message</a>
Struct and sending it to the receivers.</p>
<h3 id="module-writing-your-custom-handler" class="section-heading">
<a href="#module-writing-your-custom-handler" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
Writing your custom Handler
</h3>
<p>You must to <em>use</em> the POABackend.CustomHandler module. That will requires you to implement the function <code class="inline">child_spec/1</code> which will be
called from the <code class="inline">POABackend.CustomHandler.Supervisor</code> and it must returns the child spec for the process you are going to spawn.</p>
<pre><code class="elixir">defmodule MyHandler do
use POABackend.CustomHandler
def child_spec(options) do
Plug.Adapters.Cowboy.child_spec(scheme: options[:scheme], plug: POABackend.CustomHandler.Rest.Router, options: [port: options[:port]])
end
end</code></pre>
<p>In this example we are initializing our CustomHandler for REST requests using the Cowboy Plug and defining the endpoints in the <code class="inline">POABackend.CustomHandler.Rest.Router</code>
module.</p>
<h3 id="module-configuring-the-handlers-in-the-config-file" class="section-heading">
<a href="#module-configuring-the-handlers-in-the-config-file" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
Configuring the handlers in the config file
</h3>
<p>So far we have created a Custom Handler but we didnt tell <code class="inline">poa_backend</code> to start it. In order to do it we have to define the new Handler in
the config file.</p>
<pre><code class="elixir">config :poa_backend,
:custom_handlers,
[
{:rest_custom_handler, POABackend.CustomHandler.Rest, [port: 4002]}
]</code></pre>
<p>Inside the <code class="inline">:custom_handlers</code> list we define the handlers we want to start. Each Handler is defined in a triple tuple where the first argument
is the id for that handler, the second one is the Elixir module which implements the CustomHandler behaviour and the third one is a list for arguments
which will be passed to the <code class="inline">child_spec/1</code> function as a parameter</p>
<h3 id="module-helpful-functions" class="section-heading">
<a href="#module-helpful-functions" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
Helpful functions
</h3>
<p>This module also define some helpful functions:</p>
<ul>
<li>send_to_receivers/1: This function will publish the incomming message to the appropiate metric type (Data Type). A Custom Handler must call it when it wants to dispatch a message.
</li>
<li>publish_inactive/1: Will publish an inactive message to all the metrics in the system. A Custom Handler must call it when detects if a client is disconnected or/and inactive
</li>
</ul>
</section>
<section id="summary" class="details-list">
<h1 class="section-heading">
<a class="hover-link" href="#summary">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this section</span>
</a>
Summary
</h1>
<div class="summary-functions summary">
<h2>
<a href="#functions">Functions</a>
</h2>
<div class="summary-row">
<div class="summary-signature">
<a href="#publish_inactive/1">publish_inactive(agent_id)</a>
</div>
<div class="summary-synopsis"><p>Publish an inactive message to all the metrics defined in the config file</p>
</div>
</div>
<div class="summary-row">
<div class="summary-signature">
<a href="#send_to_receivers/1">send_to_receivers(message)</a>
</div>
<div class="summary-synopsis"><p>This function dispatches the given Message to the appropiate receivers based on the Data Type (ie :ethereum_metric)</p>
</div>
</div>
</div>
<div class="summary-callbacks summary">
<h2>
<a href="#callbacks">Callbacks</a>
</h2>
<div class="summary-row">
<div class="summary-signature">
<a href="#c:child_spec/1">child_spec(options)</a>
</div>
<div class="summary-synopsis"><p>This function will be called from the <code class="inline">POABackend.CustomHandler.Supervisor</code> in order
to get the child specification for start the custom handler process</p>
</div>
</div>
</div>
</section>
<section id="functions" class="details-list">
<h1 class="section-heading">
<a class="hover-link" href="#functions">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this section</span>
</a>
Functions
</h1>
<div class="detail" id="publish_inactive/1">
<div class="detail-header">
<a href="#publish_inactive/1" class="detail-link" title="Link to this function">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this function</span>
</a>
<span class="signature">publish_inactive(agent_id)</span>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/custom_handler.ex#L82" class="view-source" rel="help" title="View Source">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
</div>
<section class="docstring">
<p>Publish an inactive message to all the metrics defined in the config file.</p>
<p>A Custom Handler must call this explicity when detecting if a client is inactive for a period of time</p>
</section>
</div>
<div class="detail" id="send_to_receivers/1">
<div class="detail-header">
<a href="#send_to_receivers/1" class="detail-link" title="Link to this function">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this function</span>
</a>
<span class="signature">send_to_receivers(message)</span>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/custom_handler.ex#L73" class="view-source" rel="help" title="View Source">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
<div class="specs">
<pre>send_to_receivers(<a href="POABackend.Protocol.Message.html#t:t/0">POABackend.Protocol.Message.t</a>()) :: :ok</pre>
</div>
</div>
<section class="docstring">
<p>This function dispatches the given Message to the appropiate receivers based on the Data Type (ie :ethereum_metric).</p>
<p>The mapping between Data Types and Receivers is done in the config file.</p>
<p><em>Note</em> the message must be a <a href="POABackend.Protocol.Message.html">POABackend.Protocol.Message</a> struct</p>
</section>
</div>
</section>
<section id="callbacks" class="details-list">
<h1 class="section-heading">
<a class="hover-link" href="#callbacks">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this section</span>
</a>
Callbacks
</h1>
<div class="detail" id="c:child_spec/1">
<div class="detail-header">
<a href="#c:child_spec/1" class="detail-link" title="Link to this callback">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this callback</span>
</a>
<span class="signature">child_spec(options)</span>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/custom_handler.ex#L57" class="view-source" rel="help" title="View Source">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
<div class="specs">
<pre>child_spec(options :: <a href="https://hexdocs.pm/elixir/typespecs.html#built-in-types">list</a>()) :: <a href="http://www.erlang.org/doc/man/supervisor.html#type-child_spec">:supervisor.child_spec</a>()</pre>
</div>
</div>
<section class="docstring">
<p>This function will be called from the <code class="inline">POABackend.CustomHandler.Supervisor</code> in order
to get the child specification for start the custom handler process.</p>
</section>
</div>
</section>
<footer class="footer">
<p>
<span class="line">
Built using
<a href="https://github.com/elixir-lang/ex_doc" title="ExDoc" rel="help" target="_blank">ExDoc</a> (v0.18.3),
</span>
<span class="line">
designed by
<a href="https://twitter.com/dignifiedquire" target="_blank" title="@dignifiedquire">Friedel Ziegelmayer</a>.
</span>
</p>
</footer>
</div>
</div>
</section>
</div>
<script src="dist/app-9bd040e5e5.js"></script>
</body>
</html>

View File

@ -0,0 +1,194 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="ExDoc v0.18.3">
<title>POABackend.Protocol.DataType poa_backend v0.1.0</title>
<link rel="stylesheet" href="dist/app-480ffdc169.css" />
<script src="dist/sidebar_items-ffeb4f1e51.js"></script>
</head>
<body data-type="modules">
<script>try { if(localStorage.getItem('night-mode')) document.body.className += ' night-mode'; } catch (e) { }</script>
<div class="main">
<button class="sidebar-button sidebar-toggle">
<span class="icon-menu" aria-hidden="true"></span>
<span class="sr-only">Toggle Sidebar</span>
</button>
<button class="sidebar-button night-mode-toggle">
<span class="icon-theme" aria-hidden="true"></span>
<span class="sr-only">Toggle Theme</span>
</button>
<section class="sidebar">
<a href="api-reference.html" class="sidebar-projectLink">
<div class="sidebar-projectDetails">
<h1 class="sidebar-projectName">
poa_backend
</h1>
<h2 class="sidebar-projectVersion">
v0.1.0
</h2>
</div>
</a>
<form class="sidebar-search" action="search.html">
<button type="submit" class="search-button">
<span class="icon-search" aria-hidden="true"></span>
</button>
<input name="q" type="text" id="search-list" class="search-input" placeholder="Search" aria-label="Search" autocomplete="off" />
</form>
<ul class="sidebar-listNav">
<li><a id="extras-list" href="#full-list">Pages</a></li>
<li><a id="modules-list" href="#full-list">Modules</a></li>
</ul>
<div class="gradient"></div>
<ul id="full-list" class="sidebar-fullList"></ul>
</section>
<section class="content">
<div class="content-outer">
<div id="content" class="content-inner">
<h1>
<small class="visible-xs">poa_backend v0.1.0</small>
POABackend.Protocol.DataType
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/protocol/data_type.ex#L1" title="View Source" class="view-source" rel="help">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
</h1>
<section id="moduledoc">
<p>The protocol messages Data type.</p>
<p>Only one Data type is supported now in the backend and it is the ethereum metric</p>
</section>
<section id="summary" class="details-list">
<h1 class="section-heading">
<a class="hover-link" href="#summary">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this section</span>
</a>
Summary
</h1>
<div class="summary-types summary">
<h2>
<a href="#types">Types</a>
</h2>
<div class="summary-row">
<div class="summary-signature">
<a href="#t:t/0">t()</a>
</div>
<div class="summary-synopsis"><p>The Message Data Type. For now only ethereum metrics allowed</p>
</div>
</div>
</div>
</section>
<section id="types" class="details-list">
<h1 class="section-heading">
<a class="hover-link" href="#types">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this section</span>
</a>
Types
</h1>
<div class="types-list">
<div class="detail" id="t:t/0">
<div class="detail-header">
<a href="#t:t/0" class="detail-link" title="Link to this type">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this type</span>
</a>
<span class="signature">t()</span>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/protocol/data_type.ex#L12" class="view-source" rel="help" title="View Source">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
<div class="specs">
<pre>t() :: :ethereum_metric</pre>
</div>
</div>
<section class="docstring">
<p>The Message Data Type. For now only ethereum metrics allowed</p>
</section>
</div>
</div>
</section>
<footer class="footer">
<p>
<span class="line">
Built using
<a href="https://github.com/elixir-lang/ex_doc" title="ExDoc" rel="help" target="_blank">ExDoc</a> (v0.18.3),
</span>
<span class="line">
designed by
<a href="https://twitter.com/dignifiedquire" target="_blank" title="@dignifiedquire">Friedel Ziegelmayer</a>.
</span>
</p>
</footer>
</div>
</div>
</section>
</div>
<script src="dist/app-9bd040e5e5.js"></script>
</body>
</html>

View File

@ -0,0 +1,370 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="ExDoc v0.18.3">
<title>POABackend.Protocol.Message poa_backend v0.1.0</title>
<link rel="stylesheet" href="dist/app-480ffdc169.css" />
<script src="dist/sidebar_items-ffeb4f1e51.js"></script>
</head>
<body data-type="modules">
<script>try { if(localStorage.getItem('night-mode')) document.body.className += ' night-mode'; } catch (e) { }</script>
<div class="main">
<button class="sidebar-button sidebar-toggle">
<span class="icon-menu" aria-hidden="true"></span>
<span class="sr-only">Toggle Sidebar</span>
</button>
<button class="sidebar-button night-mode-toggle">
<span class="icon-theme" aria-hidden="true"></span>
<span class="sr-only">Toggle Theme</span>
</button>
<section class="sidebar">
<a href="api-reference.html" class="sidebar-projectLink">
<div class="sidebar-projectDetails">
<h1 class="sidebar-projectName">
poa_backend
</h1>
<h2 class="sidebar-projectVersion">
v0.1.0
</h2>
</div>
</a>
<form class="sidebar-search" action="search.html">
<button type="submit" class="search-button">
<span class="icon-search" aria-hidden="true"></span>
</button>
<input name="q" type="text" id="search-list" class="search-input" placeholder="Search" aria-label="Search" autocomplete="off" />
</form>
<ul class="sidebar-listNav">
<li><a id="extras-list" href="#full-list">Pages</a></li>
<li><a id="modules-list" href="#full-list">Modules</a></li>
</ul>
<div class="gradient"></div>
<ul id="full-list" class="sidebar-fullList"></ul>
</section>
<section class="content">
<div class="content-outer">
<div id="content" class="content-inner">
<h1>
<small class="visible-xs">poa_backend v0.1.0</small>
POABackend.Protocol.Message
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/protocol/message.ex#L1" title="View Source" class="view-source" rel="help">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
</h1>
<section id="moduledoc">
<p>The message received from the Agent (inspired in <a href="https://hexdocs.pm/plug/Plug.Conn.html"><code class="inline">Plug.Conn</code></a>).</p>
<p>This module defines the Message received from the Agent and the main functions in order
to work with it.</p>
<h2 id="module-message-fields" class="section-heading">
<a href="#module-message-fields" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
Message Fields
</h2>
<ul>
<li><code class="inline">agent_id</code> - The Agent Id which sent the message to the backend.
</li>
<li><code class="inline">data_type</code> - The kind of data the message is carring. For now only <code class="inline">ethereum_metric</code> type is defined.
</li>
<li><code class="inline">message_type</code> - This is the message type according to the custom protocol. Only <code class="inline">data</code> and <code class="inline">bye</code> are defined for now
</li>
<li><code class="inline">assigns</code> - Shared user data as a map
</li>
<li><code class="inline">data</code> - The message payloda. It is a map
</li>
</ul>
</section>
<section id="summary" class="details-list">
<h1 class="section-heading">
<a class="hover-link" href="#summary">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this section</span>
</a>
Summary
</h1>
<div class="summary-types summary">
<h2>
<a href="#types">Types</a>
</h2>
<div class="summary-row">
<div class="summary-signature">
<a href="#t:t/0">t()</a>
</div>
<div class="summary-synopsis"><p>The Message struct</p>
</div>
</div>
</div>
<div class="summary-functions summary">
<h2>
<a href="#functions">Functions</a>
</h2>
<div class="summary-row">
<div class="summary-signature">
<a href="#assign/3">assign(message, key, value)</a>
</div>
<div class="summary-synopsis"><p>Assigns a value to a key in the connection</p>
</div>
</div>
<div class="summary-row">
<div class="summary-signature">
<a href="#new/0">new()</a>
</div>
<div class="summary-synopsis"><p>Returns a new Message Struct</p>
</div>
</div>
<div class="summary-row">
<div class="summary-signature">
<a href="#new/4">new(agent_id, data_type, message_type, data)</a>
</div>
<div class="summary-synopsis"><p>Returns a new Message Struct initialized.
The params in order are: agent_id, data_type, message_type and data</p>
</div>
</div>
</div>
</section>
<section id="types" class="details-list">
<h1 class="section-heading">
<a class="hover-link" href="#types">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this section</span>
</a>
Types
</h1>
<div class="types-list">
<div class="detail" id="t:t/0">
<div class="detail-header">
<a href="#t:t/0" class="detail-link" title="Link to this type">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this type</span>
</a>
<span class="signature">t()</span>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/protocol/message.ex#L35" class="view-source" rel="help" title="View Source">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
<div class="specs">
<pre>t() :: %POABackend.Protocol.Message{
agent_id: <a href="https://hexdocs.pm/elixir/String.html#t:t/0">String.t</a>() | nil,
assigns: %{optional(<a href="https://hexdocs.pm/elixir/typespecs.html#basic-types">atom</a>()) => <a href="https://hexdocs.pm/elixir/typespecs.html#basic-types">any</a>()},
data: <a href="https://hexdocs.pm/elixir/Map.html#t:t/0">Map.t</a>() | nil,
data_type: POABackend.CustomProtocol.DataType.t() | nil,
message_type: POABackend.CustomProtocol.MessageType.t() | nil
}</pre>
</div>
</div>
<section class="docstring">
<p>The Message struct.</p>
<p>That keeps all the message data and metadata</p>
</section>
</div>
</div>
</section>
<section id="functions" class="details-list">
<h1 class="section-heading">
<a class="hover-link" href="#functions">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this section</span>
</a>
Functions
</h1>
<div class="detail" id="assign/3">
<div class="detail-header">
<a href="#assign/3" class="detail-link" title="Link to this function">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this function</span>
</a>
<span class="signature">assign(message, key, value)</span>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/protocol/message.ex#L78" class="view-source" rel="help" title="View Source">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
<div class="specs">
<pre>assign(<a href="#t:t/0">t</a>(), <a href="https://hexdocs.pm/elixir/typespecs.html#basic-types">atom</a>(), <a href="https://hexdocs.pm/elixir/typespecs.html#built-in-types">term</a>()) :: <a href="#t:t/0">t</a>()</pre>
</div>
</div>
<section class="docstring">
<p>Assigns a value to a key in the connection.</p>
<h2 id="assign/3-examples" class="section-heading">
<a href="#assign/3-examples" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
Examples
</h2>
<pre><code class="iex elixir">iex&gt; alias POABackend.Protocol.Message
iex&gt; message = Message.new()
iex&gt; message.assigns[:hello]
nil
iex&gt; message = Message.assign(message, :hello, :world)
iex&gt; message.assigns[:hello]
:world</code></pre>
</section>
</div>
<div class="detail" id="new/0">
<div class="detail-header">
<a href="#new/0" class="detail-link" title="Link to this function">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this function</span>
</a>
<span class="signature">new()</span>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/protocol/message.ex#L47" class="view-source" rel="help" title="View Source">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
<div class="specs">
<pre>new() :: <a href="#t:t/0">t</a>()</pre>
</div>
</div>
<section class="docstring">
<p>Returns a new Message Struct</p>
</section>
</div>
<div class="detail" id="new/4">
<div class="detail-header">
<a href="#new/4" class="detail-link" title="Link to this function">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this function</span>
</a>
<span class="signature">new(agent_id, data_type, message_type, data)</span>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/protocol/message.ex#L56" class="view-source" rel="help" title="View Source">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
<div class="specs">
<pre>new(
<a href="https://hexdocs.pm/elixir/String.html#t:t/0">String.t</a>(),
POABackend.CustomProtocol.DataType.t(),
POABackend.CustomProtocol.MessageType.t(),
<a href="https://hexdocs.pm/elixir/Map.html#t:t/0">Map.t</a>()
) :: <a href="#t:t/0">t</a>()</pre>
</div>
</div>
<section class="docstring">
<p>Returns a new Message Struct initialized.
The params in order are: agent_id, data_type, message_type and data</p>
</section>
</div>
</section>
<footer class="footer">
<p>
<span class="line">
Built using
<a href="https://github.com/elixir-lang/ex_doc" title="ExDoc" rel="help" target="_blank">ExDoc</a> (v0.18.3),
</span>
<span class="line">
designed by
<a href="https://twitter.com/dignifiedquire" target="_blank" title="@dignifiedquire">Friedel Ziegelmayer</a>.
</span>
</p>
</footer>
</div>
</div>
</section>
</div>
<script src="dist/app-9bd040e5e5.js"></script>
</body>
</html>

View File

@ -0,0 +1,201 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="ExDoc v0.18.3">
<title>POABackend.Protocol.MessageType poa_backend v0.1.0</title>
<link rel="stylesheet" href="dist/app-480ffdc169.css" />
<script src="dist/sidebar_items-ffeb4f1e51.js"></script>
</head>
<body data-type="modules">
<script>try { if(localStorage.getItem('night-mode')) document.body.className += ' night-mode'; } catch (e) { }</script>
<div class="main">
<button class="sidebar-button sidebar-toggle">
<span class="icon-menu" aria-hidden="true"></span>
<span class="sr-only">Toggle Sidebar</span>
</button>
<button class="sidebar-button night-mode-toggle">
<span class="icon-theme" aria-hidden="true"></span>
<span class="sr-only">Toggle Theme</span>
</button>
<section class="sidebar">
<a href="api-reference.html" class="sidebar-projectLink">
<div class="sidebar-projectDetails">
<h1 class="sidebar-projectName">
poa_backend
</h1>
<h2 class="sidebar-projectVersion">
v0.1.0
</h2>
</div>
</a>
<form class="sidebar-search" action="search.html">
<button type="submit" class="search-button">
<span class="icon-search" aria-hidden="true"></span>
</button>
<input name="q" type="text" id="search-list" class="search-input" placeholder="Search" aria-label="Search" autocomplete="off" />
</form>
<ul class="sidebar-listNav">
<li><a id="extras-list" href="#full-list">Pages</a></li>
<li><a id="modules-list" href="#full-list">Modules</a></li>
</ul>
<div class="gradient"></div>
<ul id="full-list" class="sidebar-fullList"></ul>
</section>
<section class="content">
<div class="content-outer">
<div id="content" class="content-inner">
<h1>
<small class="visible-xs">poa_backend v0.1.0</small>
POABackend.Protocol.MessageType
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/protocol/message_type.ex#L1" title="View Source" class="view-source" rel="help">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
</h1>
<section id="moduledoc">
<p>Regarding the POA Protocol only 2 types of message can be processed in the backend.</p>
<p>Those message types are</p>
<ul>
<li><code class="inline">data</code> - When data is sent to the backend. Data is also called “metric data”
</li>
<li><code class="inline">bye</code> - When the client wants to stop the communication
</li>
</ul>
<p><strong>NOTE</strong> New message types can be added in future while the protocol is extended</p>
</section>
<section id="summary" class="details-list">
<h1 class="section-heading">
<a class="hover-link" href="#summary">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this section</span>
</a>
Summary
</h1>
<div class="summary-types summary">
<h2>
<a href="#types">Types</a>
</h2>
<div class="summary-row">
<div class="summary-signature">
<a href="#t:t/0">t()</a>
</div>
<div class="summary-synopsis"><p>The message type. Only <code class="inline">data</code> and <code class="inline">bye</code> are allowed</p>
</div>
</div>
</div>
</section>
<section id="types" class="details-list">
<h1 class="section-heading">
<a class="hover-link" href="#types">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this section</span>
</a>
Types
</h1>
<div class="types-list">
<div class="detail" id="t:t/0">
<div class="detail-header">
<a href="#t:t/0" class="detail-link" title="Link to this type">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this type</span>
</a>
<span class="signature">t()</span>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/protocol/message_type.ex#L18" class="view-source" rel="help" title="View Source">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
<div class="specs">
<pre>t() :: :data | :bye</pre>
</div>
</div>
<section class="docstring">
<p>The message type. Only <code class="inline">data</code> and <code class="inline">bye</code> are allowed</p>
</section>
</div>
</div>
</section>
<footer class="footer">
<p>
<span class="line">
Built using
<a href="https://github.com/elixir-lang/ex_doc" title="ExDoc" rel="help" target="_blank">ExDoc</a> (v0.18.3),
</span>
<span class="line">
designed by
<a href="https://twitter.com/dignifiedquire" target="_blank" title="@dignifiedquire">Friedel Ziegelmayer</a>.
</span>
</p>
</footer>
</div>
</div>
</section>
</div>
<script src="dist/app-9bd040e5e5.js"></script>
</body>
</html>

View File

@ -0,0 +1,179 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="ExDoc v0.18.3">
<title>POABackend.Protocol poa_backend v0.1.0</title>
<link rel="stylesheet" href="dist/app-480ffdc169.css" />
<script src="dist/sidebar_items-ffeb4f1e51.js"></script>
</head>
<body data-type="modules">
<script>try { if(localStorage.getItem('night-mode')) document.body.className += ' night-mode'; } catch (e) { }</script>
<div class="main">
<button class="sidebar-button sidebar-toggle">
<span class="icon-menu" aria-hidden="true"></span>
<span class="sr-only">Toggle Sidebar</span>
</button>
<button class="sidebar-button night-mode-toggle">
<span class="icon-theme" aria-hidden="true"></span>
<span class="sr-only">Toggle Theme</span>
</button>
<section class="sidebar">
<a href="api-reference.html" class="sidebar-projectLink">
<div class="sidebar-projectDetails">
<h1 class="sidebar-projectName">
poa_backend
</h1>
<h2 class="sidebar-projectVersion">
v0.1.0
</h2>
</div>
</a>
<form class="sidebar-search" action="search.html">
<button type="submit" class="search-button">
<span class="icon-search" aria-hidden="true"></span>
</button>
<input name="q" type="text" id="search-list" class="search-input" placeholder="Search" aria-label="Search" autocomplete="off" />
</form>
<ul class="sidebar-listNav">
<li><a id="extras-list" href="#full-list">Pages</a></li>
<li><a id="modules-list" href="#full-list">Modules</a></li>
</ul>
<div class="gradient"></div>
<ul id="full-list" class="sidebar-fullList"></ul>
</section>
<section class="content">
<div class="content-outer">
<div id="content" class="content-inner">
<h1>
<small class="visible-xs">poa_backend v0.1.0</small>
POABackend.Protocol
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/protocol.ex#L1" title="View Source" class="view-source" rel="help">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
</h1>
<section id="moduledoc">
<h2 id="module-poa-protocol" class="section-heading">
<a href="#module-poa-protocol" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
POA Protocol
</h2>
<p>This protocol defines the communication between the Agents and the POA Backend.</p>
<p><img src="./backend_architecture.png" alt="POA Backend Architecture"/></p>
<h3 id="module-basic-calls" class="section-heading">
<a href="#module-basic-calls" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
Basic calls
</h3>
<p>Only those calls are allowed:</p>
<ul>
<li>session (<em>not implemented</em>) - In future in order to add authentication / authorization
</li>
<li>ping - Ping message
</li>
<li>data - Specific message for a given receiver. It can be a metric itself or something else
</li>
<li>bye - Message sent when the Agent wants to close the communication explicitly
</li>
</ul>
<h4>ping call</h4>
<p>abstract request:</p>
<pre><code class="json">{
id: String() # agent id
secret: String() # secret string for authentication/authorisation
}</code></pre>
<p>response:</p>
<pre><code class="json">
{
result: String() # “success” or “error”
payload: String() # optional payload
}</code></pre>
<h4>data call</h4>
<p>abstract request:</p>
<pre><code class="json">{
id: String() # agent id
secret: String() # secret string for authentication/authorisation
type: String() # data type (for now only ethereum_metrics)
data: Object() # metric data itself
}</code></pre>
<p>response:</p>
<pre><code class="json">
{
result: String() # “success” or “error”
payload: String() # optional payload
}</code></pre>
<h4>bye call</h4>
<p>abstract request:</p>
<pre><code class="json">{
id: String() # agent id
secret: String() # secret string for authentication/authorisation
}</code></pre>
<p>response:</p>
<pre><code class="json">
{
result: String() # “success” or “error”
payload: String() # optional payload
}</code></pre>
</section>
<footer class="footer">
<p>
<span class="line">
Built using
<a href="https://github.com/elixir-lang/ex_doc" title="ExDoc" rel="help" target="_blank">ExDoc</a> (v0.18.3),
</span>
<span class="line">
designed by
<a href="https://twitter.com/dignifiedquire" target="_blank" title="@dignifiedquire">Friedel Ziegelmayer</a>.
</span>
</p>
</footer>
</div>
</div>
</section>
</div>
<script src="dist/app-9bd040e5e5.js"></script>
</body>
</html>

View File

@ -0,0 +1,445 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="ExDoc v0.18.3">
<title>POABackend.Receiver poa_backend v0.1.0</title>
<link rel="stylesheet" href="dist/app-480ffdc169.css" />
<script src="dist/sidebar_items-ffeb4f1e51.js"></script>
</head>
<body data-type="modules">
<script>try { if(localStorage.getItem('night-mode')) document.body.className += ' night-mode'; } catch (e) { }</script>
<div class="main">
<button class="sidebar-button sidebar-toggle">
<span class="icon-menu" aria-hidden="true"></span>
<span class="sr-only">Toggle Sidebar</span>
</button>
<button class="sidebar-button night-mode-toggle">
<span class="icon-theme" aria-hidden="true"></span>
<span class="sr-only">Toggle Theme</span>
</button>
<section class="sidebar">
<a href="api-reference.html" class="sidebar-projectLink">
<div class="sidebar-projectDetails">
<h1 class="sidebar-projectName">
poa_backend
</h1>
<h2 class="sidebar-projectVersion">
v0.1.0
</h2>
</div>
</a>
<form class="sidebar-search" action="search.html">
<button type="submit" class="search-button">
<span class="icon-search" aria-hidden="true"></span>
</button>
<input name="q" type="text" id="search-list" class="search-input" placeholder="Search" aria-label="Search" autocomplete="off" />
</form>
<ul class="sidebar-listNav">
<li><a id="extras-list" href="#full-list">Pages</a></li>
<li><a id="modules-list" href="#full-list">Modules</a></li>
</ul>
<div class="gradient"></div>
<ul id="full-list" class="sidebar-fullList"></ul>
</section>
<section class="content">
<div class="content-outer">
<div id="content" class="content-inner">
<h1>
<small class="visible-xs">poa_backend v0.1.0</small>
POABackend.Receiver <small>behaviour</small>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/receiver.ex#L1" title="View Source" class="view-source" rel="help">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
</h1>
<section id="moduledoc">
<p>Defines a Receiver Plugin.</p>
<p>A Receiver plugin will run in an independent process and will run the <code class="inline">metrics_received/3</code>
function every time it receives a metric from the agents.</p>
<p><a href="POABackend.html"><code class="inline">POABackend</code></a> app reads the Receivers configuration from the <code class="inline">config.exs</code> file when bootstrap and will create a
process per each one of them. That configuration is referenced by :receivers key.</p>
<pre><code class="elixir">config :poa_backend,
:receivers,
[
{name, module, args}
]</code></pre>
<p>for example</p>
<pre><code class="elixir">config :poa_backend,
:receivers,
[
{:my_receiver, POABackend.Receivers.MyReceiver, [host: &quot;localhost&quot;, port: 1234]}
]</code></pre>
<p><code class="inline">name</code>, <code class="inline">module</code> and <code class="inline">args</code> must be defined in the configuration file.</p>
<ul>
<li><code class="inline">name</code>: Name for the new created process. Must be unique
</li>
<li><code class="inline">module</code>: Module which implements the Receiver behaviour
</li>
<li><code class="inline">args</code>: Initial args which will be passed to the <code class="inline">init_receiver/1</code> function
</li>
</ul>
<p>The Receivers mechanism is built on top of <a href="https://hexdocs.pm/gen_stage/GenStage.html">GenStage</a>. Receivers are Consumers (sinks) and they must
be subscribed to one or more Producers. The Producers are the Metric types (i.e. <code class="inline">ethereum_metrics</code>) and are defined in the config file too:</p>
<pre><code class="elixir">config :poa_backend,
:metrics,
[
:ethereum_metrics
]</code></pre>
<p>In order to work properly we have to define in the configuration file the relation between the Receiver
and the Metric types it wants to receive. </p>
<pre><code class="elixir">config :poa_backend,
:subscriptions,
[
{receiver_name, [metric_type1, metric_type2]}
]</code></pre>
<p>for example</p>
<pre><code class="elixir">config :poa_backend,
:subscriptions,
[
{:my_receiver, [:ethereum_metrics]}
]</code></pre>
<h2 id="module-implementing-a-receiver-plugin" class="section-heading">
<a href="#module-implementing-a-receiver-plugin" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
Implementing A Receiver Plugin
</h2>
<p>In order to implement your Receiver Plugin you must implement 3 functions.</p>
<ul>
<li><code class="inline">init_receiver/1</code>: Called only once when the process starts
</li>
<li><code class="inline">metrics_received/3</code>: This function is called eveytime the Producer (metric type) receives a message.
</li>
<li><code class="inline">handle_message/1</code>: This is called when the Receiver process receives an Erlang message
</li>
<li><code class="inline">handle_inactive/2</code>: This function is called when one client has been disconnected or is not active for a period of time.
</li>
<li><code class="inline">terminate/1</code>: Called just before stopping the process
</li>
</ul>
<p>This is a simple example of custom Receiver Plugin</p>
<pre><code class="elixir">defmodule POABackend.Receivers.MyReceiver do
use POABackend.Receiver
def init_receiver(_args) do
{:ok, :no_state}
end
def metrics_received(metrics, from, state) do
for metric &lt;- metrics do
IO.puts &quot;metric received&quot;
end
{:ok, state}
end
def handle_message(_message, state) do
{:ok, state}
end
def handle_inactive(agent_id, state) do
{:ok, state}
end
def terminate(_state) do
:ok
end
end</code></pre>
</section>
<section id="summary" class="details-list">
<h1 class="section-heading">
<a class="hover-link" href="#summary">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this section</span>
</a>
Summary
</h1>
<div class="summary-callbacks summary">
<h2>
<a href="#callbacks">Callbacks</a>
</h2>
<div class="summary-row">
<div class="summary-signature">
<a href="#c:handle_inactive/2">handle_inactive(agent_id, state)</a>
</div>
<div class="summary-synopsis"><p>This function is called when a Custom Handler detects a client is inactive</p>
</div>
</div>
<div class="summary-row">
<div class="summary-signature">
<a href="#c:handle_message/2">handle_message(msg, state)</a>
</div>
<div class="summary-synopsis"><p>In this callback is called when the Receiver process receives an erlang message</p>
</div>
</div>
<div class="summary-row">
<div class="summary-signature">
<a href="#c:init_receiver/1">init_receiver(args)</a>
</div>
<div class="summary-synopsis"><p>A callback executed when the Receiver Plugin starts.
The argument is retrieved from the configuration file when the Receiver is defined
It must return <code class="inline">{:ok, state}</code>, that <code class="inline">state</code> will be keept as in <a href="https://hexdocs.pm/elixir/GenServer.html"><code class="inline">GenServer</code></a> and can be
retrieved in the <code class="inline">metrics_received/3</code> function</p>
</div>
</div>
<div class="summary-row">
<div class="summary-signature">
<a href="#c:metrics_received/3">metrics_received(metrics, from, state)</a>
</div>
<div class="summary-synopsis"><p>This callback will be called every time a message to the subscribed metric type arrives. It must
return the tuple <code class="inline">{:ok, state}</code></p>
</div>
</div>
<div class="summary-row">
<div class="summary-signature">
<a href="#c:terminate/1">terminate(state)</a>
</div>
<div class="summary-synopsis"><p>This callback is called just before the Process goes down. This is a good place for closing connections</p>
</div>
</div>
</div>
</section>
<section id="callbacks" class="details-list">
<h1 class="section-heading">
<a class="hover-link" href="#callbacks">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this section</span>
</a>
Callbacks
</h1>
<div class="detail" id="c:handle_inactive/2">
<div class="detail-header">
<a href="#c:handle_inactive/2" class="detail-link" title="Link to this callback">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this callback</span>
</a>
<span class="signature">handle_inactive(agent_id, state)</span>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/receiver.ex#L129" class="view-source" rel="help" title="View Source">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
<div class="specs">
<pre>handle_inactive(agent_id :: <a href="https://hexdocs.pm/elixir/typespecs.html#built-in-types">binary</a>(), state :: <a href="https://hexdocs.pm/elixir/typespecs.html#basic-types">any</a>()) :: {:ok, state :: <a href="https://hexdocs.pm/elixir/typespecs.html#basic-types">any</a>()}</pre>
</div>
</div>
<section class="docstring">
<p> This function is called when a Custom Handler detects a client is inactive.</p>
<p> The Custom Handler must to call explicity to <a href="POABackend.CustomHandler.html#publish_inactive/1"><code class="inline">POABackend.CustomHandler.publish_inactive/1</code></a> and it will publish the
<code class="inline">inactive</code> message to all the metrics in the system (defined in the config file).</p>
</section>
</div>
<div class="detail" id="c:handle_message/2">
<div class="detail-header">
<a href="#c:handle_message/2" class="detail-link" title="Link to this callback">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this callback</span>
</a>
<span class="signature">handle_message(msg, state)</span>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/receiver.ex#L120" class="view-source" rel="help" title="View Source">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
<div class="specs">
<pre>handle_message(msg :: <a href="https://hexdocs.pm/elixir/typespecs.html#basic-types">any</a>(), state :: <a href="https://hexdocs.pm/elixir/typespecs.html#basic-types">any</a>()) :: {:ok, state :: <a href="https://hexdocs.pm/elixir/typespecs.html#basic-types">any</a>()}</pre>
</div>
</div>
<section class="docstring">
<p> In this callback is called when the Receiver process receives an erlang message.</p>
<p> It must return <code class="inline">{:ok, state}</code>.</p>
</section>
</div>
<div class="detail" id="c:init_receiver/1">
<div class="detail-header">
<a href="#c:init_receiver/1" class="detail-link" title="Link to this callback">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this callback</span>
</a>
<span class="signature">init_receiver(args)</span>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/receiver.ex#L106" class="view-source" rel="help" title="View Source">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
<div class="specs">
<pre>init_receiver(args :: <a href="https://hexdocs.pm/elixir/typespecs.html#built-in-types">term</a>()) :: {:ok, state :: <a href="https://hexdocs.pm/elixir/typespecs.html#basic-types">any</a>()}</pre>
</div>
</div>
<section class="docstring">
<p> A callback executed when the Receiver Plugin starts.
The argument is retrieved from the configuration file when the Receiver is defined
It must return <code class="inline">{:ok, state}</code>, that <code class="inline">state</code> will be keept as in <a href="https://hexdocs.pm/elixir/GenServer.html"><code class="inline">GenServer</code></a> and can be
retrieved in the <code class="inline">metrics_received/3</code> function.</p>
</section>
</div>
<div class="detail" id="c:metrics_received/3">
<div class="detail-header">
<a href="#c:metrics_received/3" class="detail-link" title="Link to this callback">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this callback</span>
</a>
<span class="signature">metrics_received(metrics, from, state)</span>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/receiver.ex#L113" class="view-source" rel="help" title="View Source">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
<div class="specs">
<pre>metrics_received(metrics :: [<a href="https://hexdocs.pm/elixir/typespecs.html#built-in-types">term</a>()], from :: <a href="https://hexdocs.pm/elixir/typespecs.html#basic-types">pid</a>(), state :: <a href="https://hexdocs.pm/elixir/typespecs.html#basic-types">any</a>()) ::
{:ok, state :: <a href="https://hexdocs.pm/elixir/typespecs.html#basic-types">any</a>()}</pre>
</div>
</div>
<section class="docstring">
<p> This callback will be called every time a message to the subscribed metric type arrives. It must
return the tuple <code class="inline">{:ok, state}</code></p>
</section>
</div>
<div class="detail" id="c:terminate/1">
<div class="detail-header">
<a href="#c:terminate/1" class="detail-link" title="Link to this callback">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this callback</span>
</a>
<span class="signature">terminate(state)</span>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/receiver.ex#L134" class="view-source" rel="help" title="View Source">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
<div class="specs">
<pre>terminate(state :: <a href="https://hexdocs.pm/elixir/typespecs.html#built-in-types">term</a>()) :: <a href="https://hexdocs.pm/elixir/typespecs.html#built-in-types">term</a>()</pre>
</div>
</div>
<section class="docstring">
<p> This callback is called just before the Process goes down. This is a good place for closing connections.</p>
</section>
</div>
</section>
<footer class="footer">
<p>
<span class="line">
Built using
<a href="https://github.com/elixir-lang/ex_doc" title="ExDoc" rel="help" target="_blank">ExDoc</a> (v0.18.3),
</span>
<span class="line">
designed by
<a href="https://twitter.com/dignifiedquire" target="_blank" title="@dignifiedquire">Friedel Ziegelmayer</a>.
</span>
</p>
</footer>
</div>
</div>
</section>
</div>
<script src="dist/app-9bd040e5e5.js"></script>
</body>
</html>

View File

@ -0,0 +1,347 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="ExDoc v0.18.3">
<title>POABackend.Receivers.Dashboard poa_backend v0.1.0</title>
<link rel="stylesheet" href="dist/app-480ffdc169.css" />
<script src="dist/sidebar_items-ffeb4f1e51.js"></script>
</head>
<body data-type="modules">
<script>try { if(localStorage.getItem('night-mode')) document.body.className += ' night-mode'; } catch (e) { }</script>
<div class="main">
<button class="sidebar-button sidebar-toggle">
<span class="icon-menu" aria-hidden="true"></span>
<span class="sr-only">Toggle Sidebar</span>
</button>
<button class="sidebar-button night-mode-toggle">
<span class="icon-theme" aria-hidden="true"></span>
<span class="sr-only">Toggle Theme</span>
</button>
<section class="sidebar">
<a href="api-reference.html" class="sidebar-projectLink">
<div class="sidebar-projectDetails">
<h1 class="sidebar-projectName">
poa_backend
</h1>
<h2 class="sidebar-projectVersion">
v0.1.0
</h2>
</div>
</a>
<form class="sidebar-search" action="search.html">
<button type="submit" class="search-button">
<span class="icon-search" aria-hidden="true"></span>
</button>
<input name="q" type="text" id="search-list" class="search-input" placeholder="Search" aria-label="Search" autocomplete="off" />
</form>
<ul class="sidebar-listNav">
<li><a id="extras-list" href="#full-list">Pages</a></li>
<li><a id="modules-list" href="#full-list">Modules</a></li>
</ul>
<div class="gradient"></div>
<ul id="full-list" class="sidebar-fullList"></ul>
</section>
<section class="content">
<div class="content-outer">
<div id="content" class="content-inner">
<h1>
<small class="visible-xs">poa_backend v0.1.0</small>
POABackend.Receivers.Dashboard
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/receivers/dashboard.ex#L1" title="View Source" class="view-source" rel="help">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
</h1>
<section id="moduledoc">
<p>This is a Receiver Plugin which exposes a Websocket server and sends the metrics to the connected clients</p>
<p>This Receiver needs some data to be put in the config file (<em>receivers</em> section), for example:</p>
<pre><code class="elixir">{:dashboard_receiver, POABackend.Receivers.Dashboard, [
scheme: :http,
ws_url: &quot;/ws&quot;,
port: 8181,
ws_secret: &quot;mywssecret&quot;
]}</code></pre>
<ul>
<li>scheme: the scheme type :http or :https
</li>
<li>ws_url: endpoint for starting websocket connection
</li>
<li>port: the TCP port where the websocket server will listen
</li>
<li>ws_secret: the secret string which the clients must put in the “wssecret” header in order to start the connection
</li>
</ul>
<p><strong>All fields are mandatory</strong></p>
</section>
<section id="summary" class="details-list">
<h1 class="section-heading">
<a class="hover-link" href="#summary">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this section</span>
</a>
Summary
</h1>
<div class="summary-functions summary">
<h2>
<a href="#functions">Functions</a>
</h2>
<div class="summary-row">
<div class="summary-signature">
<a href="#handle_inactive/2">handle_inactive(agent_id, state)</a>
</div>
<div class="summary-synopsis"><p>This function is called when a Custom Handler detects a client is inactive</p>
</div>
</div>
<div class="summary-row">
<div class="summary-signature">
<a href="#handle_message/2">handle_message(arg, state)</a>
</div>
<div class="summary-synopsis"><p>In this callback is called when the Receiver process receives an erlang message</p>
</div>
</div>
<div class="summary-row">
<div class="summary-signature">
<a href="#init_receiver/1">init_receiver(opts)</a>
</div>
<div class="summary-synopsis"><p>A callback executed when the Receiver Plugin starts.
The argument is retrieved from the configuration file when the Receiver is defined
It must return <code class="inline">{:ok, state}</code>, that <code class="inline">state</code> will be keept as in <a href="https://hexdocs.pm/elixir/GenServer.html"><code class="inline">GenServer</code></a> and can be
retrieved in the <a href="#metrics_received/3"><code class="inline">metrics_received/3</code></a> function</p>
</div>
</div>
<div class="summary-row">
<div class="summary-signature">
<a href="#metrics_received/3">metrics_received(metrics, from, state)</a>
</div>
<div class="summary-synopsis"><p>This callback will be called every time a message to the subscribed metric type arrives. It must
return the tuple <code class="inline">{:ok, state}</code></p>
</div>
</div>
<div class="summary-row">
<div class="summary-signature">
<a href="#terminate/1">terminate(_)</a>
</div>
<div class="summary-synopsis"><p>This callback is called just before the Process goes down. This is a good place for closing connections</p>
</div>
</div>
</div>
</section>
<section id="functions" class="details-list">
<h1 class="section-heading">
<a class="hover-link" href="#functions">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this section</span>
</a>
Functions
</h1>
<div class="detail" id="handle_inactive/2">
<div class="detail-header">
<a href="#handle_inactive/2" class="detail-link" title="Link to this function">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this function</span>
</a>
<span class="signature">handle_inactive(agent_id, state)</span>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/receivers/dashboard.ex#L115" class="view-source" rel="help" title="View Source">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
</div>
<section class="docstring">
<p> This function is called when a Custom Handler detects a client is inactive.</p>
<p> The Custom Handler must to call explicity to <a href="POABackend.CustomHandler.html#publish_inactive/1"><code class="inline">POABackend.CustomHandler.publish_inactive/1</code></a> and it will publish the
<code class="inline">inactive</code> message to all the metrics in the system (defined in the config file).</p>
<p>Callback implementation for <a href="POABackend.Receiver.html#c:handle_inactive/2"><code class="inline">POABackend.Receiver.handle_inactive/2</code></a>.</p>
</section>
</div>
<div class="detail" id="handle_message/2">
<div class="detail-header">
<a href="#handle_message/2" class="detail-link" title="Link to this function">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this function</span>
</a>
<span class="signature">handle_message(arg, state)</span>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/receivers/dashboard.ex#L111" class="view-source" rel="help" title="View Source">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
</div>
<section class="docstring">
<p> In this callback is called when the Receiver process receives an erlang message.</p>
<p> It must return <code class="inline">{:ok, state}</code>.</p>
<p>Callback implementation for <a href="POABackend.Receiver.html#c:handle_message/2"><code class="inline">POABackend.Receiver.handle_message/2</code></a>.</p>
</section>
</div>
<div class="detail" id="init_receiver/1">
<div class="detail-header">
<a href="#init_receiver/1" class="detail-link" title="Link to this function">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this function</span>
</a>
<span class="signature">init_receiver(opts)</span>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/receivers/dashboard.ex#L95" class="view-source" rel="help" title="View Source">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
</div>
<section class="docstring">
<p> A callback executed when the Receiver Plugin starts.
The argument is retrieved from the configuration file when the Receiver is defined
It must return <code class="inline">{:ok, state}</code>, that <code class="inline">state</code> will be keept as in <a href="https://hexdocs.pm/elixir/GenServer.html"><code class="inline">GenServer</code></a> and can be
retrieved in the <a href="#metrics_received/3"><code class="inline">metrics_received/3</code></a> function.</p>
<p>Callback implementation for <a href="POABackend.Receiver.html#c:init_receiver/1"><code class="inline">POABackend.Receiver.init_receiver/1</code></a>.</p>
</section>
</div>
<div class="detail" id="metrics_received/3">
<div class="detail-header">
<a href="#metrics_received/3" class="detail-link" title="Link to this function">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this function</span>
</a>
<span class="signature">metrics_received(metrics, from, state)</span>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/receivers/dashboard.ex#L101" class="view-source" rel="help" title="View Source">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
</div>
<section class="docstring">
<p> This callback will be called every time a message to the subscribed metric type arrives. It must
return the tuple <code class="inline">{:ok, state}</code></p>
<p>Callback implementation for <a href="POABackend.Receiver.html#c:metrics_received/3"><code class="inline">POABackend.Receiver.metrics_received/3</code></a>.</p>
</section>
</div>
<div class="detail" id="terminate/1">
<div class="detail-header">
<a href="#terminate/1" class="detail-link" title="Link to this function">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this function</span>
</a>
<span class="signature">terminate(_)</span>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/receivers/dashboard.ex#L133" class="view-source" rel="help" title="View Source">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
</div>
<section class="docstring">
<p> This callback is called just before the Process goes down. This is a good place for closing connections.</p>
<p>Callback implementation for <a href="POABackend.Receiver.html#c:terminate/1"><code class="inline">POABackend.Receiver.terminate/1</code></a>.</p>
</section>
</div>
</section>
<footer class="footer">
<p>
<span class="line">
Built using
<a href="https://github.com/elixir-lang/ex_doc" title="ExDoc" rel="help" target="_blank">ExDoc</a> (v0.18.3),
</span>
<span class="line">
designed by
<a href="https://twitter.com/dignifiedquire" target="_blank" title="@dignifiedquire">Friedel Ziegelmayer</a>.
</span>
</p>
</footer>
</div>
</div>
</section>
</div>
<script src="dist/app-9bd040e5e5.js"></script>
</body>
</html>

View File

@ -0,0 +1,353 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="ExDoc v0.18.3">
<title>POABackend.Receivers.DynamoDB poa_backend v0.1.0</title>
<link rel="stylesheet" href="dist/app-480ffdc169.css" />
<script src="dist/sidebar_items-ffeb4f1e51.js"></script>
</head>
<body data-type="modules">
<script>try { if(localStorage.getItem('night-mode')) document.body.className += ' night-mode'; } catch (e) { }</script>
<div class="main">
<button class="sidebar-button sidebar-toggle">
<span class="icon-menu" aria-hidden="true"></span>
<span class="sr-only">Toggle Sidebar</span>
</button>
<button class="sidebar-button night-mode-toggle">
<span class="icon-theme" aria-hidden="true"></span>
<span class="sr-only">Toggle Theme</span>
</button>
<section class="sidebar">
<a href="api-reference.html" class="sidebar-projectLink">
<div class="sidebar-projectDetails">
<h1 class="sidebar-projectName">
poa_backend
</h1>
<h2 class="sidebar-projectVersion">
v0.1.0
</h2>
</div>
</a>
<form class="sidebar-search" action="search.html">
<button type="submit" class="search-button">
<span class="icon-search" aria-hidden="true"></span>
</button>
<input name="q" type="text" id="search-list" class="search-input" placeholder="Search" aria-label="Search" autocomplete="off" />
</form>
<ul class="sidebar-listNav">
<li><a id="extras-list" href="#full-list">Pages</a></li>
<li><a id="modules-list" href="#full-list">Modules</a></li>
</ul>
<div class="gradient"></div>
<ul id="full-list" class="sidebar-fullList"></ul>
</section>
<section class="content">
<div class="content-outer">
<div id="content" class="content-inner">
<h1>
<small class="visible-xs">poa_backend v0.1.0</small>
POABackend.Receivers.DynamoDB
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/receivers/dynamo_db.ex#L1" title="View Source" class="view-source" rel="help">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
</h1>
<section id="moduledoc">
<p>This is a Receiver Plugin which stores the received Ethereum Blocks in DynamoDB</p>
<p>This Receiver needs some data to be put in the config file (<em>receivers</em> section), for example:</p>
<pre><code class="elixir">{:dynamodb_receiver, POABackend.Receivers.DynamoDB, [
scheme: &quot;http://&quot;,
host: &quot;localhost&quot;,
port: 8000,
access_key_id: &quot;myaccesskeyid&quot;,
secret_access_key: &quot;mysecretaccesskey&quot;,
region: &quot;us-east-1&quot;
]}</code></pre>
<ul>
<li>scheme: the scheme type
</li>
<li>host: host name or url
</li>
<li>port: the TCP port where the DynamoDB instance is listening
</li>
<li>access_key_id: the AWS access key
</li>
<li>secret_access_key: the AWS secret access key
</li>
<li>region: the AWS region
</li>
</ul>
<p><strong>All fields are mandatory</strong></p>
</section>
<section id="summary" class="details-list">
<h1 class="section-heading">
<a class="hover-link" href="#summary">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this section</span>
</a>
Summary
</h1>
<div class="summary-functions summary">
<h2>
<a href="#functions">Functions</a>
</h2>
<div class="summary-row">
<div class="summary-signature">
<a href="#handle_inactive/2">handle_inactive(_, state)</a>
</div>
<div class="summary-synopsis"><p>This function is called when a Custom Handler detects a client is inactive</p>
</div>
</div>
<div class="summary-row">
<div class="summary-signature">
<a href="#handle_message/2">handle_message(message, state)</a>
</div>
<div class="summary-synopsis"><p>In this callback is called when the Receiver process receives an erlang message</p>
</div>
</div>
<div class="summary-row">
<div class="summary-signature">
<a href="#init_receiver/1">init_receiver(opts)</a>
</div>
<div class="summary-synopsis"><p>A callback executed when the Receiver Plugin starts.
The argument is retrieved from the configuration file when the Receiver is defined
It must return <code class="inline">{:ok, state}</code>, that <code class="inline">state</code> will be keept as in <a href="https://hexdocs.pm/elixir/GenServer.html"><code class="inline">GenServer</code></a> and can be
retrieved in the <a href="#metrics_received/3"><code class="inline">metrics_received/3</code></a> function</p>
</div>
</div>
<div class="summary-row">
<div class="summary-signature">
<a href="#metrics_received/3">metrics_received(metrics, from, state)</a>
</div>
<div class="summary-synopsis"><p>This callback will be called every time a message to the subscribed metric type arrives. It must
return the tuple <code class="inline">{:ok, state}</code></p>
</div>
</div>
<div class="summary-row">
<div class="summary-signature">
<a href="#terminate/1">terminate(_)</a>
</div>
<div class="summary-synopsis"><p>This callback is called just before the Process goes down. This is a good place for closing connections</p>
</div>
</div>
</div>
</section>
<section id="functions" class="details-list">
<h1 class="section-heading">
<a class="hover-link" href="#functions">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this section</span>
</a>
Functions
</h1>
<div class="detail" id="handle_inactive/2">
<div class="detail-header">
<a href="#handle_inactive/2" class="detail-link" title="Link to this function">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this function</span>
</a>
<span class="signature">handle_inactive(_, state)</span>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/receivers/dynamo_db.ex#L81" class="view-source" rel="help" title="View Source">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
</div>
<section class="docstring">
<p> This function is called when a Custom Handler detects a client is inactive.</p>
<p> The Custom Handler must to call explicity to <a href="POABackend.CustomHandler.html#publish_inactive/1"><code class="inline">POABackend.CustomHandler.publish_inactive/1</code></a> and it will publish the
<code class="inline">inactive</code> message to all the metrics in the system (defined in the config file).</p>
<p>Callback implementation for <a href="POABackend.Receiver.html#c:handle_inactive/2"><code class="inline">POABackend.Receiver.handle_inactive/2</code></a>.</p>
</section>
</div>
<div class="detail" id="handle_message/2">
<div class="detail-header">
<a href="#handle_message/2" class="detail-link" title="Link to this function">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this function</span>
</a>
<span class="signature">handle_message(message, state)</span>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/receivers/dynamo_db.ex#L83" class="view-source" rel="help" title="View Source">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
</div>
<section class="docstring">
<p> In this callback is called when the Receiver process receives an erlang message.</p>
<p> It must return <code class="inline">{:ok, state}</code>.</p>
<p>Callback implementation for <a href="POABackend.Receiver.html#c:handle_message/2"><code class="inline">POABackend.Receiver.handle_message/2</code></a>.</p>
</section>
</div>
<div class="detail" id="init_receiver/1">
<div class="detail-header">
<a href="#init_receiver/1" class="detail-link" title="Link to this function">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this function</span>
</a>
<span class="signature">init_receiver(opts)</span>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/receivers/dynamo_db.ex#L66" class="view-source" rel="help" title="View Source">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
</div>
<section class="docstring">
<p> A callback executed when the Receiver Plugin starts.
The argument is retrieved from the configuration file when the Receiver is defined
It must return <code class="inline">{:ok, state}</code>, that <code class="inline">state</code> will be keept as in <a href="https://hexdocs.pm/elixir/GenServer.html"><code class="inline">GenServer</code></a> and can be
retrieved in the <a href="#metrics_received/3"><code class="inline">metrics_received/3</code></a> function.</p>
<p>Callback implementation for <a href="POABackend.Receiver.html#c:init_receiver/1"><code class="inline">POABackend.Receiver.init_receiver/1</code></a>.</p>
</section>
</div>
<div class="detail" id="metrics_received/3">
<div class="detail-header">
<a href="#metrics_received/3" class="detail-link" title="Link to this function">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this function</span>
</a>
<span class="signature">metrics_received(metrics, from, state)</span>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/receivers/dynamo_db.ex#L74" class="view-source" rel="help" title="View Source">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
</div>
<section class="docstring">
<p> This callback will be called every time a message to the subscribed metric type arrives. It must
return the tuple <code class="inline">{:ok, state}</code></p>
<p>Callback implementation for <a href="POABackend.Receiver.html#c:metrics_received/3"><code class="inline">POABackend.Receiver.metrics_received/3</code></a>.</p>
</section>
</div>
<div class="detail" id="terminate/1">
<div class="detail-header">
<a href="#terminate/1" class="detail-link" title="Link to this function">
<span class="icon-link" aria-hidden="true"></span>
<span class="sr-only">Link to this function</span>
</a>
<span class="signature">terminate(_)</span>
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend/receivers/dynamo_db.ex#L85" class="view-source" rel="help" title="View Source">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
</div>
<section class="docstring">
<p> This callback is called just before the Process goes down. This is a good place for closing connections.</p>
<p>Callback implementation for <a href="POABackend.Receiver.html#c:terminate/1"><code class="inline">POABackend.Receiver.terminate/1</code></a>.</p>
</section>
</div>
</section>
<footer class="footer">
<p>
<span class="line">
Built using
<a href="https://github.com/elixir-lang/ex_doc" title="ExDoc" rel="help" target="_blank">ExDoc</a> (v0.18.3),
</span>
<span class="line">
designed by
<a href="https://twitter.com/dignifiedquire" target="_blank" title="@dignifiedquire">Friedel Ziegelmayer</a>.
</span>
</p>
</footer>
</div>
</div>
</section>
</div>
<script src="dist/app-9bd040e5e5.js"></script>
</body>
</html>

138
doc/POABackend.html Normal file
View File

@ -0,0 +1,138 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="ExDoc v0.18.3">
<title>POABackend poa_backend v0.1.0</title>
<link rel="stylesheet" href="dist/app-480ffdc169.css" />
<script src="dist/sidebar_items-ffeb4f1e51.js"></script>
</head>
<body data-type="modules">
<script>try { if(localStorage.getItem('night-mode')) document.body.className += ' night-mode'; } catch (e) { }</script>
<div class="main">
<button class="sidebar-button sidebar-toggle">
<span class="icon-menu" aria-hidden="true"></span>
<span class="sr-only">Toggle Sidebar</span>
</button>
<button class="sidebar-button night-mode-toggle">
<span class="icon-theme" aria-hidden="true"></span>
<span class="sr-only">Toggle Theme</span>
</button>
<section class="sidebar">
<a href="api-reference.html" class="sidebar-projectLink">
<div class="sidebar-projectDetails">
<h1 class="sidebar-projectName">
poa_backend
</h1>
<h2 class="sidebar-projectVersion">
v0.1.0
</h2>
</div>
</a>
<form class="sidebar-search" action="search.html">
<button type="submit" class="search-button">
<span class="icon-search" aria-hidden="true"></span>
</button>
<input name="q" type="text" id="search-list" class="search-input" placeholder="Search" aria-label="Search" autocomplete="off" />
</form>
<ul class="sidebar-listNav">
<li><a id="extras-list" href="#full-list">Pages</a></li>
<li><a id="modules-list" href="#full-list">Modules</a></li>
</ul>
<div class="gradient"></div>
<ul id="full-list" class="sidebar-fullList"></ul>
</section>
<section class="content">
<div class="content-outer">
<div id="content" class="content-inner">
<h1>
<small class="visible-xs">poa_backend v0.1.0</small>
POABackend
<a href="https://github.com/poanetwork/poa-netstats-wharehouse/blob/v0.1.0/lib/poa_backend.ex#L1" title="View Source" class="view-source" rel="help">
<span class="icon-code" aria-hidden="true"></span>
<span class="sr-only">View Source</span>
</a>
</h1>
<section id="moduledoc">
<p>Storage and data-processing companion for the <a href="https://github.com/poanetwork/poa-netstats-agent">poa-netstats-agent</a></p>
<h2 id="module-documentation" class="section-heading">
<a href="#module-documentation" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
Documentation
</h2>
<p>In order to build the documentation run</p>
<pre><code class="elixir">mix deps.get
mix docs</code></pre>
<p>That command will create a <code class="inline">doc/</code> folder with the actual Documentation.</p>
<h2 id="module-run-tests" class="section-heading">
<a href="#module-run-tests" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
Run Tests
</h2>
<p>In order to run the tests we have to run the command</p>
<pre><code class="elixir">mix test</code></pre>
<p><a href="POABackend.html#content"><code class="inline">POABackend</code></a> comes also with a code analysis tool <a href="https://github.com/rrrene/credo">Credo</a> and a types checker tool <a href="https://github.com/jeremyjh/dialyxir">Dialyxir</a>. In order to run them we have to run</p>
<pre><code class="elixir">mix credo
mix dialyzer</code></pre>
</section>
<footer class="footer">
<p>
<span class="line">
Built using
<a href="https://github.com/elixir-lang/ex_doc" title="ExDoc" rel="help" target="_blank">ExDoc</a> (v0.18.3),
</span>
<span class="line">
designed by
<a href="https://twitter.com/dignifiedquire" target="_blank" title="@dignifiedquire">Friedel Ziegelmayer</a>.
</span>
</p>
</footer>
</div>
</div>
</section>
</div>
<script src="dist/app-9bd040e5e5.js"></script>
</body>
</html>

BIN
doc/REST_architecture.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

190
doc/api-reference.html Normal file
View File

@ -0,0 +1,190 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="ExDoc v0.18.3">
<title>API Reference poa_backend v0.1.0</title>
<link rel="stylesheet" href="dist/app-480ffdc169.css" />
<script src="dist/sidebar_items-ffeb4f1e51.js"></script>
</head>
<body data-type="extras">
<script>try { if(localStorage.getItem('night-mode')) document.body.className += ' night-mode'; } catch (e) { }</script>
<div class="main">
<button class="sidebar-button sidebar-toggle">
<span class="icon-menu" aria-hidden="true"></span>
<span class="sr-only">Toggle Sidebar</span>
</button>
<button class="sidebar-button night-mode-toggle">
<span class="icon-theme" aria-hidden="true"></span>
<span class="sr-only">Toggle Theme</span>
</button>
<section class="sidebar">
<a href="api-reference.html" class="sidebar-projectLink">
<div class="sidebar-projectDetails">
<h1 class="sidebar-projectName">
poa_backend
</h1>
<h2 class="sidebar-projectVersion">
v0.1.0
</h2>
</div>
</a>
<form class="sidebar-search" action="search.html">
<button type="submit" class="search-button">
<span class="icon-search" aria-hidden="true"></span>
</button>
<input name="q" type="text" id="search-list" class="search-input" placeholder="Search" aria-label="Search" autocomplete="off" />
</form>
<ul class="sidebar-listNav">
<li><a id="extras-list" href="#full-list">Pages</a></li>
<li><a id="modules-list" href="#full-list">Modules</a></li>
</ul>
<div class="gradient"></div>
<ul id="full-list" class="sidebar-fullList"></ul>
</section>
<section class="content">
<div class="content-outer">
<div id="content" class="content-inner">
<h1>
<small class="visible-xs">poa_backend v0.1.0</small>
API Reference
</h1>
<section class="details-list">
<h2 id="modules" class="section-heading">
<a href="#modules" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
Modules
</h2>
<div class="summary">
<div class="summary-row">
<div class="summary-signature"><a href="POABackend.html">POABackend</a></div>
<div class="summary-synopsis"><p>Storage and data-processing companion for the <a href="https://github.com/poanetwork/poa-netstats-agent">poa-netstats-agent</a></p>
</div>
</div>
<div class="summary-row">
<div class="summary-signature"><a href="POABackend.CustomHandler.html">POABackend.CustomHandler</a></div>
<div class="summary-synopsis"><p>A Custom Handler is responsible of handling data sent from Agents (i.e. REST over HTTP, WebSockets…) “speaking” the POA Protocol</p>
</div>
</div>
<div class="summary-row">
<div class="summary-signature"><a href="POABackend.CustomHandler.REST.html">POABackend.CustomHandler.REST</a></div>
<div class="summary-synopsis"><p>This module implements the REST Custom Handler over HTTP/1.1</p>
</div>
</div>
<div class="summary-row">
<div class="summary-signature"><a href="POABackend.Protocol.html">POABackend.Protocol</a></div>
<div class="summary-synopsis"><h2 id="poa-protocol" class="section-heading">
<a href="#poa-protocol" class="hover-link"><span class="icon-link" aria-hidden="true"></span></a>
POA Protocol
</h2>
</div>
</div>
<div class="summary-row">
<div class="summary-signature"><a href="POABackend.Protocol.DataType.html">POABackend.Protocol.DataType</a></div>
<div class="summary-synopsis"><p>The protocol messages Data type</p>
</div>
</div>
<div class="summary-row">
<div class="summary-signature"><a href="POABackend.Protocol.Message.html">POABackend.Protocol.Message</a></div>
<div class="summary-synopsis"><p>The message received from the Agent (inspired in <a href="https://hexdocs.pm/plug/Plug.Conn.html"><code class="inline">Plug.Conn</code></a>)</p>
</div>
</div>
<div class="summary-row">
<div class="summary-signature"><a href="POABackend.Protocol.MessageType.html">POABackend.Protocol.MessageType</a></div>
<div class="summary-synopsis"><p>Regarding the POA Protocol only 2 types of message can be processed in the backend</p>
</div>
</div>
<div class="summary-row">
<div class="summary-signature"><a href="POABackend.Receiver.html">POABackend.Receiver</a></div>
<div class="summary-synopsis"><p>Defines a Receiver Plugin</p>
</div>
</div>
<div class="summary-row">
<div class="summary-signature"><a href="POABackend.Receivers.Dashboard.html">POABackend.Receivers.Dashboard</a></div>
<div class="summary-synopsis"><p>This is a Receiver Plugin which exposes a Websocket server and sends the metrics to the connected clients</p>
</div>
</div>
<div class="summary-row">
<div class="summary-signature"><a href="POABackend.Receivers.DynamoDB.html">POABackend.Receivers.DynamoDB</a></div>
<div class="summary-synopsis"><p>This is a Receiver Plugin which stores the received Ethereum Blocks in DynamoDB</p>
</div>
</div>
</div>
</section>
<footer class="footer">
<p>
<span class="line">
Built using
<a href="https://github.com/elixir-lang/ex_doc" title="ExDoc" rel="help" target="_blank">ExDoc</a> (v0.18.3),
</span>
<span class="line">
designed by
<a href="https://twitter.com/dignifiedquire" target="_blank" title="@dignifiedquire">Friedel Ziegelmayer</a>.
</span>
</p>
</footer>
</div>
</div>
</section>
</div>
<script src="dist/app-9bd040e5e5.js"></script>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

1
doc/dist/app-480ffdc169.css vendored Normal file

File diff suppressed because one or more lines are too long

8
doc/dist/app-9bd040e5e5.js vendored Normal file

File diff suppressed because one or more lines are too long

1
doc/dist/sidebar_items-ffeb4f1e51.js vendored Normal file
View File

@ -0,0 +1 @@
sidebarNodes={"extras":[{"id":"api-reference","title":"API Reference","group":"","headers":[{"id":"Modules","anchor":"modules"},{"id":"POA Protocol","anchor":"poa-protocol"}]},{"id":"initial_architecture","title":"Initial Architecture","group":"","headers":[]}],"exceptions":[],"modules":[{"id":"POABackend","title":"POABackend","group":""},{"id":"POABackend.Protocol","title":"POABackend.Protocol","group":"POA Protocol"},{"id":"POABackend.Protocol.DataType","title":"POABackend.Protocol.DataType","group":"POA Protocol","types":[{"id":"t/0","anchor":"t:t/0"}]},{"id":"POABackend.Protocol.Message","title":"POABackend.Protocol.Message","group":"POA Protocol","functions":[{"id":"assign/3","anchor":"assign/3"},{"id":"new/0","anchor":"new/0"},{"id":"new/4","anchor":"new/4"}],"types":[{"id":"t/0","anchor":"t:t/0"}]},{"id":"POABackend.Protocol.MessageType","title":"POABackend.Protocol.MessageType","group":"POA Protocol","types":[{"id":"t/0","anchor":"t:t/0"}]},{"id":"POABackend.CustomHandler","title":"POABackend.CustomHandler","group":"Custom Handler","callbacks":[{"id":"child_spec/1","anchor":"c:child_spec/1"}],"functions":[{"id":"publish_inactive/1","anchor":"publish_inactive/1"},{"id":"send_to_receivers/1","anchor":"send_to_receivers/1"}]},{"id":"POABackend.CustomHandler.REST","title":"POABackend.CustomHandler.REST","group":"Custom Handler","functions":[{"id":"ping_monitor/1","anchor":"ping_monitor/1"}]},{"id":"POABackend.Receiver","title":"POABackend.Receiver","group":"Receivers","callbacks":[{"id":"handle_inactive/2","anchor":"c:handle_inactive/2"},{"id":"handle_message/2","anchor":"c:handle_message/2"},{"id":"init_receiver/1","anchor":"c:init_receiver/1"},{"id":"metrics_received/3","anchor":"c:metrics_received/3"},{"id":"terminate/1","anchor":"c:terminate/1"}]},{"id":"POABackend.Receivers.Dashboard","title":"POABackend.Receivers.Dashboard","group":"Receivers","functions":[{"id":"handle_inactive/2","anchor":"handle_inactive/2"},{"id":"handle_message/2","anchor":"handle_message/2"},{"id":"init_receiver/1","anchor":"init_receiver/1"},{"id":"metrics_received/3","anchor":"metrics_received/3"},{"id":"terminate/1","anchor":"terminate/1"}]},{"id":"POABackend.Receivers.DynamoDB","title":"POABackend.Receivers.DynamoDB","group":"Receivers","functions":[{"id":"handle_inactive/2","anchor":"handle_inactive/2"},{"id":"handle_message/2","anchor":"handle_message/2"},{"id":"init_receiver/1","anchor":"init_receiver/1"},{"id":"metrics_received/3","anchor":"metrics_received/3"},{"id":"terminate/1","anchor":"terminate/1"}]}],"tasks":[]}

BIN
doc/fonts/icomoon.eot Normal file

Binary file not shown.

18
doc/fonts/icomoon.svg Normal file
View File

@ -0,0 +1,18 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Generated by IcoMoon</metadata>
<defs>
<font id="icomoon" horiz-adv-x="512">
<font-face units-per-em="512" ascent="480" descent="-32" />
<missing-glyph horiz-adv-x="512" />
<glyph unicode="&#x20;" horiz-adv-x="256" d="" />
<glyph unicode="&#xe005;" glyph-name="link" d="M362.666 437.333q25.166 0 48.584-9.5t41.916-28 28-41.916 9.5-48.584q0-25-9.584-48.583t-27.916-41.917l-64-64q-1.834-1.834-5.5-5.166-17.834-15.834-39.834-24.084t-45.166-8.25q-29.166 0-55.166 12.5-19.5 9.166-35.334 25t-25 35.334q12.5 12.5 30.166 12.5 6.167 0 12.5-1.834 10.834-17.5 28.334-28.334 20.5-12.5 44.5-12.5 16.666 0 32.334 6.334t28 18.666l64 64q12.334 12.333 18.666 28t6.334 32.333-6.334 32.334-18.666 28-28 18.666-32.334 6.334-32.334-6.334-28-18.666l-44.834-44.834q-21.334 5.834-44.166 5.834-3.667 0-10.334-0.334 3.333 3.667 5.167 5.5l64 64q18.334 18.334 41.916 27.917t48.584 9.583zM213.333 288q29.167 0 55.167-12.5 19.5-9.167 35.334-25t25-35.333q-12.5-12.5-30.166-12.5-6.166 0-12.5 1.834-10.834 17.5-28.334 28.333-20.5 12.5-44.5 12.5-16.666 0-32.334-6.333t-28-18.667l-64-64q-12.334-12.334-18.666-28t-6.334-32.334 6.334-32.334 18.666-28 28-18.666 32.334-6.334 32.334 6.334 28 18.666l44.834 44.834q21.334-5.834 44.166-5.834 3.666 0 10.334 0.334-3.334-3.666-5.166-5.5l-64-64q-18.5-18.5-41.916-28t-48.584-9.5q-25 0-48.584 9.584t-41.916 27.916q-18.5 18.5-28 41.916t-9.5 48.584 9.5 48.584 28 41.916l64 64q1.834 1.833 5.5 5.166 17.834 15.834 39.834 24.084t45.166 8.25z" />
<glyph unicode="&#xe036;" glyph-name="search" d="M213.333 437.333q39 0 74.583-15.25t61.25-40.916 40.916-61.25 15.25-74.584q0-33.5-10.916-64.167t-31.084-55.666l121.166-121q6.166-6.166 6.166-15.166 0-9.166-6.084-15.25t-15.25-6.084q-9 0-15.166 6.166l-121 121.166q-25-20.166-55.666-31.084t-64.166-10.916q-39 0-74.584 15.25t-61.25 40.916-40.916 61.25-15.25 74.584 15.25 74.584 40.916 61.25 61.25 40.916 74.584 15.25zM213.333 394.666q-30.333 0-58-11.834t-47.666-31.833-31.834-47.667-11.834-58 11.834-58 31.834-47.666 47.666-31.834 58-11.834 58 11.834 47.666 31.834 31.834 47.666 11.834 58-11.834 58-31.834 47.667-47.666 31.833-58 11.834z" />
<glyph unicode="&#xe117;" glyph-name="cross" d="M405.334 373.333q9.166 0 15.25-6.083t6.084-15.25q0-9-6.166-15.167l-134.334-134.166 134.333-134.167q6.166-6.166 6.166-15.166 0-9.166-6.084-15.25t-15.25-6.084q-9 0-15.166 6.166l-134.166 134.334-134.167-134.333q-6.166-6.166-15.166-6.166-9.166 0-15.25 6.084t-6.084 15.25q0 9 6.166 15.166l134.333 134.167-134.333 134.167q-6.166 6.166-6.166 15.166 0 9.167 6.084 15.25t15.25 6.084q9 0 15.166-6.167l134.167-134.333 134.167 134.333q6.166 6.166 15.166 6.166z" />
<glyph unicode="&#xe120;" glyph-name="menu" d="M64 352h384q8.834 0 15.084-6.25t6.25-15.083-6.25-15.084-15.084-6.25h-384q-8.834 0-15.084 6.25t-6.25 15.084 6.25 15.083 15.084 6.25zM64 96h384q8.834 0 15.084-6.25t6.25-15.084-6.25-15.084-15.084-6.25h-384q-8.834 0-15.084 6.25t-6.25 15.084 6.25 15.084 15.084 6.25zM64 224h384q8.834 0 15.084-6.25t6.25-15.084-6.25-15.084-15.084-6.25h-384q-8.834 0-15.084 6.25t-6.25 15.084 6.25 15.084 15.084 6.25z" />
<glyph unicode="&#xe900;" glyph-name="moon" d="M458.666 215.467c-6.4 4.267-17.067 4.267-23.466-2.134-44.8-34.134-106.666-34.134-151.466 0-57.6 42.667-70.4 121.6-27.733 179.2 4.267 6.4 6.4 14.934 2.134 23.466-4.267 6.4-12.8 10.667-21.334 10.667-102.4-8.534-183.466-89.6-192-192-10.666-117.334 74.666-221.867 192-232.534 6.4 0 12.8 0 19.2 0 49.067 0 98.134 17.067 136.534 49.067 44.8 36.267 70.4 87.466 76.8 145.067 0 6.4-4.267 14.933-10.666 19.2zM366.933 83.2c-34.134-29.866-78.933-42.666-123.733-38.4-93.867 8.534-162.133 91.733-153.6 185.6 6.4 66.133 51.2 123.733 110.934 145.066-25.6-68.266-2.133-149.333 59.733-196.267 46.933-34.134 106.666-42.666 160-23.466-12.8-27.733-29.866-53.334-53.334-72.534z" />
<glyph unicode="&#xe901;" glyph-name="sun" d="M256 341.333c-70.4 0-128-57.6-128-128s57.6-128 128-128 128 57.6 128 128-57.6 128-128 128zM256 128c-46.934 0-85.334 38.4-85.334 85.334s38.4 85.334 85.334 85.334c46.933 0 85.334-38.4 85.334-85.334s-38.4-85.334-85.334-85.334zM256 384c12.8 0 21.334 8.534 21.334 21.334v42.666c0 12.8-8.534 21.333-21.334 21.333s-21.334-8.534-21.334-21.333v-42.666c0-12.8 8.534-21.334 21.334-21.334zM256 42.667c-12.8 0-21.334-8.534-21.334-21.334v-42.666c0-12.8 8.534-21.333 21.334-21.333s21.334 8.534 21.334 21.333v42.666c0 12.8-8.534 21.334-21.334 21.334zM104.534 334.933c4.266-4.267 10.666-6.4 14.933-6.4s10.666 2.134 14.933 6.4c8.534 8.534 8.534 21.334 0 29.867l-29.867 29.866c-8.534 8.534-21.334 8.534-29.867 0s-8.534-21.334 0-29.866l29.867-29.867zM407.466 91.733c-8.534 8.534-21.334 8.534-29.866 0s-8.534-21.334 0-29.866l29.866-29.866c4.267-4.267 10.666-6.4 14.933-6.4s10.666 2.134 14.933 6.4c8.534 8.534 8.534 21.334 0 29.866l-29.866 29.866zM85.334 213.333c0 12.8-8.534 21.334-21.334 21.334h-42.666c-12.8 0-21.334-8.534-21.334-21.334s8.534-21.334 21.334-21.334h42.666c12.8 0 21.334 8.534 21.334 21.334zM490.666 234.667h-42.666c-12.8 0-21.334-8.534-21.334-21.334s8.534-21.334 21.334-21.334h42.666c12.8 0 21.334 8.534 21.334 21.334s-8.534 21.334-21.334 21.334zM104.534 91.733l-29.867-29.866c-8.534-8.534-8.534-21.334 0-29.866 4.266-4.267 10.666-6.4 14.933-6.4s10.666 2.134 14.933 6.4l29.867 29.866c8.534 8.534 8.534 21.334 0 29.866s-21.334 8.534-29.867 0zM392.534 328.533c6.4 0 10.666 2.134 14.933 6.4l29.866 29.867c8.534 8.534 8.534 21.333 0 29.866s-21.334 8.534-29.866 0l-29.866-29.866c-8.534-8.534-8.534-21.334 0-29.867 2.134-4.267 8.534-6.4 14.933-6.4z" />
<glyph unicode="&#xf105;" glyph-name="angle-right" horiz-adv-x="183" d="M170 190.476q0-3.714-2.857-6.572l-133.143-133.143q-2.857-2.857-6.572-2.857t-6.572 2.857l-14.286 14.286q-2.857 2.857-2.857 6.572t2.857 6.572l112.285 112.286-112.285 112.286q-2.857 2.857-2.857 6.572t2.857 6.572l14.285 14.286q2.857 2.857 6.572 2.857t6.572-2.857l133.143-133.143q2.857-2.857 2.857-6.572z" />
<glyph unicode="&#xf121;" glyph-name="code" horiz-adv-x="549" d="M176.286 65.047l-14.286-14.286q-2.857-2.857-6.572-2.857t-6.572 2.857l-133.143 133.143q-2.857 2.857-2.857 6.572t2.857 6.572l133.143 133.143q2.857 2.857 6.572 2.857t6.572-2.857l14.286-14.286q2.857-2.857 2.857-6.571t-2.857-6.572l-112.285-112.286 112.285-112.286q2.857-2.857 2.857-6.572t-2.857-6.572zM345.143 369.905l-106.572-368.857q-1.143-3.714-4.428-5.572t-6.714-0.714l-17.714 4.857q-3.714 1.143-5.572 4.428t-0.714 7l106.572 368.857q1.143 3.714 4.428 5.571t6.714 0.715l17.714-4.857q3.714-1.143 5.572-4.428t0.714-7zM532.857 183.905l-133.143-133.143q-2.857-2.857-6.572-2.857t-6.572 2.857l-14.286 14.286q-2.857 2.857-2.857 6.572t2.857 6.572l112.286 112.286-112.286 112.286q-2.857 2.857-2.857 6.572t2.857 6.572l14.286 14.286q2.857 2.857 6.572 2.857t6.572-2.857l133.143-133.143q2.857-2.857 2.857-6.572t-2.857-6.572z" />
</font></defs></svg>

After

Width:  |  Height:  |  Size: 6.7 KiB

BIN
doc/fonts/icomoon.ttf Normal file

Binary file not shown.

BIN
doc/fonts/icomoon.woff Normal file

Binary file not shown.

11
doc/index.html Normal file
View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>poa_backend v0.1.0 Documentation</title>
<meta http-equiv="refresh" content="0; url=api-reference.html">
<meta name="robots" content="noindex">
<meta name="generator" content="ExDoc v0.18.3">
</head>
<body></body>
</html>

View File

@ -0,0 +1,132 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="ExDoc v0.18.3">
<title>Initial Architecture poa_backend v0.1.0</title>
<link rel="stylesheet" href="dist/app-480ffdc169.css" />
<script src="dist/sidebar_items-ffeb4f1e51.js"></script>
</head>
<body data-type="extras">
<script>try { if(localStorage.getItem('night-mode')) document.body.className += ' night-mode'; } catch (e) { }</script>
<div class="main">
<button class="sidebar-button sidebar-toggle">
<span class="icon-menu" aria-hidden="true"></span>
<span class="sr-only">Toggle Sidebar</span>
</button>
<button class="sidebar-button night-mode-toggle">
<span class="icon-theme" aria-hidden="true"></span>
<span class="sr-only">Toggle Theme</span>
</button>
<section class="sidebar">
<a href="api-reference.html" class="sidebar-projectLink">
<div class="sidebar-projectDetails">
<h1 class="sidebar-projectName">
poa_backend
</h1>
<h2 class="sidebar-projectVersion">
v0.1.0
</h2>
</div>
</a>
<form class="sidebar-search" action="search.html">
<button type="submit" class="search-button">
<span class="icon-search" aria-hidden="true"></span>
</button>
<input name="q" type="text" id="search-list" class="search-input" placeholder="Search" aria-label="Search" autocomplete="off" />
</form>
<ul class="sidebar-listNav">
<li><a id="extras-list" href="#full-list">Pages</a></li>
<li><a id="modules-list" href="#full-list">Modules</a></li>
</ul>
<div class="gradient"></div>
<ul id="full-list" class="sidebar-fullList"></ul>
</section>
<section class="content">
<div class="content-outer">
<div id="content" class="content-inner">
<h1>Server Architecture</h1>
<p>This is the diagram for the new Elixir-based architecture. We propose a new server layer between the Agents and the Sinks (with the Dashboard UI being a type of sink).</p>
<p><img src="../assets/general_overview.png" alt="General Overview"/></p>
<p>The Backend Server is the actor in this new Server layer. It is in charge of speaking with the Agents, receiving Data / Metrics, converting the data from the protocol messages to Elixir structures and dispatching the result to different Receivers based on a mapping in the config file.</p>
<p><img src="../assets/backend_architecture.png" alt="Backend Architecture"/></p>
<p>Key points:</p>
<ul>
<li><p><strong>Custom Protocol</strong>: The custom Protocol is the language the Agents Transfer and Custom Protocol Handler must speak. That defines the messages and data which can be exchanged.
The messages defined in the protocol can be pure JSON for now but we must think in other lighter options like messagepack
The messages will have (among others) a mandatory field for the “type of data” sent. The possible values for this field will be defined and are fixed, for now only an “ethereum<em>metrics” type exists. That will allow us to map the type of metric to the receiver (i.e. sending ethereum<em>metrics to the dashboard and system_metrics to a database)
__With this decision we remove the PRIMUS protocol</em></em></p>
</li>
<li><p><strong>Custom Protocol Handler</strong>: The communication between the Agents and the Backend Server is done with a custom protocol over Websockets (for now) but it is extensible (via Plugins) to different technologies like REST endpoints over HTTP or others. In order to support a new technology here we have to implement a new Custom Protocol Handler plugin and it will involve a new Agent Transfer too.
It will be a simple Websockets server for now (probably with a light version of Phoenix or Cowboy directly).
Each request will be executed in a separate process (handled by Cowboy/Phoenix) and will be responsible of decoding the messages from the Custom Protocol to Elixir structs.
Bottom line is the Agents Transfer speaks with the Custom Protocol Handler</p>
</li>
<li><p><strong>Receivers</strong>: The Custom Protocol Handler will dispatch the messages to the Receivers processes based on the “type of data” field.
Receivers are going to be Plugins, where anyone can create its own plugin and extend the system. For now the only Receiver will be the Dashboard Receiver which will be in charge of transferring the messages to the Dashboard but we can create more Receivers like one for storing metrics in a AWS DynamoDB.
The means to map the receivers with the type of data will be specified in the config file (as we are doing for the Agents) i.e., we can map “ethereum_metrics” going to the Dashboard Receiver and AWS DynamoDB Receiver and “system_metrics” to only the AWS DynamoDB Receiver.</p>
</li>
<li><p><strong>Sinks</strong>: The receivers can do anything with the data. They can send metrics to the Dashboard UI, send data to External Databases or whatever we want. For that we have to write our own Receiver and map it to the messages we want in the config file and adding our desired behaviour.
The Dashboard UI (NodeJS) will be refactored and modified in order to speak directly with the Receiver instead of directly with the Agents. We have to modify this communication and create a new protocol.</p>
</li>
</ul>
<p>This new Backend Server layer allow us to scale if the systems requires it. The way we will scale is adding more Backend Server nodes to the system</p>
<p><img src="../assets/scaling.png" alt="Scaling"/></p>
<p>f the system grows exponentially and the presented distributed architecture is not enough, the plugin system and the APIs will allow us to migrate to a microservice architecture easily. We will have 3 independent layers:</p>
<ul>
<li><p><strong>Frontend layer</strong>: This will consist in many nodes (as needed) implementing only one type of Customer Protocol Handler.</p>
</li>
<li><p><strong>Service layer</strong>: This will consist in a few nodes gathering the data sent from the Frontend layer, transforming the messages to known standard formats and dispatches it to the appropriate receiver.</p>
</li>
<li><p><strong>Receivers layer</strong>: This is a bunch of nodes running only one specific receiver.</p>
</li>
</ul>
<p><img src="../assets/high_scalable.png" alt="High Scaling"/></p>
<footer class="footer">
<p>
<span class="line">
Built using
<a href="https://github.com/elixir-lang/ex_doc" title="ExDoc" rel="help" target="_blank">ExDoc</a> (v0.18.3),
</span>
<span class="line">
designed by
<a href="https://twitter.com/dignifiedquire" target="_blank" title="@dignifiedquire">Friedel Ziegelmayer</a>.
</span>
</p>
</footer>
</div>
</div>
</section>
</div>
<script src="dist/app-9bd040e5e5.js"></script>
</body>
</html>

96
doc/search.html Normal file
View File

@ -0,0 +1,96 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="ExDoc v0.18.3">
<title>Search poa_backend v0.1.0</title>
<link rel="stylesheet" href="dist/app-480ffdc169.css" />
<script src="dist/sidebar_items-ffeb4f1e51.js"></script>
</head>
<body data-type="search">
<script>try { if(localStorage.getItem('night-mode')) document.body.className += ' night-mode'; } catch (e) { }</script>
<div class="main">
<button class="sidebar-button sidebar-toggle">
<span class="icon-menu" aria-hidden="true"></span>
<span class="sr-only">Toggle Sidebar</span>
</button>
<button class="sidebar-button night-mode-toggle">
<span class="icon-theme" aria-hidden="true"></span>
<span class="sr-only">Toggle Theme</span>
</button>
<section class="sidebar">
<a href="api-reference.html" class="sidebar-projectLink">
<div class="sidebar-projectDetails">
<h1 class="sidebar-projectName">
poa_backend
</h1>
<h2 class="sidebar-projectVersion">
v0.1.0
</h2>
</div>
</a>
<form class="sidebar-search" action="search.html">
<button type="submit" class="search-button">
<span class="icon-search" aria-hidden="true"></span>
</button>
<input name="q" type="text" id="search-list" class="search-input" placeholder="Search" aria-label="Search" autocomplete="off" />
</form>
<ul class="sidebar-listNav">
<li><a id="extras-list" href="#full-list">Pages</a></li>
<li><a id="modules-list" href="#full-list">Modules</a></li>
</ul>
<div class="gradient"></div>
<ul id="full-list" class="sidebar-fullList"></ul>
</section>
<section class="content">
<div class="content-outer">
<div id="content" class="content-inner">
<div id="search">
<h1>Search</h1>
</div>
<footer class="footer">
<p>
<span class="line">
Built using
<a href="https://github.com/elixir-lang/ex_doc" title="ExDoc" rel="help" target="_blank">ExDoc</a> (v0.18.3),
</span>
<span class="line">
designed by
<a href="https://twitter.com/dignifiedquire" target="_blank" title="@dignifiedquire">Friedel Ziegelmayer</a>.
</span>
</p>
</footer>
</div>
</div>
</section>
</div>
<script src="dist/app-9bd040e5e5.js"></script>
</body>
</html>

View File

@ -23,61 +23,6 @@ defmodule POABackend.CustomHandler.REST do
This Pluting also defines the endpoints needed to use the POA Protocol.
## _hello_ endpoint
```
POST /hello
```
request:
```
Headers: {"content-type", "application/json"}
payload:
{
id: String() # agent id
secret: String() # secret string for authentication/authorisation
data: Object() # optional data for receivers (i.e. Dashboard needs specific data here)
}
```
responses:
| Code | Description |
| :--- | :---------- |
| 200 | Success _{"result":"success"}_ |
| 401 | Unauthorized |
| 415 | Unsupported Media Type (only _application/json_ allowed) |
| 422 | Unprocessable Entity. Required fields missing|
Example:
```
curl -v -d '{"id":"agentID", "secret":"mysecret", "data":"{}"}' -H "Content-Type: application/json" -X POST http://localhost:4002/hello
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 4002 (#0)
> POST /hello HTTP/1.1
> Host: localhost:4002
> User-Agent: curl/7.53.1
> Accept: */*
> Content-Type: application/json
> Content-Length: 50
>
* upload completely sent off: 50 out of 50 bytes
< HTTP/1.1 200 OK
< server: Cowboy
< date: Thu, 07 Jun 2018 20:33:06 GMT
< content-length: 20
< cache-control: max-age=0, private, must-revalidate
< content-type: application/json; charset=utf-8
<
* Connection #0 to host localhost left intact
{"result":"success"}
```
## _ping_ endpoint
```
@ -132,61 +77,6 @@ defmodule POABackend.CustomHandler.REST do
{"result":"success"}
```
## _latency_ endpoint
```
POST /latency
```
request:
```
Headers: {"content-type", "application/json"}
payload:
{
id: String() # agent id
secret: String() # secret string for authentication/authorisation
latency: Float() # latency in milliseconds
}
```
responses:
| Code | Description |
| :--- | :---------- |
| 200 | Success _{"result":"success"}_ |
| 401 | Unauthorized |
| 415 | Unsupported Media Type (only _application/json_ allowed) |
| 422 | Unprocessable Entity. Required fields missing|
Example:
```
curl -v -d '{"id":"agentID", "secret":"mysecret", "latency":22.0}' -H "Content-Type: application/json" -X POST http://localhost:4002/latency
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 4002 (#0)
> POST /latency HTTP/1.1
> Host: localhost:4002
> User-Agent: curl/7.53.1
> Accept: */*
> Content-Type: application/json
> Content-Length: 53
>
* upload completely sent off: 53 out of 53 bytes
< HTTP/1.1 200 OK
< server: Cowboy
< date: Fri, 08 Jun 2018 15:02:09 GMT
< content-length: 20
< cache-control: max-age=0, private, must-revalidate
< content-type: application/json; charset=utf-8
<
* Connection #0 to host localhost left intact
{"result":"success"}
```
## _data_ endpoint
```
@ -314,12 +204,6 @@ defmodule POABackend.CustomHandler.REST do
plug :match
plug :dispatch
post "/hello" do
conn
|> put_resp_content_type("application/json")
|> send_success_resp()
end
post "/ping" do
:ok = REST.ping_monitor(conn.params["id"])
@ -328,25 +212,6 @@ defmodule POABackend.CustomHandler.REST do
|> send_success_resp()
end
post "/latency" do
conn = REST.Plugs.RequiredFields.call(conn, ~w(latency))
with false <- conn.halted,
true <- is_float(conn.params["latency"])
do
conn
|> put_resp_content_type("application/json")
|> send_success_resp()
else
false ->
conn
|> send_resp(422, "")
|> halt
true ->
conn
end
end
post "/data" do
conn = REST.Plugs.RequiredFields.call(conn, ~w(type data))

View File

@ -12,33 +12,10 @@ defmodule POABackend.Protocol do
Only those calls are allowed:
* session (*not implemented*) - In future in order to add authentication / authorization
* hello - Message sent when starting a communication with the backend
* ping - Ping message
* latency - The Agent will calculate the latency and send it to the Backend
* data - Specific message for a given receiver. It can be a metric itself or something else
* bye - Message sent when the Agent wants to close the communication explicitly
#### hello call
abstract request:
```json
{
id: String() # agent id
secret: String() # secret string for authentication/authorisation
data: Object() # optional data for receivers (i.e. Dashboard needs specific data here)
}
```
response:
```json
{
result: String() # “success” or “error”
payload: any() # optional payload
}
```
#### ping call
abstract request:
@ -60,28 +37,6 @@ defmodule POABackend.Protocol do
}
```
#### latency call
abstract request:
```json
{
id: String() # agent id
secret: String() # secret string for authentication/authorisation
latency: Float() # latency in milliseconds
}
```
response:
```json
{
result: String() # “success” or “error”
payload: String() # optional payload
}
```
#### data call
abstract request:

View File

@ -13,7 +13,7 @@ defmodule POABackend.Protocol.Message do
* `agent_id` - The Agent Id which sent the message to the backend.
* `data_type` - The kind of data the message is carring. For now only `ethereum_metric` type is defined.
* `message_type` - This is the message type according to the custom protocol. Only `hello`, `data` and `latency` are defined
* `message_type` - This is the message type according to the custom protocol. Only `data` and `bye` are defined for now
* `assigns` - Shared user data as a map
* `data` - The message payloda. It is a map

View File

@ -1,19 +1,20 @@
defmodule POABackend.Protocol.MessageType do
@moduledoc """
Regarding the POA Protocol only 3 types of message can be processed in the backend.
Regarding the POA Protocol only 2 types of message can be processed in the backend.
Those message types are
* `hello` - When the communication starts
* `data` - When data is sent to the backend. Data is also called "metric data"
* `latency` - When the agent sent the latency value
* `bye` - When the client wants to stop the communication
__NOTE__ New message types can be added in future while the protocol is extended
"""
@typedoc """
The message type. Only `hello`, `data` and `latency` are allowed
The message type. Only `data` and `bye` are allowed
"""
@type t :: :hello | :data | :latency
@type t :: :data | :bye
end

View File

@ -51,8 +51,9 @@ defmodule POABackend.MixProject do
defp docs do
[
source_ref: "v#{@version}",
main: "POABackend",
# main: "POABackend",
source_url: "https://github.com/poanetwork/poa-netstats-wharehouse",
extras: ["pages/initial_architecture.md": [filename: "initial_architecture", title: "Initial Architecture"]],
groups_for_modules: [
"POA Protocol": [
POABackend.Protocol,

View File

@ -0,0 +1,41 @@
# Server Architecture
This is the diagram for the new Elixir-based architecture. We propose a new server layer between the Agents and the Sinks (with the Dashboard UI being a type of sink).
![General Overview](../assets/general_overview.png)
The Backend Server is the actor in this new Server layer. It is in charge of speaking with the Agents, receiving Data / Metrics, converting the data from the protocol messages to Elixir structures and dispatching the result to different Receivers based on a mapping in the config file.
![Backend Architecture](../assets/backend_architecture.png)
Key points:
- __Custom Protocol__: The custom Protocol is the language the Agents Transfer and Custom Protocol Handler must speak. That defines the messages and data which can be exchanged.
The messages defined in the protocol can be pure JSON for now but we must think in other lighter options like messagepack
The messages will have (among others) a mandatory field for the “type of data” sent. The possible values for this field will be defined and are fixed, for now only an “ethereum_metrics” type exists. That will allow us to map the type of metric to the receiver (i.e. sending ethereum_metrics to the dashboard and system_metrics to a database)
__With this decision we remove the PRIMUS protocol__
- __Custom Protocol Handler__: The communication between the Agents and the Backend Server is done with a custom protocol over Websockets (for now) but it is extensible (via Plugins) to different technologies like REST endpoints over HTTP or others. In order to support a new technology here we have to implement a new Custom Protocol Handler plugin and it will involve a new Agent Transfer too.
It will be a simple Websockets server for now (probably with a light version of Phoenix or Cowboy directly).
Each request will be executed in a separate process (handled by Cowboy/Phoenix) and will be responsible of decoding the messages from the Custom Protocol to Elixir structs.
Bottom line is the Agents Transfer speaks with the Custom Protocol Handler
- __Receivers__: The Custom Protocol Handler will dispatch the messages to the Receivers processes based on the “type of data” field.
Receivers are going to be Plugins, where anyone can create its own plugin and extend the system. For now the only Receiver will be the Dashboard Receiver which will be in charge of transferring the messages to the Dashboard but we can create more Receivers like one for storing metrics in a AWS DynamoDB.
The means to map the receivers with the type of data will be specified in the config file (as we are doing for the Agents) i.e., we can map “ethereum_metrics” going to the Dashboard Receiver and AWS DynamoDB Receiver and “system_metrics” to only the AWS DynamoDB Receiver.
- __Sinks__: The receivers can do anything with the data. They can send metrics to the Dashboard UI, send data to External Databases or whatever we want. For that we have to write our own Receiver and map it to the messages we want in the config file and adding our desired behaviour.
The Dashboard UI (NodeJS) will be refactored and modified in order to speak directly with the Receiver instead of directly with the Agents. We have to modify this communication and create a new protocol.
This new Backend Server layer allow us to scale if the systems requires it. The way we will scale is adding more Backend Server nodes to the system
![Scaling](../assets/scaling.png)
f the system grows exponentially and the presented distributed architecture is not enough, the plugin system and the APIs will allow us to migrate to a microservice architecture easily. We will have 3 independent layers:
- __Frontend layer__: This will consist in many nodes (as needed) implementing only one type of Customer Protocol Handler.
- __Service layer__: This will consist in a few nodes gathering the data sent from the Frontend layer, transforming the messages to known standard formats and dispatches it to the appropriate receiver.
- __Receivers layer__: This is a bunch of nodes running only one specific receiver.
![High Scaling](../assets/high_scalable.png)

View File

@ -5,41 +5,6 @@ defmodule CustomHandler.RESTTest do
@base_url "localhost:4002"
# ----------------------------------------
# /hello Endpoint Tests
# ----------------------------------------
test "testing the REST /hello endpoint" do
url = @base_url <> "/hello"
{:ok, data} = Poison.encode(%{id: "agentID", secret: "mysecret", data: %{hello: "world"}})
headers = [{"Content-Type", "application/json"}]
{200, %{"result" => "success"}} = post(url, data, headers)
end
test "testing the REST /hello endpoint without content-type" do
url = @base_url <> "/hello"
{:ok, data} = Poison.encode(%{id: "agentID", secret: "mysecret", data: %{hello: "world"}})
{415, :nobody} = post(url, data, [])
end
test "testing the REST /hello endpoint without required fields" do
url = @base_url <> "/hello"
{:ok, data} = Poison.encode(%{id: "agentID", data: %{hello: "world"}})
headers = [{"Content-Type", "application/json"}]
{422, :nobody} = post(url, data, headers)
end
test "testing the REST /hello endpoint with wrong secret" do
url = @base_url <> "/hello"
{:ok, data} = Poison.encode(%{id: "agentID", secret: "wrong_secret", data: %{hello: "world"}})
headers = [{"Content-Type", "application/json"}]
{401, :nobody} = post(url, data, headers)
end
# ----------------------------------------
# /ping Endpoint Tests
# ----------------------------------------
@ -121,57 +86,6 @@ defmodule CustomHandler.RESTTest do
assert_receive :inactive_received, 20_000
end
# ----------------------------------------
# /latency Endpoint Tests
# ----------------------------------------
test "testing the REST /latency endpoint" do
url = @base_url <> "/latency"
{:ok, data} = Poison.encode(%{id: "agentID", secret: "mysecret", latency: 15.0})
headers = [{"Content-Type", "application/json"}]
{200, %{"result" => "success"}} = post(url, data, headers)
end
test "testing the REST /latency endpoint without content-type" do
url = @base_url <> "/latency"
{:ok, data} = Poison.encode(%{id: "agentID", secret: "mysecret", latency: 15.0})
{415, :nobody} = post(url, data, [])
end
test "testing the REST /latency endpoint without required fields" do
url = @base_url <> "/latency"
{:ok, data} = Poison.encode(%{id: "agentID", latency: 15.0})
headers = [{"Content-Type", "application/json"}]
{422, :nobody} = post(url, data, headers)
end
test "testing the REST /latency endpoint without latency field" do
url = @base_url <> "/latency"
{:ok, data} = Poison.encode(%{id: "agentID", secret: "mysecret"})
headers = [{"Content-Type", "application/json"}]
{422, :nobody} = post(url, data, headers)
end
test "testing the REST /latency endpoint with wrong latency field" do
url = @base_url <> "/latency"
{:ok, data} = Poison.encode(%{id: "agentID", secret: "mysecret", latency: "no number"})
headers = [{"Content-Type", "application/json"}]
{422, :nobody} = post(url, data, headers)
end
test "testing the REST /latency endpoint with wrong secret" do
url = @base_url <> "/latency"
{:ok, data} = Poison.encode(%{id: "agentID", secret: "wrong_secret", latency: 15.0})
headers = [{"Content-Type", "application/json"}]
{401, :nobody} = post(url, data, headers)
end
# ----------------------------------------
# /data Endpoint Tests
# ----------------------------------------