# `Money.ExchangeRates.Retriever`
[🔗](https://github.com/ex-money/money/blob/v6.2.0/lib/money/exchange_rates/retriever.ex#L1)

A `GenServer` that retrieves exchange rates from a configured API module on a
periodic or on-demand basis.

Add it to your application's supervision tree to enable the exchange rates
service:

    children = [
      MyApp.Repo,
      Money.ExchangeRates.Retriever
    ]

To start with a custom configuration:

    children = [
      {Money.ExchangeRates.Retriever, [config: my_config]}
    ]

Multiple named retrievers can be started independently, each backed by a
different API source:

    children = [
      {Money.ExchangeRates.Retriever, [name: :open_exchange_rates, config: oxr_config]},
      {Money.ExchangeRates.Retriever, [name: :fixer, config: fixer_config]}
    ]

    Money.ExchangeRates.Retriever.latest_rates(:open_exchange_rates)
    Money.ExchangeRates.Retriever.historic_rates(:fixer, ~D[2024-01-01])

> #### Named retrievers each get their own cache {: .info}
>
> The bundled cache implementations (`Money.ExchangeRates.Cache.Ets` and
> `Money.ExchangeRates.Cache.Dets`) key their storage (the ETS table name /
> DETS file path) by the retriever's `:name`, so multiple named retrievers
> can safely share the same `cache_module` - each gets its own separated
> cache.
>
> A custom cache module that implements only the deprecated,
> lower-arity `Money.ExchangeRates.Cache` callbacks behaves as a single,
> module-wide cache instead. Named retrievers sharing such a module will
> overwrite each other's rates; give each its own `cache_module` in that
> case.

By default exchange rates are retrieved from
[Open Exchange Rates](http://openexchangerates.org). The retrieval interval
is configured via the `:exchange_rates_retrieve_every` key (milliseconds):

    config :ex_money,
      exchange_rates_retrieve_every: 300_000

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `config`

```elixir
@spec config(GenServer.name()) ::
  Money.ExchangeRates.Config.t() | {:error, {module(), String.t()}}
```

Returns the current configuration of the Exchange Rates
Retrieval service

# `delete`

> This function is deprecated. Use `Supervisor.delete_child/2` on your application's supervisor instead.

```elixir
@spec delete(GenServer.server()) :: :ok
```

# `historic_rates`

```elixir
@spec historic_rates(Calendar.date()) ::
  {:ok, Money.ExchangeRates.t()} | {:error, {Exception.t(), binary()}}
@spec historic_rates(Date.Range.t()) ::
  [ok: Money.ExchangeRates.t(), error: {Exception.t(), binary()}]
  | {:error, {Exception.t(), binary()}}
```

Forces retrieval of historic exchange rates for a single date

* `date` is a `t:Date.t/0` or any date-compatible map or struct (`t:Calendar.date/0`) or

* a `Date.Range.t` created by `Date.range/2` that specifies a
  range of dates to retrieve

Returns:

* `{:ok, rates}` if exchange rates request is successfully sent.

* `{:error, reason}` if the request cannot be sent.

Sends a message to the exchange rate retrieval worker to request
historic rates for a specified date or range be retrieved and
stored.

This function does not return exchange rates, for that see
`Money.ExchangeRates.latest_rates/0` or
`Money.ExchangeRates.historic_rates/1`.

# `historic_rates`

```elixir
@spec historic_rates(GenServer.server(), Calendar.date()) ::
  {:ok, Money.ExchangeRates.t()} | {:error, {Exception.t(), binary()}}
@spec historic_rates(GenServer.server(), Date.Range.t()) ::
  [ok: Money.ExchangeRates.t(), error: {Exception.t(), binary()}]
  | {:error, {Exception.t(), binary()}}
@spec historic_rates(Calendar.date(), Calendar.date()) ::
  [ok: Money.ExchangeRates.t(), error: {Exception.t(), binary()}]
  | {:error, {Exception.t(), binary()}}
```

Forces retrieval of historic exchange rates for a range of dates

* `from` is a `t:Date.t/0` or any date-compatible map or struct (`t:Calendar.date/0`).

* `to` is a `t:Date.t/0` or any date-compatible map or struct (`t:Calendar.date/0`).

Returns:

* `{:ok, rates}` if exchange rates request is successfully sent.

* `{:error, reason}` if the request cannot be sent.

Sends a message to the exchange rate retrieval process for each
date in the range `from`..`to` to request historic rates be
retrieved.

# `historic_rates`

```elixir
@spec historic_rates(GenServer.server(), Calendar.date(), Calendar.date()) ::
  [ok: Money.ExchangeRates.t(), error: {Exception.t(), binary()}]
  | {:error, {Exception.t(), binary()}}
```

# `last_updated`

```elixir
@spec last_updated(GenServer.server()) ::
  {:ok, DateTime.t()} | {:error, {Exception.t(), binary()}}
```

Returns the timestamp of the last successful exchange rate retrieval.

Returns:

* `{:ok, datetime}` if rates have been retrieved at least once.

* `{:error, reason}` if the retriever is not running or no retrieval has
  occurred yet.

# `latest_rates`

```elixir
@spec latest_rates(GenServer.server()) ::
  {:ok, Money.ExchangeRates.t()} | {:error, {Exception.t(), binary()}}
```

Forces retrieval of the latest exchange rates

Sends a message to the exchange rate retrieval worker to request
current rates be retrieved and stored.

Returns:

* `{:ok, rates}` if exchange rates request is successfully sent.

* `{:error, reason}` if the request cannot be sent.

This function does not return exchange rates, for that see
`Money.ExchangeRates.latest_rates/0` or
`Money.ExchangeRates.historic_rates/1`.

# `latest_rates_available?`

```elixir
@spec latest_rates_available?(GenServer.server()) :: boolean()
```

Returns `true` if the latest exchange rates are available in the cache,
`false` otherwise.

Returns `false` when the retriever is not running, even if the cache table
still exists.

# `reconfigure`

```elixir
@spec reconfigure(GenServer.name(), Money.ExchangeRates.Config.t()) ::
  Money.ExchangeRates.Config.t() | {:error, {module(), String.t()}}
```

Updates the configuration for the Exchange Rate
Service

# `restart`

> This function is deprecated. Use `Supervisor.restart_child/2` on your application's supervisor instead.

```elixir
@spec restart(GenServer.name()) :: GenServer.on_start()
```

# `retrieve_rates`

> This function is deprecated. Use `Money.ExchangeRates.HTTP` or the HTTP client of your preference directly instead.

```elixir
@spec retrieve_rates(charlist() | String.t(), Money.ExchangeRates.Config.t()) ::
  {:ok, map() | :not_modified} | {:error, term()}
```

# `start`

> This function is deprecated. Use `Supervisor.start_child/2` on your application's supervisor instead.

```elixir
@spec start(GenServer.name(), Money.ExchangeRates.Config.t()) :: GenServer.on_start()
```

# `stop`

> This function is deprecated. Use `Supervisor.terminate_child/2` on your application's supervisor instead.

```elixir
@spec stop(GenServer.server()) :: :ok
```

---

*Consult [api-reference.md](api-reference.md) for complete listing*
