From 2bede602c2113297e6a36ffd14f4f1b459920c87 Mon Sep 17 00:00:00 2001
From: Felipe Ripoll
Date: Wed, 29 Aug 2018 08:05:59 -0600
Subject: [PATCH] [#59] improving documentation
---
README.md | 41 +-
config/config.exs | 8 +
config/prod.exs | 2 +-
doc/.build | 5 +-
doc/404.html | 2 +-
doc/POABackend.Auth.Guardian.Plug.html | 2 +-
doc/POABackend.Auth.Models.Token.html | 2 +-
doc/POABackend.Auth.Models.User.html | 2 +-
doc/POABackend.Auth.REST.html | 2 +-
doc/POABackend.Auth.html | 22 +-
doc/POABackend.CustomHandler.REST.html | 2 +-
doc/POABackend.CustomHandler.html | 2 +-
doc/POABackend.Protocol.DataType.html | 2 +-
doc/POABackend.Protocol.Message.html | 2 +-
doc/POABackend.Protocol.MessageType.html | 2 +-
doc/POABackend.Protocol.html | 2 +-
doc/POABackend.Receiver.html | 2 +-
doc/POABackend.Receivers.Dashboard.html | 2 +-
doc/POABackend.Receivers.DynamoDB.html | 2 +-
doc/POABackend.Receivers.Eth.Stats.html | 336 ++++
doc/POABackend.Receivers.Repo.html | 1852 ++++++++++++++++++++
doc/POABackend.Receivers.System.Stats.html | 336 ++++
doc/POABackend.html | 50 +-
doc/api-reference.html | 22 +-
doc/dist/sidebar_items-3739fd4c82.js | 1 -
doc/dist/sidebar_items-3d14d8fe9b.js | 1 +
doc/initial_architecture.html | 2 +-
doc/search.html | 2 +-
lib/poa_backend.ex | 41 +-
lib/poa_backend/receivers/eth/stats.ex | 15 +-
lib/poa_backend/receivers/system/stats.ex | 15 +-
mix.exs | 4 +-
32 files changed, 2733 insertions(+), 50 deletions(-)
create mode 100644 doc/POABackend.Receivers.Eth.Stats.html
create mode 100644 doc/POABackend.Receivers.Repo.html
create mode 100644 doc/POABackend.Receivers.System.Stats.html
delete mode 100644 doc/dist/sidebar_items-3739fd4c82.js
create mode 100644 doc/dist/sidebar_items-3d14d8fe9b.js
diff --git a/README.md b/README.md
index 6eb896d..8909cb8 100644
--- a/README.md
+++ b/README.md
@@ -19,23 +19,56 @@ mix docs
That command will create a `doc/` folder with the actual Documentation.
-## Run Tests
+## Configuring Databases for first time
-`POABackend` uses [Mnesia](http://erlang.org/doc/man/mnesia.html) as a local database with [Ecto](https://hexdocs.pm/ecto/Ecto.html). In order to have this running we have to create a folder where `Mnesia` will store our data. In order to do that we have to define it in the `config/test.exs` file like this:
+`POABackend` uses many Databases. For Authentication we use [Mnesia](http://erlang.org/doc/man/mnesia.html) as a local database and for some receivers which require storage we use Postgres. All databases are managed on top of [Ecto](https://hexdocs.pm/ecto/Ecto.html) a widly used database wrapper for Elixir projects.
+
+For this reason we have to set the databases before running the `POABackend` for the first time.
+
+- Auth Database (Mnesia): Setting up Mnesia is easy since it is working localy and is built in the Erlang Virtual Machine. We only have to say "where" we are going to store the database's files. In order to do that we have to add the configuration to the config file (`prod.exs` or `test.exs` depending if you want to run tests or production)
```
config :mnesia,
dir: 'your/local/path' # make sure this directory exists!
```
-once we have the path defined we have to create the database (those commands must be run only once if you are going to use always this same path for testing). In your root folder run:
+- Receivers Database (Postgres): This is a little more complex than Mnesia. We need a Postgres instance running somewhere and we have to add the config to the config files
+
+```
+config :poa_backend, POABackend.Receivers.Repo,
+ priv: "priv/receivers", # this value is not changed
+ adapter: Ecto.Adapters.Postgres,
+ database: "poabackend_stats",
+ username: "postgres",
+ password: "postgres",
+ hostname: "localhost"
+```
+
+The important fields here are `database`, `username`, `password` and `hostname`. The rest of values must remain exactly as the example.
+
+Once we have set the database configuration we have to create and migrate the databases, in order to do that we should be in the root of the project and run:
+
+- for production
+
+```
+MIX_ENV=prod mix ecto.create
+MIX_ENV=prod mix ecto.migrate
+```
+
+- for test
```
MIX_ENV=test mix ecto.create
MIX_ENV=test mix ecto.migrate
```
-Now the environment is set. We can run the tests with:
+Now the environment is ready for running `POABackend`
+
+## Run Tests
+
+The first time you run the tests you will need having the Database's environment set up. Check the previous section and set the configuration in the `config/test.exs` file.
+
+Once the environment is set. We can run the tests with:
```
mix test
diff --git a/config/config.exs b/config/config.exs
index fc116b8..1f27a30 100644
--- a/config/config.exs
+++ b/config/config.exs
@@ -23,4 +23,12 @@ config :poa_backend, POABackend.Auth.Repo,
config :mnesia,
dir: 'priv/data/mnesia' # make sure this directory exists!
+config :poa_backend, POABackend.Receivers.Repo,
+ priv: "priv/receivers", # this value is not changed
+ adapter: Ecto.Adapters.Postgres,
+ database: "poabackend_stats",
+ username: "postgres",
+ password: "postgres",
+ hostname: "localhost"
+
import_config "#{Mix.env}.exs"
diff --git a/config/prod.exs b/config/prod.exs
index 48ec67f..f61b63c 100644
--- a/config/prod.exs
+++ b/config/prod.exs
@@ -85,7 +85,7 @@ config :mnesia,
dir: 'priv/data/mnesia' # make sure this directory exists!
config :poa_backend, POABackend.Receivers.Repo,
- priv: "priv/receivers",
+ priv: "priv/receivers", # this value is not changed
adapter: Ecto.Adapters.Postgres,
database: "poabackend_stats",
username: "postgres",
diff --git a/doc/.build b/doc/.build
index 20cb5e2..3f67fef 100644
--- a/doc/.build
+++ b/doc/.build
@@ -4,12 +4,13 @@ fonts/icomoon.eot
fonts/icomoon.svg
fonts/icomoon.ttf
fonts/icomoon.woff
-dist/sidebar_items-3739fd4c82.js
+dist/sidebar_items-3d14d8fe9b.js
api-reference.html
initial_architecture.html
search.html
404.html
POABackend.html
+POABackend.Receivers.Repo.html
POABackend.Auth.html
POABackend.Auth.Guardian.Plug.html
POABackend.Auth.Models.Token.html
@@ -24,4 +25,6 @@ POABackend.CustomHandler.REST.html
POABackend.Receiver.html
POABackend.Receivers.Dashboard.html
POABackend.Receivers.DynamoDB.html
+POABackend.Receivers.Eth.Stats.html
+POABackend.Receivers.System.Stats.html
index.html
diff --git a/doc/404.html b/doc/404.html
index 48ca53c..f0ca307 100644
--- a/doc/404.html
+++ b/doc/404.html
@@ -8,7 +8,7 @@
404 – poa_backend v0.1.0
-
+
diff --git a/doc/POABackend.Auth.Guardian.Plug.html b/doc/POABackend.Auth.Guardian.Plug.html
index fdbacb4..24255c0 100644
--- a/doc/POABackend.Auth.Guardian.Plug.html
+++ b/doc/POABackend.Auth.Guardian.Plug.html
@@ -8,7 +8,7 @@
POABackend.Auth.Guardian.Plug – poa_backend v0.1.0
-
+
diff --git a/doc/POABackend.Auth.Models.Token.html b/doc/POABackend.Auth.Models.Token.html
index 7a8e395..bcd2e3c 100644
--- a/doc/POABackend.Auth.Models.Token.html
+++ b/doc/POABackend.Auth.Models.Token.html
@@ -8,7 +8,7 @@
POABackend.Auth.Models.Token – poa_backend v0.1.0
-
+
diff --git a/doc/POABackend.Auth.Models.User.html b/doc/POABackend.Auth.Models.User.html
index 3afa4ef..c84b08e 100644
--- a/doc/POABackend.Auth.Models.User.html
+++ b/doc/POABackend.Auth.Models.User.html
@@ -8,7 +8,7 @@
POABackend.Auth.Models.User – poa_backend v0.1.0
-
+
diff --git a/doc/POABackend.Auth.REST.html b/doc/POABackend.Auth.REST.html
index 56f8ebf..eb186a9 100644
--- a/doc/POABackend.Auth.REST.html
+++ b/doc/POABackend.Auth.REST.html
@@ -8,7 +8,7 @@
POABackend.Auth.REST – poa_backend v0.1.0
-
+
diff --git a/doc/POABackend.Auth.html b/doc/POABackend.Auth.html
index 656f55b..3db7c08 100644
--- a/doc/POABackend.Auth.html
+++ b/doc/POABackend.Auth.html
@@ -8,7 +8,7 @@
POABackend.Auth – poa_backend v0.1.0
-
+
@@ -318,7 +318,7 @@ with that name in the database already
authenticate_admin(admin_name, password)
-
+ View Source
@@ -378,7 +378,7 @@ with that name in the database already
create_banned_token(jwt_token)
-
+ View Source
@@ -409,7 +409,7 @@ This function will extract the expiration time from the claims and store them in
create_banned_token(token, expires)
-
+ View Source
@@ -504,7 +504,7 @@ expiration time as Integer.
generate_password()
-
+ View Source
@@ -533,7 +533,7 @@ expiration time as Integer.
generate_user_name()
-
+ View Source
@@ -562,7 +562,7 @@ expiration time as Integer.
generate_user_name(user_name)
-
+ View Source
@@ -620,7 +620,7 @@ expiration time as Integer.
purge_banned_tokens()
-
+ View Source
@@ -678,7 +678,7 @@ expiration time as Integer.
token_banned?(token)
-
+ View Source
@@ -736,7 +736,7 @@ expiration time as Integer.
valid_token?(jwt_token)
-
+ View Source
@@ -765,7 +765,7 @@ expiration time as Integer.
valid_user_name?(user_name)
-
+ View Source
diff --git a/doc/POABackend.CustomHandler.REST.html b/doc/POABackend.CustomHandler.REST.html
index 9a7d8a5..8288db7 100644
--- a/doc/POABackend.CustomHandler.REST.html
+++ b/doc/POABackend.CustomHandler.REST.html
@@ -8,7 +8,7 @@
POABackend.CustomHandler.REST – poa_backend v0.1.0
-
+
diff --git a/doc/POABackend.CustomHandler.html b/doc/POABackend.CustomHandler.html
index 5c183ff..72bb231 100644
--- a/doc/POABackend.CustomHandler.html
+++ b/doc/POABackend.CustomHandler.html
@@ -8,7 +8,7 @@
POABackend.CustomHandler – poa_backend v0.1.0
-
+
diff --git a/doc/POABackend.Protocol.DataType.html b/doc/POABackend.Protocol.DataType.html
index 4eba283..cd7e666 100644
--- a/doc/POABackend.Protocol.DataType.html
+++ b/doc/POABackend.Protocol.DataType.html
@@ -8,7 +8,7 @@
POABackend.Protocol.DataType – poa_backend v0.1.0
-
+
diff --git a/doc/POABackend.Protocol.Message.html b/doc/POABackend.Protocol.Message.html
index b2dd061..f43cfb5 100644
--- a/doc/POABackend.Protocol.Message.html
+++ b/doc/POABackend.Protocol.Message.html
@@ -8,7 +8,7 @@
POABackend.Protocol.Message – poa_backend v0.1.0
-
+
diff --git a/doc/POABackend.Protocol.MessageType.html b/doc/POABackend.Protocol.MessageType.html
index db7eef2..24713f2 100644
--- a/doc/POABackend.Protocol.MessageType.html
+++ b/doc/POABackend.Protocol.MessageType.html
@@ -8,7 +8,7 @@
POABackend.Protocol.MessageType – poa_backend v0.1.0
-
+
diff --git a/doc/POABackend.Protocol.html b/doc/POABackend.Protocol.html
index b475403..8dec9ae 100644
--- a/doc/POABackend.Protocol.html
+++ b/doc/POABackend.Protocol.html
@@ -8,7 +8,7 @@
POABackend.Protocol – poa_backend v0.1.0
-
+
diff --git a/doc/POABackend.Receiver.html b/doc/POABackend.Receiver.html
index 44a1049..792b608 100644
--- a/doc/POABackend.Receiver.html
+++ b/doc/POABackend.Receiver.html
@@ -8,7 +8,7 @@
POABackend.Receiver – poa_backend v0.1.0
-
+
diff --git a/doc/POABackend.Receivers.Dashboard.html b/doc/POABackend.Receivers.Dashboard.html
index 22bbb83..80307ca 100644
--- a/doc/POABackend.Receivers.Dashboard.html
+++ b/doc/POABackend.Receivers.Dashboard.html
@@ -8,7 +8,7 @@
POABackend.Receivers.Dashboard – poa_backend v0.1.0
-
+
diff --git a/doc/POABackend.Receivers.DynamoDB.html b/doc/POABackend.Receivers.DynamoDB.html
index 3c2ab40..c036af4 100644
--- a/doc/POABackend.Receivers.DynamoDB.html
+++ b/doc/POABackend.Receivers.DynamoDB.html
@@ -8,7 +8,7 @@
POABackend.Receivers.DynamoDB – poa_backend v0.1.0
-
+
diff --git a/doc/POABackend.Receivers.Eth.Stats.html b/doc/POABackend.Receivers.Eth.Stats.html
new file mode 100644
index 0000000..003e6b8
--- /dev/null
+++ b/doc/POABackend.Receivers.Eth.Stats.html
@@ -0,0 +1,336 @@
+
+
+
+
+
+
+
+ POABackend.Receivers.Eth.Stats – poa_backend v0.1.0
+
+
+
+
+
+
+
+
+
+
+
+
This is a Receiver Plugin which is in charge of storing the Ethereum Statistics received from the Agents in a Postgres
+database. If we want to use it we have to declare it in the Config file, inside the :receivers section, ie:
This Plugin uses Postgres as a backend, specifically the eth_stats table. Make sure that table exists before using
+this Plugin.
+
We also need to subscribe this plugin to :ethereum_metrics metrics in the config file. For that we have to add this line
+to the list in the :subscriptions section:
A callback executed when the Receiver Plugin starts.
+ The argument is retrieved from the configuration file when the Receiver is defined
+ It must return {:ok, state}, that state will be keept as in GenServer and can be
+ retrieved in the metrics_received/3 function
This function is called when a Custom Handler detects a client is inactive.
+
The Custom Handler must to call explicity to POABackend.CustomHandler.publish_inactive/1 and it will publish the
+ inactive message to all the metrics in the system (defined in the config file).
A callback executed when the Receiver Plugin starts.
+ The argument is retrieved from the configuration file when the Receiver is defined
+ It must return {:ok, state}, that state will be keept as in GenServer and can be
+ retrieved in the metrics_received/3 function.
Returns a lazy enumerable that emits all entries from the data store
+matching the given query. SQL adapters, such as Postgres and MySQL, can only
+enumerate a stream inside a transaction
Calculate the given aggregate over the given field.
+
If the query has a limit, offset or distinct set, it will be
+automatically wrapped in a subquery in order to return the
+proper result.
+
Any preload or select in the query will be ignored in favor of
+the column being aggregated.
+
The aggregation will fail if any group_by field is set.
+
+
+ Options
+
+
+
See the “Shared options” section at the module documentation.
+
+
+ Examples
+
+
+
# Returns the number of visits per blog post
+Repo.aggregate(Post, :count, :visits)
+
+# Returns the average number of visits for the top 10
+query = from Post, limit: 10
+Repo.aggregate(query, :avg, :visits)
:prefix - The prefix to run the query on (such as the schema path
+in Postgres or the database in MySQL). This overrides the prefix set
+in the query.
+
+
+
See the “Shared options” section at the module documentation.
+
+
+ Example
+
+
+
# Fetch all post titles
+query = from p in Post,
+ select: p.title
+MyRepo.all(query)
It returns {:ok, struct} if the struct has been successfully
+deleted or {:error, changeset} if there was a validation
+or a known constraint error.
+
+
+ Options
+
+
+
+
:prefix - The prefix to run the query on (such as the schema path
+in Postgres or the database in MySQL). This overrides the prefix set
+in the struct.
+
+
+
See the “Shared options” section at the module documentation.
+
+
+ Example
+
+
+
post = MyRepo.get!(Post, 42)
+case MyRepo.delete post do
+ {:ok, struct} -> # Deleted with success
+ {:error, changeset} -> # Something went wrong
+end
It returns a tuple containing the number of entries
+and any returned result as second element. If the database
+does not support RETURNING in DELETE statements or no
+return result was selected, the second element will be nil.
+
+
+ Options
+
+
+
+
:returning - selects which fields to return. When true,
+returns all fields in the given struct. May be a list of
+fields, where a struct is still returned but only with the
+given fields. Or false, where nothing is returned (the default).
+This option is not supported by all databases.
+
+
:prefix - The prefix to run the query on (such as the schema path
+in Postgres or the database in MySQL). This overrides the prefix set
+in the query.
+
+
+
See the “Shared options” section at the module documentation for
+remaining options.
+
+
+ Examples
+
+
+
MyRepo.delete_all(Post)
+
+from(p in Post, where: p.id < 10) |> MyRepo.delete_all
In case a struct is given, the struct is converted into a changeset
+with all non-nil fields as part of the changeset.
+
In case a changeset is given, the changes in the changeset are
+merged with the struct fields, and all of them are sent to the
+database.
+
It returns {:ok, struct} if the struct has been successfully
+inserted or {:error, changeset} if there was a validation
+or a known constraint error.
+
+
+ Options
+
+
+
+
:prefix - The prefix to run the query on (such as the schema path
+in Postgres or the database in MySQL). This overrides the prefix set
+in the struct.
+
+
:on_conflict - It may be one of :raise (the default), :nothing,
+:replace_all, a keyword list of update instructions or an Ecto.Query
+query for updates. See the “Upserts” section for more information.
+
+
:conflict_target - Which columns to verify for conflicts. If
+none is specified, the conflict target is left up to the database
+and is usually made of primary keys and/or unique/exclusion constraints.
+
+
+
See the “Shared options” section at the module documentation.
+
+
+ Examples
+
+
+
A typical example is calling MyRepo.insert/1 with a struct
+and acting on the return value:
+
case MyRepo.insert %Post{title: "Ecto is great"} do
+ {:ok, struct} -> # Inserted with success
+ {:error, changeset} -> # Something went wrong
+end
+
+
+ Upserts
+
+
+
insert_all provides upserts (update or inserts) via the :on_conflict
+option. The :on_conflict option supports the following values:
+
+
:raise - raises if there is a conflicting primary key or unique index
+
+
:nothing - ignores the error in case of conflicts
+
+
:replace_all - replace all entries in the database by the one being
+currently attempted
+
+
a keyword list of update instructions - such as the one given to
+c:update_all/3, for example: [set: [title: "new title"]]
+
+
an Ecto.Query that will act as an UPDATE statement, such as the
+one given to c:update_all/3
+
+
+
Upserts map to “ON CONFLICT” on databases like Postgres and “ON DUPLICATE KEY”
+on databases such as MySQL.
+
As an example, imagine :title is marked as a unique column in
+the database:
+
# Insert it once
+{:ok, inserted} = MyRepo.insert(%Post{title: "this is unique"})
+
+# Insert with the same title but do nothing on conflicts.
+# Keep in mind that, although this returns :ok, the returned
+# struct does not reflect the data in the database. For instance,
+# in case of "on_conflict: :nothing", the returned post has no ID.
+{:ok, ignored} = MyRepo.insert(%Post{title: "this is unique"}, on_conflict: :nothing)
+assert ignored.id == nil
+
+# Now let's insert with the same title but use a query to update
+# a column on conflicts. Although this returns :ok and a struct with
+# the existing ID for successful operations, the other columns may
+# not necessarily reflect the data in the database. In fact, any
+# operation done on `:on_conflict` won't be automatically mapped to
+# the struct.
+
+# In Postgres (it requires the conflict target for updates):
+on_conflict = [set: [body: "updated"]]
+{:ok, updated} = MyRepo.insert(%Post{title: "this is unique"},
+ on_conflict: on_conflict, conflict_target: :title)
+
+# In MySQL (conflict target is not supported):
+on_conflict = [set: [title: "updated"]]
+{:ok, updated} = MyRepo.insert(%Post{id: inserted.id, title: "updated"},
+ on_conflict: on_conflict)
It expects a schema (MyApp.User) or a source ("users") or
+both ({"users", MyApp.User}) as the first argument. The second
+argument is a list of entries to be inserted, either as keyword
+lists or as maps.
+
It returns a tuple containing the number of entries
+and any returned result as second element. If the database
+does not support RETURNING in UPDATE statements or no
+return result was selected, the second element will be nil.
+
When a schema is given, the values given will be properly dumped
+before being sent to the database. If the schema contains an
+autogenerated ID field, it will be handled either at the adapter
+or the storage layer. However any other autogenerated value, like
+timestamps, won’t be autogenerated when using c:insert_all/3.
+This is by design as this function aims to be a more direct way
+to insert data into the database without the conveniences of
+c:insert/2. This is also consistent with c:update_all/3 that
+does not handle timestamps as well.
+
If a source is given, without a schema, the given fields are passed
+as is to the adapter.
+
+
+ Options
+
+
+
+
:returning - selects which fields to return. When true,
+returns all fields in the given struct. May be a list of
+fields, where a struct is still returned but only with the
+given fields. Or false, where nothing is returned (the default).
+This option is not supported by all databases.
+
+
:prefix - The prefix to run the query on (such as the schema path
+in Postgres or the database in MySQL).
+
+
:on_conflict - It may be one of :raise (the default), :nothing,
+:replace_all, a keyword list of update instructions or an Ecto.Query
+query for updates. See the “Upserts” section for more information.
+
+
:conflict_target - Which columns to verify for conflicts. If
+none is specified, the conflict target is left up to the database
+and is usually made of primary keys and/or unique/exclusion constraints.
+
+
+
See the “Shared options” section at the module documentation for
+remaining options.
+
+
+ Examples
+
+
+
MyRepo.insert_all(Post, [[title: "My first post"], [title: "My second post"]])
+MyRepo.insert_all(Post, [%{title: "My first post"}, %{title: "My second post"}])
+
+
+ Upserts
+
+
+
insert_all provides upserts (update or inserts) via the :on_conflict
+option. The :on_conflict option supports the following values:
+
+
:raise - raises if there is a conflicting primary key or unique index
+
+
:nothing - ignores the error in case of conflicts
+
+
:replace_all - replace all entries in the database by the one being
+currently attempted
+
+
a keyword list of update instructions - such as the one given to
+c:update_all/3, for example: [set: [title: "new title"]]
+
+
an Ecto.Query that will act as an UPDATE statement, such as the
+one given to c:update_all/3
+
+
+
Upserts map to “ON CONFLICT” on databases like Postgres and “ON DUPLICATE KEY”
+on databases such as MySQL.
+
+
+ Return values
+
+
+
By default, both Postgres and MySQL return the amount of entries
+inserted on insert_all. However, when the :on_conflict option
+is specified, Postgres will only return a row if it was affected
+while MySQL returns at least the number of entries attempted.
+
For example, if :on_conflict is set to :nothing, Postgres will
+return 0 if no new entry was added while MySQL will still return
+the amount of entries attempted to be inserted, even if no entry
+was added. Even worse, if :on_conflict is query, MySQL will return
+the number of attempted entries plus the number of entries modified
+by the UPDATE query.
Inserts or updates a changeset depending on whether the struct is persisted
+or not.
+
The distinction whether to insert or update will be made on the
+Ecto.Schema.Metadata field :state. The :state is automatically set by
+Ecto when loading or building a schema.
+
Please note that for this to work, you will have to load existing structs from
+the database. So even if the struct exists, this won’t work:
:prefix - The prefix to run the query on (such as the schema path
+in Postgres or the database in MySQL). This overrides the prefix set
+in the struct.
+
+
+
See the “Shared options” section at the module documentation.
+
+
+ Example
+
+
+
result =
+ case MyRepo.get(Post, id) do
+ nil -> %Post{id: id} # Post not found, we build one
+ post -> post # Post exists, let's use it
+ end
+ |> Post.changeset(changes)
+ |> MyRepo.insert_or_update
+
+case result do
+ {:ok, struct} -> # Inserted or updated with success
+ {:error, changeset} -> # Something went wrong
+end
The first argument can be a schema, or a map (of types) and determines the return value:
+a struct or a map, respectively.
+
The second argument data specifies fields and values that are to be loaded.
+It can be a map, a keyword list, or a {fields, values} tuple.
+Fields can be atoms or strings.
+
Fields that are not present in the schema (or types map) are ignored.
+If any of the values has invalid type, an error is raised.
Preloads all associations on the given struct or structs.
+
This is similar to Ecto.Query.preload/3 except it allows
+you to preload structs after they have been fetched from the
+database.
+
In case the association was already loaded, preload won’t attempt
+to reload it.
+
+
+ Options
+
+
+
Besides the “Shared options” section at the module documentation,
+it accepts:
+
+
:force - By default, Ecto won’t preload associations that
+are already loaded. By setting this option to true, any existing
+association will be discarded and reloaded.
+
+
:in_parallel - If the preloads must be done in parallel. It can
+only be performed when we have more than one preload and the
+repository is not in a transaction. Defaults to true.
+
+
:prefix - the prefix to fetch preloads from. By default, queries
+will use the same prefix as the one in the given collection. This
+option allows the prefix to be changed.
+
Returns a lazy enumerable that emits all entries from the data store
+matching the given query. SQL adapters, such as Postgres and MySQL, can only
+enumerate a stream inside a transaction.
:prefix - The prefix to run the query on (such as the schema path
+in Postgres or the database in MySQL). This overrides the prefix set
+in the query
+
+
:max_rows - The number of rows to load from the database as we stream.
+It is supported at least by Postgres and MySQL and defaults to 500.
+
+
+
See the “Shared options” section at the module documentation.
+
+
+ Example
+
+
+
# Fetch all post titles
+query = from p in Post,
+ select: p.title
+stream = MyRepo.stream(query)
+MyRepo.transaction(fn() ->
+ Enum.to_list(stream)
+end)
Runs the given function or Ecto.Multi inside a transaction.
+
+
+ Use with function
+
+
+
If an unhandled error occurs the transaction will be rolled back
+and the error will bubble up from the transaction function.
+If no error occurred the transaction will be committed when the
+function returns. A transaction can be explicitly rolled back
+by calling rollback/1, this will immediately leave the function
+and return the value given to rollback as {:error, value}.
+
A successful transaction returns the value returned by the function
+wrapped in a tuple as {:ok, value}.
+
If transaction/2 is called inside another transaction, the function
+is simply executed, without wrapping the new transaction call in any
+way. If there is an error in the inner transaction and the error is
+rescued, or the inner transaction is rolled back, the whole outer
+transaction is marked as tainted, guaranteeing nothing will be committed.
+
+
+ Use with Ecto.Multi
+
+
+
Besides functions transaction can be used with an Ecto.Multi struct.
+Transaction will be started, all operations applied and in case of
+success committed returning {:ok, changes}. In case of any errors
+the transaction will be rolled back and
+{:error, failed_operation, failed_value, changes_so_far} will be
+returned.
+
You can read more about using transactions with Ecto.Multi as well as
+see some examples in the Ecto.Multi documentation.
+
+
+ Options
+
+
+
See the “Shared options” section at the module documentation.
+
+
+ Examples
+
+
+
MyRepo.transaction(fn ->
+ MyRepo.update!(%{alice | balance: alice.balance - 10})
+ MyRepo.update!(%{bob | balance: bob.balance + 10})
+end)
+
+# Roll back a transaction explicitly
+MyRepo.transaction(fn ->
+ p = MyRepo.insert!(%Post{})
+ if not Editor.post_allowed?(p) do
+ MyRepo.rollback(:posting_not_allowed)
+ end
+end)
+
+# With Ecto.Multi
+Ecto.Multi.new
+|> Ecto.Multi.insert(:post, %Post{})
+|> MyRepo.transaction
A changeset is required as it is the only mechanism for
+tracking dirty changes. Only the fields present in the changes part
+of the changeset are sent to the database. Any other, in-memory
+changes done to the schema are ignored.
It returns {:ok, struct} if the struct has been successfully
+updated or {:error, changeset} if there was a validation
+or a known constraint error.
+
+
+ Options
+
+
+
Besides the “Shared options” section at the module documentation,
+it accepts:
+
+
:force - By default, if there are no changes in the changeset,
+update!/2 is a no-op. By setting this option to true, update
+callbacks will always be executed, even if there are no changes
+(including timestamps).
+
+
:prefix - The prefix to run the query on (such as the schema path
+in Postgres or the database in MySQL). This overrides the prefix set
+in the struct.
+
+
+
+
+ Example
+
+
+
post = MyRepo.get!(Post, 42)
+post = Ecto.Changeset.change post, title: "New title"
+case MyRepo.update post do
+ {:ok, struct} -> # Updated with success
+ {:error, changeset} -> # Something went wrong
+end
Updates all entries matching the given query with the given values.
+
It returns a tuple containing the number of entries
+and any returned result as second element. If the database
+does not support RETURNING in UPDATE statements or no
+return result was selected, the second element will be nil.
+
Keep in mind this update_all will not update autogenerated
+fields like the updated_at columns.
+
See Ecto.Query.update/3 for update operations that can be
+performed on fields.
+
+
+ Options
+
+
+
+
:returning - selects which fields to return. When true,
+returns all fields in the given struct. May be a list of
+fields, where a struct is still returned but only with the
+given fields. Or false, where nothing is returned (the default).
+This option is not supported by all databases.
+
+
:prefix - The prefix to run the query on (such as the schema path
+in Postgres or the database in MySQL). This overrides the prefix set
+in the query.
+
+
+
See the “Shared options” section at the module documentation for
+remaining options.
+
+
+ Examples
+
+
+
MyRepo.update_all(Post, set: [title: "New title"])
+
+MyRepo.update_all(Post, inc: [visits: 1])
+
+from(p in Post, where: p.id < 10)
+|> MyRepo.update_all(set: [title: "New title"])
+
+from(p in Post, where: p.id < 10, update: [set: [title: "New title"]])
+|> MyRepo.update_all([])
+
+from(p in Post, where: p.id < 10, update: [set: [title: fragment("?", new_title)]])
+|> MyRepo.update_all([])
This is a Receiver Plugin which is in charge of storing the System Metrics received from the Agents in a Postgres
+database. If we want to use it we have to declare it in the Config file, inside the :receivers section, ie:
This Plugin uses Postgres as a backend, specifically the system_stats table. Make sure that table exists before using
+this Plugin.
+
We also need to subscribe this plugin to :system_metrics metrics in the config file. For that we have to add this line
+to the list in the :subscriptions section:
A callback executed when the Receiver Plugin starts.
+ The argument is retrieved from the configuration file when the Receiver is defined
+ It must return {:ok, state}, that state will be keept as in GenServer and can be
+ retrieved in the metrics_received/3 function
This function is called when a Custom Handler detects a client is inactive.
+
The Custom Handler must to call explicity to POABackend.CustomHandler.publish_inactive/1 and it will publish the
+ inactive message to all the metrics in the system (defined in the config file).
A callback executed when the Receiver Plugin starts.
+ The argument is retrieved from the configuration file when the Receiver is defined
+ It must return {:ok, state}, that state will be keept as in GenServer and can be
+ retrieved in the metrics_received/3 function.
That command will create a doc/ folder with the actual Documentation.
+
+
+ Configuring Databases for first time
+
+
+
POABackend uses many Databases. For Authentication we use Mnesia as a local database and for some receivers which require storage we use Postgres. All databases are managed on top of Ecto a widly used database wrapper for Elixir projects.
+
For this reason we have to set the databases before running the POABackend for the first time.
+
+
Auth Database (Mnesia): Setting up Mnesia is easy since it is working localy and is built in the Erlang Virtual Machine. We only have to say “where” we are going to store the database’s files. In order to do that we have to add the configuration to the config file (prod.exs or test.exs depending if you want to run tests or production)
+
+
+
config :mnesia,
+ dir: 'your/local/path' # make sure this directory exists!
+
+
Receivers Database (Postgres): This is a little more complex than Mnesia. We need a Postgres instance running somewhere and we have to add the config to the config files
+
+
+
config :poa_backend, POABackend.Receivers.Repo,
+ priv: "priv/receivers", # this value is not changed
+ adapter: Ecto.Adapters.Postgres,
+ database: "poabackend_stats",
+ username: "postgres",
+ password: "postgres",
+ hostname: "localhost"
+
The important fields here are database, username, password and hostname. The rest of values must remain exactly as the example.
+
Once we have set the database configuration we have to create and migrate the databases, in order to do that we should be in the root of the project and run:
Now the environment is ready for running POABackend
Run Tests
-
POABackend uses Mnesia as a local database with Ecto. In order to have this running we have to create a folder where Mnesia will store our data. In order to do that we have to define it in the config/test.exs file like this:
-
config :mnesia,
- dir: 'your/local/path' # make sure this directory exists!
-
once we have the path defined we have to create the database (those commands must be run only once if you are going to use always this same path for testing). In your root folder run:
Now the environment is set. We can run the tests with:
+
The first time you run the tests you will need having the Database’s environment set up. Check the previous section and set the configuration in the config/test.exs file.
+
Once the environment is set. We can run the tests with:
mix test
POABackend comes also with a code analysis tool Credo and a types checker tool Dialyxir. In order to run them we have to run
mix credo
diff --git a/doc/api-reference.html b/doc/api-reference.html
index 8029746..aa1a3be 100644
--- a/doc/api-reference.html
+++ b/doc/api-reference.html
@@ -8,7 +8,7 @@
API Reference – poa_backend v0.1.0
-
+
@@ -195,6 +195,26 @@ Those Admins are defined in the Config (ie prod.exs)
This is a Receiver Plugin which stores the received Ethereum Blocks in DynamoDB
This is a Receiver Plugin which is in charge of storing the Ethereum Statistics received from the Agents in a Postgres
+database. If we want to use it we have to declare it in the Config file, inside the :receivers section, ie
This is a Receiver Plugin which is in charge of storing the System Metrics received from the Agents in a Postgres
+database. If we want to use it we have to declare it in the Config file, inside the :receivers section, ie
+
+
diff --git a/doc/dist/sidebar_items-3739fd4c82.js b/doc/dist/sidebar_items-3739fd4c82.js
deleted file mode 100644
index f9f2f9a..0000000
--- a/doc/dist/sidebar_items-3739fd4c82.js
+++ /dev/null
@@ -1 +0,0 @@
-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.Auth","title":"POABackend.Auth","group":"POA Auth","functions":[{"id":"activate_user/1","anchor":"activate_user/1"},{"id":"authenticate_admin/2","anchor":"authenticate_admin/2"},{"id":"authenticate_user/2","anchor":"authenticate_user/2"},{"id":"create_banned_token/1","anchor":"create_banned_token/1"},{"id":"create_banned_token/2","anchor":"create_banned_token/2"},{"id":"create_user/3","anchor":"create_user/3"},{"id":"deactivate_user/1","anchor":"deactivate_user/1"},{"id":"generate_password/0","anchor":"generate_password/0"},{"id":"generate_user_name/0","anchor":"generate_user_name/0"},{"id":"generate_user_name/1","anchor":"generate_user_name/1"},{"id":"get_user/1","anchor":"get_user/1"},{"id":"purge_banned_tokens/0","anchor":"purge_banned_tokens/0"},{"id":"remove_user/1","anchor":"remove_user/1"},{"id":"token_banned?/1","anchor":"token_banned?/1"},{"id":"user_active?/1","anchor":"user_active?/1"},{"id":"valid_token?/1","anchor":"valid_token?/1"},{"id":"valid_user_name?/1","anchor":"valid_user_name?/1"}]},{"id":"POABackend.Auth.Guardian.Plug","title":"POABackend.Auth.Guardian.Plug","group":"POA Auth","functions":[{"id":"authenticated?/2","anchor":"authenticated?/2"},{"id":"current_claims/2","anchor":"current_claims/2"},{"id":"current_resource/2","anchor":"current_resource/2"},{"id":"current_token/2","anchor":"current_token/2"},{"id":"implementation/0","anchor":"implementation/0"},{"id":"put_current_claims/3","anchor":"put_current_claims/3"},{"id":"put_current_resource/3","anchor":"put_current_resource/3"},{"id":"put_current_token/3","anchor":"put_current_token/3"},{"id":"remember_me/4","anchor":"remember_me/4"},{"id":"remember_me_from_token/4","anchor":"remember_me_from_token/4"},{"id":"sign_in/4","anchor":"sign_in/4"},{"id":"sign_out/2","anchor":"sign_out/2"}]},{"id":"POABackend.Auth.Models.Token","title":"POABackend.Auth.Models.Token","group":"POA Auth","functions":[{"id":"new/2","anchor":"new/2"}],"types":[{"id":"t/0","anchor":"t:t/0"}]},{"id":"POABackend.Auth.Models.User","title":"POABackend.Auth.Models.User","group":"POA Auth","functions":[{"id":"changeset/2","anchor":"changeset/2"}],"types":[{"id":"t/0","anchor":"t:t/0"}]},{"id":"POABackend.Auth.REST","title":"POABackend.Auth.REST","group":"POA Auth"},{"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":[]}
\ No newline at end of file
diff --git a/doc/dist/sidebar_items-3d14d8fe9b.js b/doc/dist/sidebar_items-3d14d8fe9b.js
new file mode 100644
index 0000000..dc3a95b
--- /dev/null
+++ b/doc/dist/sidebar_items-3d14d8fe9b.js
@@ -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.Receivers.Repo","title":"POABackend.Receivers.Repo","group":"","functions":[{"id":"aggregate/4","anchor":"aggregate/4"},{"id":"all/2","anchor":"all/2"},{"id":"config/0","anchor":"config/0"},{"id":"delete/2","anchor":"delete/2"},{"id":"delete!/2","anchor":"delete!/2"},{"id":"delete_all/2","anchor":"delete_all/2"},{"id":"get/3","anchor":"get/3"},{"id":"get!/3","anchor":"get!/3"},{"id":"get_by/3","anchor":"get_by/3"},{"id":"get_by!/3","anchor":"get_by!/3"},{"id":"in_transaction?/0","anchor":"in_transaction?/0"},{"id":"insert/2","anchor":"insert/2"},{"id":"insert!/2","anchor":"insert!/2"},{"id":"insert_all/3","anchor":"insert_all/3"},{"id":"insert_or_update/2","anchor":"insert_or_update/2"},{"id":"insert_or_update!/2","anchor":"insert_or_update!/2"},{"id":"load/2","anchor":"load/2"},{"id":"one/2","anchor":"one/2"},{"id":"one!/2","anchor":"one!/2"},{"id":"preload/3","anchor":"preload/3"},{"id":"query/3","anchor":"query/3"},{"id":"query!/3","anchor":"query!/3"},{"id":"rollback/1","anchor":"rollback/1"},{"id":"start_link/1","anchor":"start_link/1"},{"id":"stop/2","anchor":"stop/2"},{"id":"stream/2","anchor":"stream/2"},{"id":"transaction/2","anchor":"transaction/2"},{"id":"update/2","anchor":"update/2"},{"id":"update!/2","anchor":"update!/2"},{"id":"update_all/3","anchor":"update_all/3"}]},{"id":"POABackend.Auth","title":"POABackend.Auth","group":"POA Auth","functions":[{"id":"activate_user/1","anchor":"activate_user/1"},{"id":"authenticate_admin/2","anchor":"authenticate_admin/2"},{"id":"authenticate_user/2","anchor":"authenticate_user/2"},{"id":"create_banned_token/1","anchor":"create_banned_token/1"},{"id":"create_banned_token/2","anchor":"create_banned_token/2"},{"id":"create_user/3","anchor":"create_user/3"},{"id":"deactivate_user/1","anchor":"deactivate_user/1"},{"id":"generate_password/0","anchor":"generate_password/0"},{"id":"generate_user_name/0","anchor":"generate_user_name/0"},{"id":"generate_user_name/1","anchor":"generate_user_name/1"},{"id":"get_user/1","anchor":"get_user/1"},{"id":"purge_banned_tokens/0","anchor":"purge_banned_tokens/0"},{"id":"remove_user/1","anchor":"remove_user/1"},{"id":"token_banned?/1","anchor":"token_banned?/1"},{"id":"user_active?/1","anchor":"user_active?/1"},{"id":"valid_token?/1","anchor":"valid_token?/1"},{"id":"valid_user_name?/1","anchor":"valid_user_name?/1"}]},{"id":"POABackend.Auth.Guardian.Plug","title":"POABackend.Auth.Guardian.Plug","group":"POA Auth","functions":[{"id":"authenticated?/2","anchor":"authenticated?/2"},{"id":"current_claims/2","anchor":"current_claims/2"},{"id":"current_resource/2","anchor":"current_resource/2"},{"id":"current_token/2","anchor":"current_token/2"},{"id":"implementation/0","anchor":"implementation/0"},{"id":"put_current_claims/3","anchor":"put_current_claims/3"},{"id":"put_current_resource/3","anchor":"put_current_resource/3"},{"id":"put_current_token/3","anchor":"put_current_token/3"},{"id":"remember_me/4","anchor":"remember_me/4"},{"id":"remember_me_from_token/4","anchor":"remember_me_from_token/4"},{"id":"sign_in/4","anchor":"sign_in/4"},{"id":"sign_out/2","anchor":"sign_out/2"}]},{"id":"POABackend.Auth.Models.Token","title":"POABackend.Auth.Models.Token","group":"POA Auth","functions":[{"id":"new/2","anchor":"new/2"}],"types":[{"id":"t/0","anchor":"t:t/0"}]},{"id":"POABackend.Auth.Models.User","title":"POABackend.Auth.Models.User","group":"POA Auth","functions":[{"id":"changeset/2","anchor":"changeset/2"}],"types":[{"id":"t/0","anchor":"t:t/0"}]},{"id":"POABackend.Auth.REST","title":"POABackend.Auth.REST","group":"POA Auth"},{"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"}]},{"id":"POABackend.Receivers.Eth.Stats","title":"POABackend.Receivers.Eth.Stats","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.System.Stats","title":"POABackend.Receivers.System.Stats","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":[]}
\ No newline at end of file
diff --git a/doc/initial_architecture.html b/doc/initial_architecture.html
index 2381c92..56786bf 100644
--- a/doc/initial_architecture.html
+++ b/doc/initial_architecture.html
@@ -8,7 +8,7 @@
Initial Architecture – poa_backend v0.1.0
-
+
diff --git a/doc/search.html b/doc/search.html
index 1c12f43..ade5563 100644
--- a/doc/search.html
+++ b/doc/search.html
@@ -8,7 +8,7 @@
Search – poa_backend v0.1.0
-
+
diff --git a/lib/poa_backend.ex b/lib/poa_backend.ex
index eb7f434..8ed5844 100644
--- a/lib/poa_backend.ex
+++ b/lib/poa_backend.ex
@@ -21,23 +21,56 @@ defmodule POABackend do
That command will create a `doc/` folder with the actual Documentation.
- ## Run Tests
+ ## Configuring Databases for first time
- `POABackend` uses [Mnesia](http://erlang.org/doc/man/mnesia.html) as a local database with [Ecto](https://hexdocs.pm/ecto/Ecto.html). In order to have this running we have to create a folder where `Mnesia` will store our data. In order to do that we have to define it in the `config/test.exs` file like this:
+ `POABackend` uses many Databases. For Authentication we use [Mnesia](http://erlang.org/doc/man/mnesia.html) as a local database and for some receivers which require storage we use Postgres. All databases are managed on top of [Ecto](https://hexdocs.pm/ecto/Ecto.html) a widly used database wrapper for Elixir projects.
+
+ For this reason we have to set the databases before running the `POABackend` for the first time.
+
+ - Auth Database (Mnesia): Setting up Mnesia is easy since it is working localy and is built in the Erlang Virtual Machine. We only have to say "where" we are going to store the database's files. In order to do that we have to add the configuration to the config file (`prod.exs` or `test.exs` depending if you want to run tests or production)
```
config :mnesia,
dir: 'your/local/path' # make sure this directory exists!
```
- once we have the path defined we have to create the database (those commands must be run only once if you are going to use always this same path for testing). In your root folder run:
+ - Receivers Database (Postgres): This is a little more complex than Mnesia. We need a Postgres instance running somewhere and we have to add the config to the config files
+
+ ```
+ config :poa_backend, POABackend.Receivers.Repo,
+ priv: "priv/receivers", # this value is not changed
+ adapter: Ecto.Adapters.Postgres,
+ database: "poabackend_stats",
+ username: "postgres",
+ password: "postgres",
+ hostname: "localhost"
+ ```
+
+ The important fields here are `database`, `username`, `password` and `hostname`. The rest of values must remain exactly as the example.
+
+ Once we have set the database configuration we have to create and migrate the databases, in order to do that we should be in the root of the project and run:
+
+ - for production
+
+ ```
+ MIX_ENV=prod mix ecto.create
+ MIX_ENV=prod mix ecto.migrate
+ ```
+
+ - for test
```
MIX_ENV=test mix ecto.create
MIX_ENV=test mix ecto.migrate
```
- Now the environment is set. We can run the tests with:
+ Now the environment is ready for running `POABackend`
+
+ ## Run Tests
+
+ The first time you run the tests you will need having the Database's environment set up. Check the previous section and set the configuration in the `config/test.exs` file.
+
+ Once the environment is set. We can run the tests with:
```
mix test
diff --git a/lib/poa_backend/receivers/eth/stats.ex b/lib/poa_backend/receivers/eth/stats.ex
index b2e23bf..c2407da 100644
--- a/lib/poa_backend/receivers/eth/stats.ex
+++ b/lib/poa_backend/receivers/eth/stats.ex
@@ -1,7 +1,20 @@
defmodule POABackend.Receivers.Eth.Stats do
use POABackend.Receiver
- @moduledoc false
+ @moduledoc """
+ This is a Receiver Plugin which is in charge of storing the Ethereum Statistics received from the Agents in a Postgres
+ database. If we want to use it we have to declare it in the Config file, inside the `:receivers` section, ie:
+
+ {:store_eth_stats, POABackend.Receivers.Eth.Stats, []}
+
+ This Plugin uses Postgres as a backend, specifically the `eth_stats` table. Make sure that table exists before using
+ this Plugin.
+
+ We also need to subscribe this plugin to `:ethereum_metrics` metrics in the config file. For that we have to add this line
+ to the list in the `:subscriptions` section:
+
+ {:store_eth_stats, [:ethereum_metrics]}
+ """
alias POABackend.Protocol.Message
alias POABackend.Receivers.Models.EthStats
diff --git a/lib/poa_backend/receivers/system/stats.ex b/lib/poa_backend/receivers/system/stats.ex
index 29e1638..826e37d 100644
--- a/lib/poa_backend/receivers/system/stats.ex
+++ b/lib/poa_backend/receivers/system/stats.ex
@@ -1,7 +1,20 @@
defmodule POABackend.Receivers.System.Stats do
use POABackend.Receiver
- @moduledoc false
+ @moduledoc """
+ This is a Receiver Plugin which is in charge of storing the System Metrics received from the Agents in a Postgres
+ database. If we want to use it we have to declare it in the Config file, inside the `:receivers` section, ie:
+
+ {:store_system_stats, POABackend.Receivers.System.Stats, []}
+
+ This Plugin uses Postgres as a backend, specifically the `system_stats` table. Make sure that table exists before using
+ this Plugin.
+
+ We also need to subscribe this plugin to `:system_metrics` metrics in the config file. For that we have to add this line
+ to the list in the `:subscriptions` section:
+
+ {:store_system_stats, [:system_metrics]}
+ """
alias POABackend.Protocol.Message
alias POABackend.Receivers.Models.SystemStats
diff --git a/mix.exs b/mix.exs
index 137fa58..9fb6c22 100644
--- a/mix.exs
+++ b/mix.exs
@@ -88,7 +88,9 @@ defmodule POABackend.MixProject do
"Receivers": [
POABackend.Receiver,
POABackend.Receivers.DynamoDB,
- POABackend.Receivers.Dashboard
+ POABackend.Receivers.Dashboard,
+ POABackend.Receivers.System.Stats,
+ POABackend.Receivers.Eth.Stats
]
]
]