Packages
ex_money
0.4.1
6.1.1
6.1.0
6.0.0
6.0.0-rc.0
5.24.2
5.24.1
5.24.0
retired
5.23.0
5.22.0
5.21.0
5.20.0
5.19.2
5.19.1
5.19.0
5.18.0
5.17.2
5.17.1
5.17.0
5.16.1
5.16.0
5.15.4
5.15.3
5.15.2
5.15.1
5.15.0
5.14.1
5.13.0
5.12.4
5.12.3
5.12.2
5.12.1
5.12.0
5.11.0
5.10.0
5.9.0
5.8.0
5.7.4
5.7.3
5.7.2
5.7.1
5.7.0
5.6.0
5.5.5
5.5.4
5.5.3
5.5.2
5.5.1
5.5.0
5.4.1
5.4.0
5.4.0-rc.0
5.3.2
5.3.1
5.3.0
5.2.1
5.2.0
5.1.0
5.0.2
5.0.1
5.0.0
retired
4.4.3
4.4.2
retired
4.4.1
4.4.0
4.3.0
4.2.2
4.2.1
4.2.0
4.1.0
4.0.0
3.4.4
3.4.3
3.4.2
3.4.1
3.4.0
3.3.1
3.3.0
3.2.4
3.2.3
3.2.2
3.2.1
3.2.0
3.1.0
3.0.0
2.12.2
2.12.1
retired
2.12.0
retired
2.11.0
2.10.0
2.9.1
2.9.0
2.8.0
2.7.3
2.7.2
2.7.1
2.7.0
2.6.1
2.6.0
2.5.0
2.4.0
2.3.0
2.2.2
2.2.1
2.2.0
2.1.0
2.1.0-rc.1
retired
2.1.0-rc.0
retired
2.0.4
2.0.3
2.0.2
2.0.1
2.0.0
1.1.3
1.1.2
1.1.1
retired
1.1.0
1.0.0
1.0.0-rc.0
retired
0.9.0
retired
0.8.5
retired
0.8.4
retired
0.8.3
retired
0.8.2
retired
0.8.1
retired
0.8.0
retired
0.7.0
retired
0.6.2
retired
0.6.1
retired
0.6.0
retired
0.5.3
retired
0.5.2
retired
0.5.1
retired
0.5.0
retired
0.4.3
retired
0.4.2
retired
0.4.1
retired
0.4.0
retired
0.3.0
retired
0.2.0
retired
0.1.7
retired
0.1.6
retired
0.1.5
retired
0.1.4
retired
0.1.3
retired
0.1.2
retired
0.1.1
retired
0.1.0
retired
0.0.16
retired
0.0.15
retired
0.0.14
retired
0.0.13
retired
0.0.12
retired
0.0.11
retired
0.0.10
retired
0.0.9
retired
0.0.7
retired
0.0.6
retired
0.0.5
retired
0.0.4
retired
0.0.3
retired
0.0.2
retired
Money functions for operations on and localization of a money data type with support for ISO 4217 currencies and ISO 24165 digial tokens (crypto currencies).
Retired package: Deprecated
Current section
Files
Jump to
Current section
Files
lib/money/exchange_rates/exchange_rates_retriever.ex
defmodule Money.ExchangeRates.Retriever do
@moduledoc """
Implements a `GenServer` to retrieve exchange rates from
a configured retrieveal module on a periodic basis. By default exchange
rates are retrieved from [Open Exchange Rates](http://openexchangerates.org).
Retrieved data is stored in an `:ets` table.
By default the period of execution is 5 minutes (300_000 microseconds). The
period of retrieval is configured in `config.exs` or the appropriate
environment configuration. For example:
config :ex_money,
open_exchange_rates_app_id: "app_id_string",
open_exchange_rates_retrieve_every: 300_000
"""
use GenServer
require Logger
alias Money.ExchangeRates
def start_link(name, config) do
GenServer.start_link(__MODULE__, config, name: name)
end
def init(config) do
log(config, :info, "Starting exchange rate retrieval service")
initialize_ets_table()
case config.delay_before_first_retrieval do
delay when is_integer(delay) and delay > 0 ->
log(config, :info, "Rates will be retrieved in #{div(delay, 1000)} seconds " <>
"and then every #{div(config.retrieve_every, 1000)} seconds.")
schedule_work(delay)
_ ->
log(config, :info, "Rates will be retrieved every #{div(config.retrieve_every, 1000)} seconds.")
schedule_work(config.retrieve_every)
end
{:ok, config}
end
def handle_info(:latest, config) do
retrieve_rates(config)
schedule_work(config.retrieve_every)
{:noreply, config}
end
def retrieve_rates(%{callback_module: callback_module} = config) do
case ExchangeRates.get_latest_rates() do
{:ok, rates} ->
retrieved_at = DateTime.utc_now
store_rates(rates, retrieved_at)
log(config, :success, inspect(callback_module))
apply(callback_module, :rates_retrieved, [rates, retrieved_at])
log(config, :success, "Retrieved exchange rates successfully")
{:ok, rates}
{:error, reason} ->
log(config, :failure, "Could not retrieve exchange rates: #{inspect reason}")
{:error, reason}
end
end
defp schedule_work(delay_ms) do
Process.send_after(self(), :latest, delay_ms)
end
defp initialize_ets_table do
:ets.new(:exchange_rates, [:named_table, read_concurrency: true])
end
defp store_rates(rates, retrieved_at) do
:ets.insert(:exchange_rates, {:rates, rates})
:ets.insert(:exchange_rates, {:last_updated, retrieved_at})
end
defp log(%{log_levels: log_levels}, key, message) do
case Map.get(log_levels, key) do
nil ->
nil
log_level ->
Logger.log(log_level, message)
end
end
end