defmodule FlyMultiRegion do
@moduledoc ~S"""
Documentation for `FlyMultiRegion`.
For setting up read-replica databases refer to [Fly.io's documentation](https://fly.io/docs/getting-started/multi-region-databases/)
## Usage
### Installation
The package can be installed by adding `fly_multi_region` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:fly_multi_region, "~> 0.0.1"}
]
end
```
### Configuration
If you're following the Fly.io guides then your database config will happen at runtime. Add the following to the `runtime.exs` file:
```elixir
config :fly_multi_region,
region: System.get_env("FLY_REGION"),
regions: ["nrt", "ord"],
url: System.get_env("DATABASE_URL"),
opts: [
socket_options: [:inet6],
pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10")
]
```
Parameters:
- region: generated by Fly.io by default
- regions: a list of replicas in your cluster
- url: database url
- opts: configuration options for Ecto
### Supervision
Add FlyMultiRegion to your Application's supervision tree
As mentioned in [Ecto's documentation for replica databases](https://hexdocs.pm/ecto/replicas-and-dynamic-repositories.html) it's necessary to add any Repos to your supervision tree. With that in mind, make sure to add `FlyMultiRegion` to your Application module (application.ex)
```elixir
def start(_type, _args) do
children =
[
...,
FlyMultiRegion
]
...
Supervisor.start_link(children, opts)
end
```
### Repo
Add the following to your projects main Repo module:
```elixir
use FlyMultiRegion.Repo
```
"""
use Supervisor
alias __MODULE__.Repo
@doc false
def start_link(opts) do
Supervisor.start_link(__MODULE__, :ok, opts)
end
@impl true
def init(_opts) do
Supervisor.init(replicas(), strategy: :one_for_one)
end
@doc false
defp replicas do
Enum.map(regions(), fn region ->
{_, module, _, _} = Repo.new(region)
{module, region: region}
end)
end
@doc false
def regions, do: Application.get_env(:fly_multi_region, :regions) || []
@doc """
Returns replica Repo module name
"""
def repo_module(region) do
Module.concat(FlyMultiRegion.Repo, String.capitalize(region))
end
end