2017-04-19 81 views
8

我正在使用phx 1.3和傘應用程序的新套件產品的體系結構。如何爲許多應用程序構建鳳凰傘框架

我有一個現有的基於鳳凰的企業級WebRTC軟電話(許多按鍵,一個顯示器,多輸入和輸出音頻設備選擇,等等)。 我已經開發了一個與Phoenix的Slack克隆消息應用程序原型。 這兩個應用程序都相當大 我需要將手機與聊天應用程序集成到一個前端,可能只是電話,聊天客戶端和兩者。 我將需要向前移動的聊天客戶端添加很多新功能 我還希望架構支持使用相同的客戶端在呼叫服務器(基於用戶)以及潛在的大量管理員級別設置。 我也可能會在未來添加其他應用程序,如操作面板,日誌查看器,並且列表繼續... 客戶端JS非常簡單,沒有前端框架。我渲染模板服務器端,並通過通道推送HTML。

我想構建這個可插件。相同的端點和數據庫。一個普通的UX。

我想在這個保護傘中會有兩個常見的應用程序,一個用於Phoenix端點和一個控制器,另一個用於主要的Repo和一對模式。我試圖弄清楚爲每個應用程序使用兩個或多個附加應用程序是多麼困難。一個用於上下文和模式,另一個用於控制器,視圖,模板和早午餐資源。可能是另一個第三方API。

爲了使這項工作,我需要在每個應用程序中爲路由器動態分派。一種處理每個應用程序中包含的遷移的方法,可能更多的我還沒有想過。

正如任何人試過這個?有沒有類似結構的開源項目?

回答

8

我在日常工作中使用的elixir應用程序是一款帶13個應用程序的雨傘。

根部是Phoenix端點和頂層路由器,它將請求轉發給其他應用中定義的路由器。

這意味着該應用程序不會拆分爲圖層(網絡/業務/數據),而是分爲垂直域切片。

隨着應用程序在過去12個月中的顯着增長,這已經很好地擴展了。

我有最大的小問題,就是鳳凰路由器轉發到其他路由器時,從請求剝離最主要的路徑,所以我們創建了一個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 

我們管理整個數據庫的遷移在一個單一的應用程序只是爲了簡單,但外生架構是在每個應用程序另行申報。

Here是一個演示一些概念的項目。

+2

謝謝!我喜歡你的'mount'方法。我過去曾經遇到過這個問題。沒有想到你的方法。不過,我用這個'Application.get_env(:app,:routers)|> Enum.map(&(forward「/」,&1))'試了一個快速秒殺''。我把它放在我的主路由器的末端,它似乎工作。你能想到這種方法的任何問題嗎? –

+0

'垂直域切片'聽起來不錯。我已經看到了將persistence/db解壓到它自己的應用程序'apps/db /'中的引用。你對此有何看法? – AdamT

+0

我看到你提到'我們爲了簡單而在一個應用程序中管理整個數據庫的遷移。這個架構有沒有問題? – AdamT

0

我也在研究一個相當大的傘應用程序。而不是維護一個配置了每個應用程序的入口點的文件,我想看看我能否讓它更具動態性。所以我寫了一個看起來像這樣的插件:

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