feat(growth): load data on application start

To make this possible, the following changes were made:

* Use `Task` to start the load process
* Create `ets` table before start the async task
  * This is needed to keep the tables alive after the task process exits
* Adjust the application to start the `Growth.Indicators.Load` task
This commit is contained in:
João Paulo Dubas 2024-06-10 12:11:18 +00:00
parent 412250d7ef
commit b415b38184
Signed by: joao.dubas
SSH Key Fingerprint: SHA256:V1mixgOGRc/YMhGx/DNkOSmJxgA2vHNrDZEk3wt/kOA
2 changed files with 33 additions and 13 deletions

View File

@ -32,6 +32,8 @@ defmodule Growth.Indicators.Load do
""" """
use Task
alias Growth.Score alias Growth.Score
@measure_to_score [ @measure_to_score [
@ -45,6 +47,15 @@ defmodule Growth.Indicators.Load do
weight_for_height: Score.WeightForHeight weight_for_height: Score.WeightForHeight
] ]
@doc false
def start_link(_) do
Enum.map(@measure_to_score, fn {_, measure} ->
create_ets(measure)
end)
Task.start_link(__MODULE__, :all, [])
end
@spec all :: [[boolean()]] @spec all :: [[boolean()]]
@doc """ @doc """
Load indicators csv files into their own ets tables. Load indicators csv files into their own ets tables.
@ -57,20 +68,13 @@ defmodule Growth.Indicators.Load do
|> Task.await_many() |> Task.await_many()
end end
@spec create_ets(String.t()) :: {atom(), String.t()} @spec create_ets(module()) :: module()
@doc """ @doc """
Create a public ets table for the csv filename, using the file name as the table name. Create a public ets table for the growth module, using it as the table name.
Returns a tuple with table name as an atom and the filename. Returns the given module.
""" """
def create_ets(filename) do def create_ets(measure) do
measure =
filename
|> Path.basename()
|> Path.rootname()
|> String.to_atom()
|> then(&Keyword.get(@measure_to_score, &1, &1))
try do try do
:ets.new(measure, [:set, :public, :named_table]) :ets.new(measure, [:set, :public, :named_table])
rescue rescue
@ -78,6 +82,21 @@ defmodule Growth.Indicators.Load do
nil nil
end end
measure
end
@spec filename_to_measure(String.t()) :: {atom(), String.t()}
@doc """
Translate the given filename to the related module and return both in a tuple.
"""
def filename_to_measure(filename) do
measure =
filename
|> Path.basename()
|> Path.rootname()
|> String.to_atom()
|> then(&Keyword.get(@measure_to_score, &1, &1))
{measure, filename} {measure, filename}
end end
@ -127,7 +146,7 @@ defmodule Growth.Indicators.Load do
as_float(t) as_float(t)
end end
key = {String.to_existing_atom(gender), unit, converted_t} key = {String.to_atom(gender), unit, converted_t}
value = %{ value = %{
l: as_float(l), l: as_float(l),

View File

@ -16,9 +16,10 @@ defmodule Wabanex.Application do
# Start the PubSub system # Start the PubSub system
{Phoenix.PubSub, name: Wabanex.PubSub}, {Phoenix.PubSub, name: Wabanex.PubSub},
# Start the Endpoint (http/https) # Start the Endpoint (http/https)
WabanexWeb.Endpoint WabanexWeb.Endpoint,
# Start a worker by calling: Wabanex.Worker.start_link(arg) # Start a worker by calling: Wabanex.Worker.start_link(arg)
# {Wabanex.Worker, arg} # {Wabanex.Worker, arg}
{Growth.Indicators.Load, []}
] ]
# See https://hexdocs.pm/elixir/Supervisor.html # See https://hexdocs.pm/elixir/Supervisor.html