dbr.sh
Issues with Project Structure / Ecto Config
Hello! I’m writing a game app and am running into a couple issues that make me feel like I’m not organizing my project correctly. I’d greatly appreciate any pointers here. Thanks in advance.
I’m building an app where users connect over Phoenix channels, spinning up player state processes (GenServers) that connect to a game state process (also GenServer). The organization is as follows:
/state_app #genserver modules that manage player/game state
/supervisor #supervisor module to spin up game/player/registry supervisors
/websocket_server #phoenix, only used for websockets/channels
/ecto_repo #connects to postgres for persistance
Ideally I just run the state_app and everything starts up/is supervised by calls to the supervisor module.
I’m running into a couple issues:
-
I’m having trouble getting the supervisor module to manage the phoenix channel endpoint. I can point it to my endpoint module and start things up, but nothing gets served on :4000. :observer shows the processes running. I put
config :phoenix, :serve_endpoints, truein my dev.exs but no luck. Currently I have to start both the game state withiex -S mixand then the phoenix server withmix phx.serverin a separate window. -
I have to put all my Ecto repo config into both the
state_appconfig.exs andwebsocket_serverconfig.exs, since I’m starting them separately. I think it’s because the configs for dependencies aren’t used? Does this mean I want to use an umbrella app?
I was hoping that the ecto repo / socket server would be stand-alone and I could minimize coupling in my code. Is my application just better suited to an umbrella app, am I organizing things incorrectly, or is it just configuration issues? Thanks much.
Most Liked
josevalim
Each application should have its own supervision tree. Then, if the phoenix app depends on the supervisor app, you need to list the supervisor app as a dependency in your mix.exs file. If you are using umbrella, this is a matter of adding {:supervisor, in_umbrella: true} to deps. By doing this, Elixir will automatically start the supervisor app and its supervision tree before it starts the Phoenix one.
I think it would be better if you actually use the shared configuration suggestion for umbrellas. Run mix phx.new foo --umbrella and you will see how it is designed. But in a nutshell every child application has a line in their mix.exs that points to the umbrella config files. As I said, the goal of the umbrella is to share deps and config, so if you keep them in separate applications, it gives the impression they are not shared while they do. Unifying everything in the config folders of the umbrella will be clearer.
OvermindDL1
Just running mix phx.server should start everything, the phoenix server and your game state (assuming everything is wired via your application’s supervisor properly). Or if you want the console then iex -S mix phx.server.
I personally don’t like umbrella apps, I prefer dependencies. However, why not just pass in the main Ecto Repo through everything, and if you start Ecto before starting the websocket server then there is no serialization issue.
As for umbrella’s, perhaps others could talk about those, I find them horribly messy, always have since my old erlang days so I’m probably biased. ^.^;
josevalim
Is this the proper relationship? Shouldn’t the phoenix.channel start the supervisor because it needs it to work and not the opposite?
The default configuration for umbrellas is to share all configuration from all projects. I am assuming that you have opted-out from this behaviour explicitly? You could use import_config on both apps and make them import the ecto configuration from state_app but given that you are running into issues, asking if using umbrellas is the way to go is indeed wise.
Umbrellas were designed for apps that share the same dependencies and configuration. So if you want to configure some apps differently or you want to update a certain dependency for one app or not the other, then it is indeed best to drop them.
The good news is that you can still keep a very similar structure. You can keep all projects in the same repository and use :path instead of :in_umbrella for your deps. The main difference is that you are explicitly saying those things are not coupled at the config and dependencies level, so other approaches may feel more natural.
dimitarvp
Nothing wrong with having apps called data (structures and integrations with DBs and various storage backends), domain (or something similar that expresses business logic), then probably web and api that are the server-side rendering app, JSON app etc. etc.
Used that several times, it provides a very neat separation of concerns as long as you do explicit dependency management ({my_app, in_umbrella: true}).
Using path dependencies in this case is a very leaky and lame way of doing it. What if I have 5 of my apps in totally different directories both in dev and prod?








