# `Cldr.Eternal`
[🔗](https://github.com/elixir-cldr/cldr_currencies/blob/v2.17.1/lib/cldr/eternal.ex#L1)

This module implements bindings around what should be an eternal ETS table,
or at least until you decide to terminate it. It works by using "bouncing"
GenServers which come up as needed to provide an heir for the ETS table. It
operates as follows:

1. An ETS table is created with the provided name and options.
2. Two GenServers are started, an `owner` and an `heir`. The ETS table is gifted
  to the `owner`, and has the `heir` set as the heir.
3. If the `owner` crashes, the `heir` becomes the owner, and a new GenServer
  is started and assigned the role of `heir`.
4. If an `heir` dies, we attempt to start a new GenServer and notify the `owner`
  so that they may change the assigned `heir`.

This means that there should always be an `heir` to your table, which should
ensure that you don't lose anything inside ETS.

# `on_start`

```elixir
@type on_start() ::
  {:ok, pid()}
  | :ignore
  | {:error, {:already_started, pid()} | {:shutdown, term()} | term()}
```

# `table`

```elixir
@type table() :: :ets.table()
```

# `heir`

```elixir
@spec heir(table :: table()) :: any()
```

Returns the heir of a given ETS table.

## Examples

    iex> Cldr.Eternal.heir(:my_table)

# `owner`

```elixir
@spec owner(table :: table()) :: any()
```

Returns the owner of a given ETS table.

## Examples

    iex> Cldr.Eternal.owner(:my_table)

# `start`

```elixir
@spec start(name :: atom(), ets_opts :: list(), opts :: Keyword.t()) :: on_start()
```

Functionally equivalent to `start_link/3`, except that the link to the starting
process is removed after the table is started.

## Examples

    iex> Cldr.Eternal.start(:table1, [], [quiet: true])

    iex> Cldr.Eternal.start(:table2, [:compressed], [quiet: true])

    iex> Cldr.Eternal.start(:table3, [], [quiet: true])

# `start_link`

```elixir
@spec start_link(name :: atom(), ets_opts :: list(), opts :: Keyword.t()) ::
  on_start()
```

Creates a new ETS table using the provided `ets_opts`.

These options are passed through as-is, with the exception of prepending the
`:public` and `:named_table` options. Seeing as you can't execute inside the
GenServers, your table will have to be public to be interacted with.

## Options

You may provide a third parameter containing Eternal options:

- `:name` - override the default naming scheme and use a custom name for this
  table. Remember to use this name when calling `stop/1`.
- `:quiet` - by default, Eternal logs debug messages. Setting this to true will
  disable this logging.

## Examples

    iex> Cldr.Eternal.start_link(:table1, [], [quiet: true])

    iex> Cldr.Eternal.start_link(:table2, [:compressed], [quiet: true])

    iex> Cldr.Eternal.start_link(:table3, [], [quiet: true])

# `stop`

```elixir
@spec stop(table :: table()) :: :ok
```

Terminates both servers in charge of a given ETS table.

Note: this will terminate your ETS table.

## Examples

    iex> Cldr.Eternal.stop(:my_table)
    :ok

---

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