7stud

7stud

Phoenix.PubSub in an umbrella app -- Phoenix in Action 1.4

I’m working my way through “Phoenix in Action 1.4” for the second time. The instructions have you create an umbrella app with two apps: auction and auction_web, and following the instructions I created the auction_web app with --no-ecto. Unfortunately, --no-ecto seems to be the root cause of continuing PubSub warnings/errors. I was successful squelching the PubSub warnings/errors for a few days while I was working on getting the auction_web app to display a list of items on a web page, but then I moved inside the auction app to create a Postgres database, and when I tried to execute iex -S mix, then PubSub, like a Phoenix, rose from the ashes to bite me again:

...phoenix_apps/second_auction/auction_umbrella $ iex -S mix
...
...
...
> 14:25:30.946 [notice] Application eex exited: :stopped
> ** (Mix) Could not start application auction: Auction.Application.start(:normal, []) returned an error: shutdown: failed to start child: Phoenix.PubSub.Supervisor
>     ** (EXIT) shutdown: failed to start child: Phoenix.PubSub.PG2
>         ** (EXIT) shutdown: failed to start child: Auction.PubSub.Adapter
>             ** (EXIT) exited in: :gen_server.call(Phoenix.PubSub, {:join_local, Auction.PubSub.Adapter, #PID<0.4916.0>}, :infinity)
>                 ** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started

Am I in the wrong directory? If I change into apps/auction/ and try again, I get:

auction_umbrella/apps/auction$ iex -S mix
Generated auction app
15:13:27.742 [notice] Application auction exited: exited in: Auction.Application.start(:normal, [])
    ** (EXIT) an exception was raised:
        ** (ArgumentError) The module Phoenix.PubSub was given as a child to a supervisor but it does not exist
            (elixir 1.16.0-rc.1) lib/supervisor.ex:797: Supervisor.init_child/1
            (elixir 1.16.0-rc.1) lib/enum.ex:1700: Enum."-map/2-lists^map/1-1-"/2
            (elixir 1.16.0-rc.1) lib/supervisor.ex:783: Supervisor.init/2
            (elixir 1.16.0-rc.1) lib/supervisor.ex:707: Supervisor.start_link/2
            (kernel 9.1) application_master.erl:293: :application_master.start_it_old/4
15:13:27.747 [notice] Application ecto_sql exited: :stopped
15:13:27.747 [notice] Application postgrex exited: :stopped
15:13:27.747 [notice] Application db_connection exited: :stopped
15:13:27.747 [notice] Application ecto exited: :stopped
15:13:27.748 [notice] Application decimal exited: :stopped
15:13:27.748 [notice] Application telemetry exited: :stopped
15:13:27.748 [notice] Application eex exited: :stopped
** (Mix) Could not start application auction: exited in: Auction.Application.start(:normal, [])
    ** (EXIT) an exception was raised:
        ** (ArgumentError) The module Phoenix.PubSub was given as a child to a supervisor but it does not exist
            (elixir 1.16.0-rc.1) lib/supervisor.ex:797: Supervisor.init_child/1
            (elixir 1.16.0-rc.1) lib/enum.ex:1700: Enum."-map/2-lists^map/1-1-"/2
            (elixir 1.16.0-rc.1) lib/supervisor.ex:783: Supervisor.init/2
            (elixir 1.16.0-rc.1) lib/supervisor.ex:707: Supervisor.start_link/2
            (kernel 9.1) application_master.erl:293: :application_master.start_it_old/4

And, if I switch into apps/auction_web/ I get:

auction_umbrella/apps/auction_web$ iex -S mix
Erlang/OTP 26 [erts-14.1.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit]

Interactive Elixir (1.16.0-rc.1) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> 

I’m using:

Phoenix 1.7.10
Erlang/OTP 26.1.2
Elixir 1.16.0-rc.1-otp-26

Here are all the places where the name PubSub occurs in my umbrella app:

  1. apps/auction/lib/auction/application.ex:
defmodule Auction.Application do
  # See https://hexdocs.pm/elixir/Application.html
  # for more information on OTP Applications
  @moduledoc false

  use Application

  @impl true
  def start(_type, _args) do
    children = [
      # Starts a worker by calling: Auction.Worker.start_link(arg)
      # {Auction.Worker, arg}
      {Phoenix.PubSub, name: Auction.PubSub},
      {Auction.Repo, []}
    ]

    # See https://hexdocs.pm/elixir/Supervisor.html
    # for other strategies and supported options
    opts = [strategy: :one_for_one, name: Auction.Supervisor]
    Supervisor.start_link(children, opts)
  end
end
  1. apps/auction_web/lib/auction_web/application.ex:
defmodule AuctionWeb.Application do
  # See https://hexdocs.pm/elixir/Application.html
  # for more information on OTP Applications
  @moduledoc false

  use Application

  @impl true
  def start(_type, _args) do
    children = [
      {Phoenix.PubSub, name: AuctionWeb.PubSub},
      AuctionWeb.Telemetry,
      # Start a worker by calling: AuctionWeb.Worker.start_link(arg)
      # {AuctionWeb.Worker, arg},
      # Start to serve requests, typically the last entry
      AuctionWeb.Endpoint
    ]

    # See https://hexdocs.pm/elixir/Supervisor.html
    # for other strategies and supported options
    opts = [strategy: :one_for_one, name: AuctionWeb.Supervisor]
    Supervisor.start_link(children, opts)
  end

  # Tell Phoenix to update the endpoint configuration
  # whenever the application is updated.
  @impl true
  def config_change(changed, _new, removed) do
    AuctionWeb.Endpoint.config_change(changed, removed)
    :ok
  end
end
  1. auction_umbrella/config/config.exs:
# This file is responsible for configuring your umbrella
# and **all applications** and their dependencies with the
# help of the Config module.
#
# Note that all applications in your umbrella share the
# same configuration and dependencies, which is why they
# all use the same configuration file. If you want different
# configurations or dependencies per app, it is best to
# move said applications out of the umbrella.
import Config

# Stuff I added:

config :auction, ecto_repos: [Auction.Repo]

config :auction, Auction.Repo,
  database: "auction",
  username: "7stud",
  password: "",
  hostname: "localhost",
  port: "5432"

##############################

config :auction_web,
  generators: [context_app: false]

# Configures the endpoint
config :auction_web, AuctionWeb.Endpoint,
  url: [host: "localhost"],
  adapter: Phoenix.Endpoint.Cowboy2Adapter,
  render_errors: [
    formats: [html: AuctionWeb.ErrorHTML, json: AuctionWeb.ErrorJSON],
    layout: false
  ],
  pubsub_server: AuctionWeb.PubSub,
  live_view: [signing_salt: "cOmLEVHn"]

# Configure esbuild (the version is required)
config :esbuild,
  version: "0.17.11",
  default: [
    args:
      ~w(js/app.js --bundle --target=es2017 --outdir=../priv/static/assets --external:/fonts/* --external:/images/*),
    cd: Path.expand("../apps/auction_web/assets", __DIR__),
    env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
  ]

# Configure tailwind (the version is required)
config :tailwind,
  version: "3.3.2",
  default: [
    args: ~w(
      --config=tailwind.config.js
      --input=css/app.css
      --output=../priv/static/assets/app.css
    ),
    cd: Path.expand("../apps/auction_web/assets", __DIR__)
  ]

# Sample configuration:
#
#     config :logger, :console,
#       level: :info,
#       format: "$date $time [$level] $metadata$message\n",
#       metadata: [:user_id]
#
import Config

# Configures Elixir's Logger
config :logger, :console,
  format: "$time $metadata[$level] $message\n",
  metadata: [:request_id]

# Use Jason for JSON parsing in Phoenix
config :phoenix, :json_library, Jason

# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{config_env()}.exs"

Most Liked

al2o3cr

al2o3cr

What was involved in that? It shouldn’t have needed any “squelching”…

In particular, did you change anything in mix.exs like applications? That list is maintained automatically nowadays, but you’ll still see a lot of old advice to fiddle with it and it can flat-out break your app if misconfigured.


This error is coming from PG2Worker, which is trying to connect to a pg process in pg_join:

https://github.com/phoenixframework/phoenix_pubsub/blob/507cea298bbfce46eba0d410fe4037dfe61923d8/lib/phoenix/pubsub/pg2.ex#L118

https://github.com/erlang/otp/blob/2bcabe9e94d6328767729d8ff4def9bc229955ab/lib/kernel/src/pg.erl#L133-L136

The message suggests that the application supervisor for phoenix_pubsub didn’t start correctly, since that’s what makes the pg process:

https://github.com/phoenixframework/phoenix_pubsub/blob/507cea298bbfce46eba0d410fe4037dfe61923d8/lib/phoenix/pubsub/application.ex#L11-L13


On the other hand, this error suggests that running the app in apps/auction isn’t loading Phoenix at all. :thinking:


A general tip: having separate PubSub instances is explicitly against the design goal of the Phoenix pubsub system. The idea is that code in the “not-web” application can’t explicitly call code in the “web” application (because the dependencies don’t point that way), but it can push messages into pubsub that are handled by the “web” application.

Where Next?

Popular in Questions Top

nobody
How to bind a phoenix app to a specific ip address? could not find anything about that, nowhere, unfortunately, but for me this is quite...
New
sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
New
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID&lt;0.412.0&gt; terminating ** (Postgrex.Error) FATAL...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
script
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this "1000" What is the ...
New
jaysoifer
Is there a way to rollback a specific migration and only that one (“skipping” all the other ones)? Would mix ecto.rollback -v 200809061...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New

Other popular topics Top

lastday4you
I wanted to check elixir version in phoenix because i found that my elixir is 1.5 but when i use Enum.chunk_by it said the function is un...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 43757 214
New
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 54120 245
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement