При выполнении запросов к базе данных с помощью Ecto мы будем использовать что-то вроде Users.Repo.get!(id)
, это, конечно, работает, но почему мне не нужно send/receive
для связи с процессом Users.Repo
? Почему я могу просто назвать это просто ссылкой на модуль и имя функции?
Users
— это OTP-приложение, в котором Users.Application
процесс Users.Repo
загружается как дочерний элемент процесса Users.Supervisor
.
...
def start(_type, _args) do
children = [
Users.Repo,
]
opts = [strategy: :one_for_one, name: Users.Supervisor]
Supervisor.start_link(children, opts)
end
Users.Repo
получает Ecto.Repo
инъекцию с помощью использования Ecto.Repo , и, следовательно, реализация get/3
по умолчанию делегируется в Ecto.Repo.Queryable.get/3 , а затем переходит в adapter.execute/5.
adapter
, в свою очередь, уже является GenServer, а execute/5
является интерфейсом к процессу, вызываемому за сценой. Этот уровень абстракции необходим для инкапсуляции пула соединений, тайм-аутов, обработки ошибок и т. д.