Skip to content

Commit

Permalink
Use ExchangeRates.lastest_rates/0 default in sum/2
Browse files Browse the repository at this point in the history
Return {:error, reason} in exchange rates public
API when the retriever isn't running - instead of
letting the process crash.
  • Loading branch information
kipcole9 committed Mar 21, 2024
1 parent e56e2b6 commit d0a8b21
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 14 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ This is the changelog for Money v5.16.0 released on ______, 2024. For older cha

* Update to [CLDR 45.0](https://cldr.unicode.org/index/downloads/cldr-45) data.

* Return structured errors for `Money.ExchangeRates.latest_rates/0`, `Money.ExchangeRates.historic_rates/1`, `Money.ExchangeRates.last_updated/0` and `Money.ExchangeRates.latest_rates_available?/0` when the exchange rates retrieval process is not running.

## Money v5.15.4

This is the changelog for Money v5.15.4 released on February 29th, 2024. For older changelogs please consult the release tag on [GitHub](https://github.com/kipcole9/money/tags)
Expand Down
19 changes: 15 additions & 4 deletions lib/money.ex
Original file line number Diff line number Diff line change
Expand Up @@ -1295,10 +1295,10 @@ defmodule Money do
## Examples
iex> Money.sum [Money.new(:USD, 100), Money.new(:USD, 200), Money.new(:USD, 50)]
iex> Money.sum([Money.new(:USD, 100), Money.new(:USD, 200), Money.new(:USD, 50)])
{:ok, Money.new(:USD, 350)}
iex> Money.sum [Money.new(:USD, 100), Money.new(:USD, 200), Money.new(:AUD, 50)]
iex> Money.sum([Money.new(:USD, 100), Money.new(:USD, 200), Money.new(:AUD, 50)], %{})
{:error,
{Money.ExchangeRateError, "No exchange rate is available for currency :AUD"}}
Expand All @@ -1308,9 +1308,20 @@ defmodule Money do
"""
@doc since: "5.3.0"
@spec sum([t(), ...], ExchangeRates.t()) :: {:ok, t} | {:error, {module(), String.t()}}
@spec sum([t(), ...], ExchangeRates.t() | {:ok, ExchangeRates.t()} | {:error, {module(), String.t()}}) ::
{:ok, t} | {:error, {module(), String.t()}}

def sum([%Money{} = first | rest] = money_list, rates \\ %{}) when is_list(money_list) do
def sum(money_list, rates \\ Money.ExchangeRates.latest_rates())

def sum(money_list, {:ok, %{} = rates}) when is_list(money_list) do
sum(money_list, rates)
end

def sum(money_list, {:error, reason}) when is_list(money_list) do
{:error, reason}
end

def sum([%Money{} = first | rest] = money_list, %{} = rates) when is_list(money_list) do
%Money{currency: target_currency} = first

Enum.reduce_while(rest, {:ok, first}, fn money, {:ok, acc} ->
Expand Down
44 changes: 34 additions & 10 deletions lib/money/exchange_rates.ex
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,14 @@ defmodule Money.ExchangeRates do
"""
@spec latest_rates() :: {:ok, map()} | {:error, {Exception.t(), binary}}
def latest_rates do
case cache().latest_rates() do
{:ok, rates} -> {:ok, rates}
{:error, _} -> Retriever.latest_rates()
try do
case cache().latest_rates() do
{:ok, rates} -> {:ok, rates}
{:error, _} -> Retriever.latest_rates()
end
catch
:exit, {:noproc, {GenServer, :call, [Money.ExchangeRates.Retriever, :config, _timeout]}} ->
{:error, no_retriever_running_error()}
end
end

Expand All @@ -268,9 +273,14 @@ defmodule Money.ExchangeRates do
"""
@spec historic_rates(Date.t()) :: {:ok, map()} | {:error, {Exception.t(), binary}}
def historic_rates(date) do
case cache().historic_rates(date) do
{:ok, rates} -> {:ok, rates}
{:error, _} -> Retriever.historic_rates(date)
try do
case cache().historic_rates(date) do
{:ok, rates} -> {:ok, rates}
{:error, _} -> Retriever.historic_rates(date)
end
catch
:exit, {:noproc, {GenServer, :call, [Money.ExchangeRates.Retriever, :config, _timeout]}} ->
{:error, no_retriever_running_error()}
end
end

Expand All @@ -280,9 +290,14 @@ defmodule Money.ExchangeRates do
"""
@spec latest_rates_available?() :: boolean
def latest_rates_available? do
case cache().latest_rates() do
{:ok, _rates} -> true
_ -> false
try do
case cache().latest_rates() do
{:ok, _rates} -> true
_ -> false
end
catch
:exit, {:noproc, {GenServer, :call, [Money.ExchangeRates.Retriever, :config, _timeout]}} ->
false
end
end

Expand All @@ -301,6 +316,15 @@ defmodule Money.ExchangeRates do
"""
@spec last_updated() :: {:ok, DateTime.t()} | {:error, {Exception.t(), binary}}
def last_updated do
cache().last_updated()
try do
cache().last_updated()
catch
:exit, {:noproc, {GenServer, :call, [Money.ExchangeRates.Retriever, :config, _timeout]}} ->
{:error, no_retriever_running_error()}
end
end

defp no_retriever_running_error do
{Money.ExchangeRateError, "Exchange Rates retrieval process is not running"}
end
end

0 comments on commit d0a8b21

Please sign in to comment.