How to structure the Phoenix umbrella concept for many applications

I play with architecture for a new set of products using phx 1.3 and umbrella applications.

I have an existing enterprise-class WebRTC softphone based on Phoenix (many keys, display, selection of several input and output audio devices, etc.). I developed a prototype Slack clone messaging app with Phoenix. Both applications are quite large. I need to integrate the phone with the chat application into one interface, which can be either just a phone or a chat client, and both. I will need to add many new features for the chat client moving forward. I also want the architecture to support the use of the same client to provide additional settings on the call server (user-based) and, possibly, a large number of administrator level settings. I can also add other applications in the future, for example, the control panel, the log viewer, and the list goes on ... The client side of JS is quite simple, and not an interface platform. I process the server side of the templates and push the html through the pipes.

I would like to build this plugin. Same endpoint and database. One common UX.

I think there will be two common applications in the umbrella: one for the Phoenix endpoint and several controllers, and the other for the main repo and a couple of circuits. I am trying to understand how difficult it will be to use two or more additional applications for each application. One for context and schema, one for controllers, views, templates, and a brunch resource. Perhaps another for third-party APIs.

To make this work, I will need dynamic sending for routers in each of the applications. A method for handling the migrations contained in each of the applications, and probably more, which I have not thought about.

How did you try all this? Are there open source projects with a similar structure?

+8
elixir phoenix-framework
source share
2 answers

The elixir application that I work with every day is an umbrella with 13 applications.

The root folder contains the Phoenix endpoint and the top-level router, which redirects requests to routers defined in other applications.

This means that the application is not divided into layers (web / business / data), but rather into vertical slices of the domain.

This has improved significantly since the application has grown significantly over the past 12 months.

The biggest thing I had was that Phoenix routers share the leading path from the request when forwarding to other routers, so we created a mount macro for use with the Plug router, which keeps the request path unchanged:

 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 

and mount:

 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 

We manage the migration of the entire database in one application for simplicity only, but Ecto Schemas are declared separately in each application.

Here is a project demonstrating some of the concepts.

+8
source share

I am also working on a rather large umbrella application. Instead of supporting a file with customized entry points for each application, I wanted to see if I could make it more dynamic. Therefore, I wrote firmware that looks like this:

 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 

I added this plug to the end point. And then it's up to the called module, which again can add a router or something similar to the endpoint using Plug.Builder

You can see the full example here: https://github.com/tverlaan/location_routing

0
source share

All Articles