Как структурировать каркас зонтика Phoenix для многих приложений

Я играю с архитектурой для нового набора продуктов с использованием phx 1.3 и зонтичных приложений.

У меня есть программный телефон WebRTC корпоративного класса на базе Phoenix (множество клавиш, дисплей, несколько аудио-устройств ввода и вывода и т. Д.). Я разработал прототип приложения для клонирования сообщений Slack с помощью Phoenix. Оба приложения довольно большие, мне нужно интегрировать телефон с приложением чата в один интерфейс, который может быть либо просто телефоном, либо клиентом чата, и обоими. Мне нужно будет добавить много новых функций в чат-клиент. Я также хочу, чтобы архитектура поддерживала использование одного и того же клиента для предоставления дополнительных настроек на сервере вызовов (на основе пользователей) и, возможно, большого количества настроек уровня администратора. Возможно, в будущем я добавлю и другие приложения, такие как панель оператора, средство просмотра журналов, и этот список можно продолжить... JS на стороне клиента довольно прост, нет фреймворка. Я отрисовываю шаблоны на стороне сервера и выдвигаю html по каналам.

Я хотел бы построить этот плагин. Та же конечная точка и база данных. Один общий UX.

Я думаю, что в центре будет два общих приложения: одно для конечной точки Phoenix и пара контроллеров, а другое для основного репо и пара схем. Я пытаюсь понять, насколько сложно будет использовать два или более дополнительных приложения для каждого приложения. Один для контекста и схемы, другой для контроллеров, представлений, шаблонов и ресурсов позднего завтрака. Возможно, другой для сторонних API.

Чтобы это работало, мне понадобится динамическая рассылка для маршрутизаторов в каждом приложении. Метод для обработки миграций, содержащихся в каждом из приложений, и, вероятно, больше, о чем я еще не думал.

Как кто-нибудь пробовал это? Есть ли проекты с открытым исходным кодом с похожей структурой?

2 ответа

Приложение с эликсиром, с которым я работаю каждый день, представляет собой зонтик с 13 приложениями.

В корне находится конечная точка Phoenix и маршрутизатор верхнего уровня, который пересылает запросы маршрутизаторам, определенным в других приложениях.

Это означает, что приложение не разбито на слои (сеть / бизнес / данные), а скорее на вертикальные доменные срезы.

Это хорошо масштабируется, так как приложение значительно выросло за последние 12 месяцев.

Самый большой недостаток, который у меня был, заключается в том, что маршрутизаторы Phoenix удаляют начальный путь из запроса при пересылке на другие маршрутизаторы, поэтому мы создали mount макрос для использования с Plug маршрутизатор, который сохраняет путь запроса без изменений:

defmodule MyApp.Router do
  @moduledoc """
  Top level routing to each of the sub-systems
  """

  use Plug.Router

  plug :match
  plug :dispatch

  mount "/events/*_", Events.Router
  mount "/report/*_", Report.Router
  mount "/stats/*_",  Stats.Router
  mount "/auth/*_",   Auth.Router
end

и смонтировать:

defmacro mount(path, router, opts \\ []) do
  quote do
    @opts unquote(router).init(unquote(opts))
    match unquote(path), do: unquote(router).call(var!(conn), @opts)
  end
end

Мы просто осуществляем миграцию всей базы данных в одном приложении, но схемы Ecto объявляются в каждом приложении отдельно.

Вот проект, который демонстрирует некоторые концепции.

Я также работаю над довольно большим зонтичным приложением. Вместо того, чтобы поддерживать файл с настроенными точками входа для каждого приложения, я хотел посмотреть, смогу ли я сделать его более динамичным. Поэтому я написал плагин, который выглядит следующим образом:

def call(%{path_info: [path|_]} = conn, opts) do
  path = path |> String.downcase() |> Macro.camelize()
  module =
    try do
      Module.safe_concat [LocationRouting, path, Location]
    rescue
      _ -> nil
    end
  if module do
    module.call(conn, opts)
  else
    conn
  end
end

Я добавил этот штекер в конечную точку. И затем это до вызываемого модуля, который снова способен добавить маршрутизатор или что-то похожее на конечную точку с помощью Plug.Builder

Вы можете посмотреть полный пример здесь: https://github.com/tverlaan/location_routing

Другие вопросы по тегам