When making database queries using Ecto we will use something like Users.Repo.get!(id)
, this of course works, but why do I not need to send/receive
to communicate with the Users.Repo
process? Why can I just call it as simple as referencing the module and function name?
Users
is an OTP Application, where Users.Application
has the Users.Repo
process loaded as children to the Users.Supervisor
process
...
def start(_type, _args) do
children = [
Users.Repo,
]
opts = [strategy: :one_for_one, name: Users.Supervisor]
Supervisor.start_link(children, opts)
end
Users.Repo
gets Ecto.Repo
injected with use Ecto.Repo
and hence default get/3
implementation is delegated to Ecto.Repo.Queryable.get/3
and then down to adapter.execute/5
.
adapter
in turn is already a GenServer
and execute/5
is an interface to the process called behind the scene. That abstraction level is required to encapsulate connection pool, timeouts, error handling, etc for you.